diff --git a/patches/minecraft/net/minecraft/tags/Tag.java.patch b/patches/minecraft/net/minecraft/tags/Tag.java.patch new file mode 100644 index 000000000..78758c654 --- /dev/null +++ b/patches/minecraft/net/minecraft/tags/Tag.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/tags/Tag.java ++++ b/net/minecraft/tags/Tag.java +@@ -151,9 +151,11 @@ + this.func_200159_a(new ResourceLocation(s.substring(1))); + } + } ++ net.minecraftforge.common.ForgeHooks.deserializeTagAdditions(this, p_200158_1_, p_200158_2_, p_200158_3_); + + return this; + } ++ public Tag.Builder remove(Tag.ITagEntry e) { this.field_200052_a.remove(e); return this; } + } + + public interface ITagEntry { +@@ -192,6 +194,8 @@ + public Collection func_200578_a() { + return this.field_200165_a; + } ++ @Override public int hashCode() { return this.field_200165_a.hashCode(); } ++ @Override public boolean equals(Object o) { return o == this || (o instanceof Tag.ListEntry && this.field_200165_a.equals(((Tag.ListEntry) o).field_200165_a)); } + } + + public static class TagEntry implements Tag.ITagEntry { +@@ -238,5 +242,7 @@ + public void func_200576_a(JsonArray p_200576_1_, Function p_200576_2_) { + p_200576_1_.add("#" + this.func_200577_a()); + } ++ @Override public int hashCode() { return java.util.Objects.hashCode(this.field_200163_a); } ++ @Override public boolean equals(Object o) { return o == this || (o instanceof Tag.TagEntry && java.util.Objects.equals(this.field_200163_a, ((Tag.TagEntry) o).field_200163_a)); } + } + } diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index 6028ee9ec..d0b898eeb 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -29,6 +29,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Deque; import java.util.HashSet; import java.util.List; @@ -37,6 +38,8 @@ import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -46,6 +49,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Queues; import com.google.common.collect.Sets; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; @@ -1157,4 +1161,76 @@ public class ForgeHooks Result res = ForgeEventFactory.canEntitySpawn(entity, world, x, y, z, null); return res == Result.DEFAULT ? 0 : res == Result.DENY ? -1 : 1; } + + public static void deserializeTagAdditions(Tag.Builder builder, Predicate isValueKnown, Function valueGetter, JsonObject json) + { + if (json.has("optional")) + { + for (JsonElement entry : JsonUtils.getJsonArray(json, "optional")) + { + String s = JsonUtils.getString(entry, "value"); + if (!s.startsWith("#")) + { + ResourceLocation rl = new ResourceLocation(s); + if (isValueKnown.test(rl) && valueGetter.apply(rl) != null) + { + builder.add(valueGetter.apply(rl)); + } + } else + { + builder.add(new OptionalTagEntry<>(new ResourceLocation(s.substring(1)))); + } + } + } + + if (json.has("remove")) + { + for (JsonElement entry : JsonUtils.getJsonArray(json, "remove")) + { + String s = JsonUtils.getString(entry, "value"); + if (!s.startsWith("#")) + { + ResourceLocation rl = new ResourceLocation(s); + if (isValueKnown.test(rl) && valueGetter.apply(rl) != null) + { + Tag.ITagEntry dummyEntry = new Tag.ListEntry<>(Collections.singletonList(valueGetter.apply(rl))); + builder.remove(dummyEntry); + } + } else + { + Tag.ITagEntry dummyEntry = new Tag.TagEntry<>(new ResourceLocation(s.substring(1))); + builder.remove(dummyEntry); + } + } + } + } + + private static class OptionalTagEntry extends Tag.TagEntry + { + private Tag resolvedTag = null; + + OptionalTagEntry(ResourceLocation referent) + { + super(referent); + } + + @Override + public boolean resolve(@Nonnull Function> resolver) + { + if (this.resolvedTag == null) + { + this.resolvedTag = resolver.apply(this.getSerializedId()); + } + return true; // never fail if resolver returns null + } + + @Override + public void populate(@Nonnull Collection items) + { + if (this.resolvedTag != null) + { + items.addAll(this.resolvedTag.getAllElements()); + } + } + } }