package net.minecraft.core; import com.mojang.datafixers.util.Either; import java.util.Collection; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; import javax.annotation.Nullable; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; public interface Holder { T value(); boolean isBound(); boolean is(ResourceLocation p_205713_); boolean is(ResourceKey p_205712_); boolean is(Predicate> p_205711_); boolean is(TagKey p_205705_); @Deprecated boolean is(Holder p_334336_); Stream> tags(); Either, T> unwrap(); Optional> unwrapKey(); Holder.Kind kind(); boolean canSerializeIn(HolderOwner p_255833_); default String getRegisteredName() { return this.unwrapKey().map(p_335124_ -> p_335124_.location().toString()).orElse("[unregistered]"); } static Holder direct(T p_205710_) { return new Holder.Direct<>(p_205710_); } public record Direct(T value) implements Holder { @Override public boolean isBound() { return true; } @Override public boolean is(ResourceLocation p_205727_) { return false; } @Override public boolean is(ResourceKey p_205725_) { return false; } @Override public boolean is(TagKey p_205719_) { return false; } @Override public boolean is(Holder p_329830_) { return this.value.equals(p_329830_.value()); } @Override public boolean is(Predicate> p_205723_) { return false; } @Override public Either, T> unwrap() { return Either.right(this.value); } @Override public Optional> unwrapKey() { return Optional.empty(); } @Override public Holder.Kind kind() { return Holder.Kind.DIRECT; } @Override public String toString() { return "Direct{" + this.value + "}"; } @Override public boolean canSerializeIn(HolderOwner p_256328_) { return true; } @Override public Stream> tags() { return Stream.of(); } @Override public T value() { return this.value; } } public static enum Kind { REFERENCE, DIRECT; } public static class Reference implements Holder { private final HolderOwner owner; @Nullable private Set> tags; private final Holder.Reference.Type type; @Nullable private ResourceKey key; @Nullable private T value; protected Reference(Holder.Reference.Type p_256425_, HolderOwner p_256562_, @Nullable ResourceKey p_256636_, @Nullable T p_255889_) { this.owner = p_256562_; this.type = p_256425_; this.key = p_256636_; this.value = p_255889_; } public static Holder.Reference createStandAlone(HolderOwner p_255955_, ResourceKey p_255958_) { return new Holder.Reference<>(Holder.Reference.Type.STAND_ALONE, p_255955_, p_255958_, null); } @Deprecated public static Holder.Reference createIntrusive(HolderOwner p_256106_, @Nullable T p_255948_) { return new Holder.Reference<>(Holder.Reference.Type.INTRUSIVE, p_256106_, null, p_255948_); } public ResourceKey key() { if (this.key == null) { throw new IllegalStateException("Trying to access unbound value '" + this.value + "' from registry " + this.owner); } else { return this.key; } } @Override public T value() { if (this.value == null) { throw new IllegalStateException("Trying to access unbound value '" + this.key + "' from registry " + this.owner); } else { return this.value; } } @Override public boolean is(ResourceLocation p_205779_) { return this.key().location().equals(p_205779_); } @Override public boolean is(ResourceKey p_205774_) { return this.key() == p_205774_; } private Set> boundTags() { if (this.tags == null) { throw new IllegalStateException("Tags not bound"); } else { return this.tags; } } @Override public boolean is(TagKey p_205760_) { return this.boundTags().contains(p_205760_); } @Override public boolean is(Holder p_335729_) { return p_335729_.is(this.key()); } @Override public boolean is(Predicate> p_205772_) { return p_205772_.test(this.key()); } @Override public boolean canSerializeIn(HolderOwner p_256521_) { return this.owner.canSerializeIn(p_256521_); } @Override public Either, T> unwrap() { return Either.left(this.key()); } @Override public Optional> unwrapKey() { return Optional.of(this.key()); } @Override public Holder.Kind kind() { return Holder.Kind.REFERENCE; } @Override public boolean isBound() { return this.key != null && this.value != null; } void bindKey(ResourceKey p_251943_) { if (this.key != null && p_251943_ != this.key) { throw new IllegalStateException("Can't change holder key: existing=" + this.key + ", new=" + p_251943_); } else { this.key = p_251943_; } } protected void bindValue(T p_249418_) { if (this.type == Holder.Reference.Type.INTRUSIVE && this.value != p_249418_) { throw new IllegalStateException("Can't change holder " + this.key + " value: existing=" + this.value + ", new=" + p_249418_); } else { this.value = p_249418_; } } void bindTags(Collection> p_205770_) { this.tags = Set.copyOf(p_205770_); } @Override public Stream> tags() { return this.boundTags().stream(); } @Override public String toString() { return "Reference{" + this.key + "=" + this.value + "}"; } protected static enum Type { STAND_ALONE, INTRUSIVE; } } }