Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add REA filters #260

Open
wants to merge 4 commits into
base: 1.21
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public class BlockContentRegistries {

return DataResult.success(block);
}))
.validator(block -> block.getDefaultState().contains(Properties.AXIS))
.build();

/**
Expand Down
3 changes: 3 additions & 0 deletions library/data/registry_entry_attachment/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ qslModule {
impl("resource_loader")
impl("networking")
}
data {
impl("tags")
}
management {
compileOnly("command")
testmodOnly("command")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -287,6 +288,26 @@ default Optional<V> get(R entry) {
*/
boolean remove(TagKey<R> tag);

/**
* The entry validation can prevent entries from being shown in the attachment.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Being shown" is misleading; it implies that this validator will silently drop entries, but you seem to throw a hard exception when an entry that fails the predicate is added:

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));
}

* 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<R> 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<R> entryFilter() {
return TagKey.of(this.registry().getKey(), this.id().withPath(s -> "filter/" + s));
}

/**
* {@return this attachment's "value associated with entry" event}
*/
Expand Down Expand Up @@ -444,6 +465,8 @@ final class Builder<R, V> {
private @Nullable V defaultValue;
private @Nullable DefaultValueProvider<R, V> defaultValueProvider;

private Predicate<R> validator = o -> true;

private Builder(Registry<R> registry, Identifier id, Class<V> valueClass, Codec<V> codec) {
this.registry = registry;
this.id = id;
Expand Down Expand Up @@ -501,6 +524,19 @@ public Builder<R, V> defaultValueProvider(@Nullable DefaultValueProvider<R, V> d
return this;
}

/**
* Sets the registry entry validator for the attachment.
*
* @see RegistryEntryAttachment#entryValidator()
*
* @param validator the entry validator
* @return this builder
*/
public Builder<R, V> validator(Predicate<R> validator) {
this.validator = validator;
return this;
}

/**
* Builds a new attachment.
*
Expand All @@ -510,10 +546,10 @@ public RegistryEntryAttachment<R, V> build() {
RegistryEntryAttachment<R, V> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -33,8 +35,8 @@ public final class ComputedDefaultRegistryEntryAttachmentImpl<R, V> extends Regi

private final @NotNull DefaultValueProvider<R, V> defaultValueProvider;

public ComputedDefaultRegistryEntryAttachmentImpl(Registry<R> registry, Identifier id, Class<V> valueClass, Codec<V> codec, Side side, @NotNull DefaultValueProvider<R, V> defaultValueProvider) {
super(registry, id, valueClass, codec, side);
public ComputedDefaultRegistryEntryAttachmentImpl(Registry<R> registry, Identifier id, Class<V> valueClass, Codec<V> codec, Side side, @NotNull DefaultValueProvider<R, V> defaultValueProvider, Predicate<R> validator) {
super(registry, id, valueClass, codec, side, validator);
this.defaultValueProvider = defaultValueProvider;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,8 +29,8 @@ public final class ConstantDefaultRegistryEntryAttachmentImpl<R, V> extends Regi
private final @Nullable V defaultValue;

public ConstantDefaultRegistryEntryAttachmentImpl(Registry<R> registry, Identifier id, Class<V> valueClass,
Codec<V> codec, Side side, @Nullable V defaultValue) {
super(registry, id, valueClass, codec, side);
Codec<V> codec, Side side, @Nullable V defaultValue, Predicate<R> validator) {
super(registry, id, valueClass, codec, side, validator);

if (defaultValue != null) {
var encoded = this.codec.encodeStart(JsonOps.INSTANCE, defaultValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<R, V> implements RegistryEntryAttachment<R, V> {
Expand All @@ -44,14 +46,16 @@ public abstract class RegistryEntryAttachmentImpl<R, V> implements RegistryEntry
protected final Event<TagValueAdded<R, V>> tagValueAddedEvent;
protected final Event<ValueRemoved<R>> valueRemovedEvent;
protected final Event<TagValueRemoved<R>> tagValueRemovedEvent;
protected final Predicate<R> validator;

public RegistryEntryAttachmentImpl(Registry<R> registry, Identifier id, Class<V> valueClass, Codec<V> codec,
Side side) {
Side side, Predicate<R> 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) {
Expand Down Expand Up @@ -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;
Expand All @@ -130,6 +138,12 @@ public Set<R> keySet() {
Set<R> 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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -213,6 +231,11 @@ public boolean remove(TagKey<R> tag) {
return false;
}

@Override
public Predicate<R> entryValidator() {
return this.validator;
}

@Override
public Event<ValueAdded<R, V>> valueAddedEvent() {
return this.valueAddedEvent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -47,8 +45,6 @@ public class ItemContentRegistriesInitializer implements ModInitializer {

public static final Map<ItemConvertible, Float> INITIAL_COMPOST_CHANCE = ImmutableMap.copyOf(ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE);

public static final TagKey<Item> FUEL_FILTERS = TagKey.of(RegistryKeys.ITEM, new Identifier("quilt", "fuel_filters"));

private static boolean collectInitialTags = false;

@Override
Expand All @@ -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);
Expand Down