Skip to content

Commit

Permalink
Rework how boilerplate loader predicates are registered
Browse files Browse the repository at this point in the history
Instead of having 3 extra fields in the class, they are all registered automatically in PredicateLoader. In addition, we now have RegistrySetLoader and FallbackLoader to handle other common predicate elements
Static methods were added to the interface to construct the common type as its less clear the loader can handle that
Semantic change: all boilerplate loader types are registered under mantle, this makes the fallback registry work better.
  • Loading branch information
KnightMiner committed Mar 23, 2024
1 parent dc252ce commit bc76247
Show file tree
Hide file tree
Showing 20 changed files with 474 additions and 497 deletions.
31 changes: 2 additions & 29 deletions src/main/java/slimeknights/mantle/Mantle.java
Expand Up @@ -33,19 +33,13 @@
import slimeknights.mantle.config.Config;
import slimeknights.mantle.data.predicate.block.BlockPredicate;
import slimeknights.mantle.data.predicate.block.BlockPropertiesPredicate;
import slimeknights.mantle.data.predicate.block.SetBlockPredicate;
import slimeknights.mantle.data.predicate.block.TagBlockPredicate;
import slimeknights.mantle.data.predicate.damage.DamageSourcePredicate;
import slimeknights.mantle.data.predicate.damage.SourceAttackerPredicate;
import slimeknights.mantle.data.predicate.damage.SourceMessagePredicate;
import slimeknights.mantle.data.predicate.entity.EntitySetPredicate;
import slimeknights.mantle.data.predicate.entity.HasEnchantmentEntityPredicate;
import slimeknights.mantle.data.predicate.entity.LivingEntityPredicate;
import slimeknights.mantle.data.predicate.entity.MobTypePredicate;
import slimeknights.mantle.data.predicate.entity.TagEntityPredicate;
import slimeknights.mantle.data.predicate.item.ItemPredicate;
import slimeknights.mantle.data.predicate.item.ItemSetPredicate;
import slimeknights.mantle.data.predicate.item.ItemTagPredicate;
import slimeknights.mantle.datagen.MantleFluidTagProvider;
import slimeknights.mantle.datagen.MantleFluidTooltipProvider;
import slimeknights.mantle.datagen.MantleTags;
Expand Down Expand Up @@ -134,29 +128,15 @@ private void register(RegisterEvent event) {
// predicates
{
// block predicates
BlockPredicate.LOADER.register(getResource("and"), BlockPredicate.AND);
BlockPredicate.LOADER.register(getResource("or"), BlockPredicate.OR);
BlockPredicate.LOADER.register(getResource("inverted"), BlockPredicate.INVERTED);
BlockPredicate.LOADER.register(getResource("any"), BlockPredicate.ANY.getLoader());
BlockPredicate.LOADER.register(getResource("requires_tool"), BlockPredicate.REQUIRES_TOOL.getLoader());
BlockPredicate.LOADER.register(getResource("set"), SetBlockPredicate.LOADER);
BlockPredicate.LOADER.register(getResource("tag"), TagBlockPredicate.LOADER);
BlockPredicate.LOADER.register(getResource("block_properties"), BlockPropertiesPredicate.LOADER);

// item predicates
ItemPredicate.LOADER.register(getResource("and"), ItemPredicate.AND);
ItemPredicate.LOADER.register(getResource("or"), ItemPredicate.OR);
ItemPredicate.LOADER.register(getResource("inverted"), ItemPredicate.INVERTED);
ItemPredicate.LOADER.register(getResource("any"), ItemPredicate.ANY.getLoader());
ItemPredicate.LOADER.register(getResource("set"), ItemSetPredicate.LOADER);
ItemPredicate.LOADER.register(getResource("tag"), ItemTagPredicate.LOADER);
// make sure the item predicate registry is loaded, nothing to register here
ItemPredicate.ANY.getLoader();

// entity predicates
LivingEntityPredicate.LOADER.register(getResource("and"), LivingEntityPredicate.AND);
LivingEntityPredicate.LOADER.register(getResource("or"), LivingEntityPredicate.OR);
LivingEntityPredicate.LOADER.register(getResource("inverted"), LivingEntityPredicate.INVERTED);
// simple
LivingEntityPredicate.LOADER.register(getResource("any"), LivingEntityPredicate.ANY.getLoader());
LivingEntityPredicate.LOADER.register(getResource("fire_immune"), LivingEntityPredicate.FIRE_IMMUNE.getLoader());
LivingEntityPredicate.LOADER.register(getResource("water_sensitive"), LivingEntityPredicate.WATER_SENSITIVE.getLoader());
LivingEntityPredicate.LOADER.register(getResource("on_fire"), LivingEntityPredicate.ON_FIRE.getLoader());
Expand All @@ -167,8 +147,6 @@ private void register(RegisterEvent event) {
LivingEntityPredicate.LOADER.register(getResource("underwater"), LivingEntityPredicate.UNDERWATER.getLoader());
LivingEntityPredicate.LOADER.register(getResource("raining_at"), LivingEntityPredicate.RAINING.getLoader());
// property
LivingEntityPredicate.LOADER.register(getResource("set"), EntitySetPredicate.LOADER);
LivingEntityPredicate.LOADER.register(getResource("tag"), TagEntityPredicate.LOADER);
LivingEntityPredicate.LOADER.register(getResource("mob_type"), MobTypePredicate.LOADER);
LivingEntityPredicate.LOADER.register(getResource("has_enchantment"), HasEnchantmentEntityPredicate.LOADER);
// register mob types
Expand All @@ -179,10 +157,6 @@ private void register(RegisterEvent event) {
MobTypePredicate.MOB_TYPES.register(new ResourceLocation("water"), MobType.WATER);

// damage predicates
DamageSourcePredicate.LOADER.register(getResource("and"), DamageSourcePredicate.AND);
DamageSourcePredicate.LOADER.register(getResource("or"), DamageSourcePredicate.OR);
DamageSourcePredicate.LOADER.register(getResource("inverted"), DamageSourcePredicate.INVERTED);
DamageSourcePredicate.LOADER.register(getResource("any"), DamageSourcePredicate.ANY.getLoader());
// vanilla properties
DamageSourcePredicate.LOADER.register(getResource("projectile"), DamageSourcePredicate.PROJECTILE.getLoader());
DamageSourcePredicate.LOADER.register(getResource("explosion"), DamageSourcePredicate.EXPLOSION.getLoader());
Expand All @@ -198,7 +172,6 @@ private void register(RegisterEvent event) {
DamageSourcePredicate.LOADER.register(getResource("melee"), DamageSourcePredicate.MELEE.getLoader());
DamageSourcePredicate.LOADER.register(getResource("message"), SourceMessagePredicate.LOADER);
DamageSourcePredicate.LOADER.register(getResource("attacker"), SourceAttackerPredicate.LOADER);

}
}
else if (key == Registry.BLOCK_ENTITY_TYPE_REGISTRY) {
Expand Down

This file was deleted.

@@ -0,0 +1,103 @@
package slimeknights.mantle.data.predicate;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import lombok.RequiredArgsConstructor;
import net.minecraft.resources.ResourceLocation;
import slimeknights.mantle.Mantle;
import slimeknights.mantle.data.loadable.record.RecordLoadable;
import slimeknights.mantle.util.JsonHelper;

import java.util.function.Function;

/** Predicate registry that upon failure to find a predicate type will fallback to the fallback type */
public class FallbackPredicateRegistry<T,F> extends PredicateRegistry<T> {
private final Function<T,F> getter;
private final PredicateRegistry<F> fallback;
private final RecordLoadable<FallbackPredicate> fallbackLoader;

/**
* Creates a new instance
* @param defaultInstance Default instance, typically expected to be an any predicate.
*/
public FallbackPredicateRegistry(IJsonPredicate<T> defaultInstance, PredicateRegistry<F> fallback, Function<T,F> getter, String fallbackName) {
super(defaultInstance);
this.fallback = fallback;
this.getter = getter;
this.fallbackLoader = RecordLoadable.create(fallback.directField(fallbackName + "_type", p -> p.predicate), FallbackPredicate::new);
this.register(Mantle.getResource(fallbackName), fallbackLoader);
}

/** Creates a fallback predicate instance */
public IJsonPredicate<T> fallback(IJsonPredicate<F> predicate) {
return new FallbackPredicate(predicate);
}

@Override
public IJsonPredicate<T> convert(JsonElement element, String key) throws JsonSyntaxException {
if (defaultInstance != null && element.isJsonNull()) {
return defaultInstance;
}
// identify type key, and the object we will load from
JsonObject object;
ResourceLocation type;
if (element.isJsonObject()) {
object = element.getAsJsonObject();
type = JsonHelper.getResourceLocation(object, "type");
} else if (compact && element.isJsonPrimitive()) {
EMPTY_OBJECT.entrySet().clear();
object = EMPTY_OBJECT;
type = JsonHelper.convertToResourceLocation(object, "type");
} else {
throw new JsonSyntaxException("Invalid JSON for " + getClass().getSimpleName() + " at " + key + ", must be a JSON object" + (compact ? " or a string" : ""));
}
// see if we have a primary loader, if so parse that
IGenericLoader<? extends IJsonPredicate<T>> loader = loaders.getValue(type);
if (loader != null) {
return loader.deserialize(object);
}
// primary loader failed, try a fallback loader
return new FallbackPredicate(this.fallback.convert(element, key));
}

@SuppressWarnings("unchecked")
@Override
public JsonElement serialize(IJsonPredicate<T> src) {
// write the fallback directly to JSON instead of as a nested type
if (src instanceof NestedPredicate<?>) {
return this.fallback.serialize(((NestedPredicate<F>)src).predicate());
}
return super.serialize(src);
}

private interface NestedPredicate<F> {
IJsonPredicate<F> predicate();
}

/** Predicate matching another predicate type */
@RequiredArgsConstructor
public class FallbackPredicate implements IJsonPredicate<T>, NestedPredicate<F> {
private final IJsonPredicate<F> predicate;

@Override
public IJsonPredicate<F> predicate() {
return predicate;
}

@Override
public boolean matches(T input) {
return predicate.matches(getter.apply(input));
}

@Override
public IJsonPredicate<T> inverted() {
return invert(this);
}

@Override
public IGenericLoader<? extends IJsonPredicate<T>> getLoader() {
return fallbackLoader;
}
}
}
@@ -1,5 +1,6 @@
package slimeknights.mantle.data.predicate;

import slimeknights.mantle.data.registry.GenericLoaderRegistry.IGenericLoader;
import slimeknights.mantle.data.registry.GenericLoaderRegistry.IHaveLoader;

/** Generic interface for predicate based JSON loaders */
Expand All @@ -9,4 +10,7 @@ public interface IJsonPredicate<I> extends IHaveLoader {

/** Inverts the given predicate */
IJsonPredicate<I> inverted();

@Override
IGenericLoader<? extends IJsonPredicate<I>> getLoader();
}

This file was deleted.

This file was deleted.

0 comments on commit bc76247

Please sign in to comment.