Fix TagEmptyCondition by passing tag context into conditional and recipe deserializers. (#8546)

This commit is contained in:
Technici4n authored and GitHub committed 2022-04-02 00:09:20 -07:00
1 parent 1f031ad2c3
commit 87c4f90fb2
21 files changed
+473 -22

No files matched your search

@@ -29,17 +29,26 @@ public class ConditionalAdvancement
return new Builder();
}
/**
* @deprecated Please use {@linkplain #processConditional(JsonObject, ICondition.IContext) the more general overload}.
*/
@Deprecated(forRemoval = true, since = "1.18.2")
@Nullable
public static JsonObject processConditional(JsonObject json) {
return processConditional(json, ICondition.IContext.EMPTY);
}
/**
* Processes the conditional advancement during loading.
* @param json The incoming json from the advancement file.
* @return The advancement that passed the conditions, or null if none did.
*/
@Nullable
public static JsonObject processConditional(JsonObject json) {
public static JsonObject processConditional(JsonObject json, ICondition.IContext context) {
JsonArray entries = GsonHelper.getAsJsonArray(json, "advancements", null);
if (entries == null)
{
return CraftingHelper.processConditions(json, "conditions") ? json : null;
return CraftingHelper.processConditions(json, "conditions", context) ? json : null;
}
int idx = 0;
@@ -47,7 +56,7 @@ public class ConditionalAdvancement
{
if (!ele.isJsonObject())
throw new JsonSyntaxException("Invalid advancement entry at index " + idx + " Must be JsonObject");
if (CraftingHelper.processConditions(GsonHelper.getAsJsonArray(ele.getAsJsonObject(), "conditions")))
if (CraftingHelper.processConditions(GsonHelper.getAsJsonArray(ele.getAsJsonObject(), "conditions"), context))
return GsonHelper.getAsJsonObject(ele.getAsJsonObject(), "advancement");
idx++;
}
@@ -65,9 +65,15 @@ public class ConditionalRecipe
return (Class<G>)cls;
}
@SuppressWarnings("unchecked") // We return a nested one, so we can't know what type it is.
@Override
public T fromJson(ResourceLocation recipeId, JsonObject json)
{
return fromJson(recipeId, json, ICondition.IContext.EMPTY);
}
@SuppressWarnings("unchecked") // We return a nested one, so we can't know what type it is.
@Override
public T fromJson(ResourceLocation recipeId, JsonObject json, ICondition.IContext context)
{
JsonArray items = GsonHelper.getAsJsonArray(json, "recipes");
int idx = 0;
@@ -75,7 +81,7 @@ public class ConditionalRecipe
{
if (!ele.isJsonObject())
throw new JsonSyntaxException("Invalid recipes entry at index " + idx + " Must be JsonObject");
if (CraftingHelper.processConditions(GsonHelper.getAsJsonArray(ele.getAsJsonObject(), "conditions")))
if (CraftingHelper.processConditions(GsonHelper.getAsJsonArray(ele.getAsJsonObject(), "conditions"), context))
return (T)RecipeManager.fromJson(recipeId, GsonHelper.getAsJsonObject(ele.getAsJsonObject(), "recipe"));
idx++;
}
@@ -199,12 +199,30 @@ public class CraftingHelper
return new ItemStack(item, GsonHelper.getAsInt(json, "count", 1));
}
/**
* @deprecated Please use the {@linkplain #processConditions(JsonObject, String, ICondition.IContext) other more general overload}.
*/
@Deprecated(forRemoval = true, since = "1.18.2")
public static boolean processConditions(JsonObject json, String memberName)
{
return !json.has(memberName) || processConditions(GsonHelper.getAsJsonArray(json, memberName));
return processConditions(json, memberName, ICondition.IContext.EMPTY);
}
public static boolean processConditions(JsonObject json, String memberName, ICondition.IContext context)
{
return !json.has(memberName) || processConditions(GsonHelper.getAsJsonArray(json, memberName), context);
}
/**
* @deprecated Please use the {@linkplain #processConditions(JsonArray, ICondition.IContext) other more general overload}.
*/
@Deprecated(forRemoval = true, since = "1.18.2")
public static boolean processConditions(JsonArray conditions)
{
return processConditions(conditions, ICondition.IContext.EMPTY);
}
public static boolean processConditions(JsonArray conditions, ICondition.IContext context)
{
for (int x = 0; x < conditions.size(); x++)
{
@@ -212,7 +230,7 @@ public class CraftingHelper
throw new JsonSyntaxException("Conditions must be an array of JsonObjects");
JsonObject json = conditions.get(x).getAsJsonObject();
if (!CraftingHelper.getCondition(json).test())
if (!CraftingHelper.getCondition(json).test(context))
return false;
}
return true;
@@ -45,10 +45,16 @@ public class AndCondition implements ICondition
@Override
public boolean test()
{
return test(IContext.EMPTY);
}
@Override
public boolean test(IContext context)
{
for (ICondition child : children)
{
if (!child.test())
if (!child.test(context))
return false;
}
return true;
@@ -0,0 +1,45 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.common.crafting.conditions;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagManager;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
public class ConditionContext implements ICondition.IContext
{
private final TagManager tagManager;
private Map<ResourceKey<?>, Map<ResourceLocation, Tag<Holder<?>>>> loadedTags = null;
public ConditionContext(TagManager tagManager)
{
this.tagManager = tagManager;
}
@Override
public <T> Map<ResourceLocation, Tag<Holder<T>>> getAllTags(ResourceKey<? extends Registry<T>> registry)
{
if (loadedTags == null)
{
var tags = tagManager.getResult();
if (tags.isEmpty()) throw new IllegalStateException("Tags have not been loaded yet.");
loadedTags = new IdentityHashMap<>();
for (var loadResult : tags)
{
loadedTags.put(loadResult.key(), (Map) Collections.unmodifiableMap(loadResult.tags()));
}
}
return (Map) loadedTags.getOrDefault(registry, Collections.emptyMap());
}
}
@@ -5,11 +5,54 @@
package net.minecraftforge.common.crafting.conditions;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import java.util.Collections;
import java.util.Map;
public interface ICondition
{
ResourceLocation getID();
default boolean test(IContext context)
{
return test();
}
/**
* @deprecated Use {@linkplain #test(IContext) the other more general overload}.
*/
@Deprecated(forRemoval = true, since = "1.18.2")
boolean test();
interface IContext
{
IContext EMPTY = new IContext()
{
@Override
public <T> Map<ResourceLocation, Tag<Holder<T>>> getAllTags(ResourceKey<? extends Registry<T>> registry)
{
return Collections.emptyMap();
}
};
/**
* Return the requested tag if available, or an empty tag otherwise.
*/
default <T> Tag<Holder<T>> getTag(TagKey<T> key)
{
return getAllTags(key.registry()).getOrDefault(key.location(), Tag.empty());
}
/**
* Return all the loaded tags for the passed registry, or an empty map if none is available.
* Note that the map and the tags are unmodifiable.
*/
<T> Map<ResourceLocation, Tag<Holder<T>>> getAllTags(ResourceKey<? extends Registry<T>> registry);
}
}
@@ -5,6 +5,9 @@
package net.minecraftforge.common.crafting.conditions;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
public interface IConditionBuilder
{
default ICondition and(ICondition... values)
@@ -41,4 +44,9 @@ public interface IConditionBuilder
{
return new ModLoadedCondition(modid);
}
default ICondition tagEmpty(TagKey<Item> tag)
{
return new TagEmptyCondition(tag.location());
}
}
@@ -29,7 +29,13 @@ public class NotCondition implements ICondition
@Override
public boolean test()
{
return !child.test();
return test(IContext.EMPTY);
}
@Override
public boolean test(IContext context)
{
return !child.test(context);
}
@Override
@@ -45,10 +45,16 @@ public class OrCondition implements ICondition
@Override
public boolean test()
{
return test(IContext.EMPTY);
}
@Override
public boolean test(IContext context)
{
for (ICondition child : children)
{
if (child.test())
if (child.test(context))
return true;
}
@@ -7,15 +7,12 @@ package net.minecraftforge.common.crafting.conditions;
import com.google.gson.JsonObject;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.util.GsonHelper;
import net.minecraft.resources.ResourceLocation;
import java.util.Iterator;
public class TagEmptyCondition implements ICondition
{
private static final ResourceLocation NAME = new ResourceLocation("forge", "tag_empty");
@@ -42,10 +39,16 @@ public class TagEmptyCondition implements ICondition
return NAME;
}
@Override
public boolean test(ICondition.IContext context)
{
return context.getTag(tag).getValues().isEmpty();
}
@Override
public boolean test()
{
return !Registry.ITEM.getTag(tag).map(HolderSet.Named::iterator).map(Iterator::hasNext).orElse(false);
return test(IContext.EMPTY);
}
@Override
@@ -0,0 +1,25 @@
/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.common.extensions;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraftforge.common.crafting.conditions.ICondition;
public interface IForgeRecipeSerializer<T extends Recipe<?>>
{
private RecipeSerializer<T> self()
{
return (RecipeSerializer<T>) this;
}
default T fromJson(ResourceLocation recipeLoc, JsonObject recipeJson, ICondition.IContext context)
{
return self().fromJson(recipeLoc, recipeJson);
}
}