249 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| 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 net.minecraft.resources.ResourceKey;
 | |
| import net.minecraft.resources.ResourceLocation;
 | |
| import net.minecraft.tags.TagKey;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| public interface Holder<T> {
 | |
| 	T value();
 | |
| 
 | |
| 	boolean isBound();
 | |
| 
 | |
| 	boolean is(ResourceLocation location);
 | |
| 
 | |
| 	boolean is(ResourceKey<T> resourceKey);
 | |
| 
 | |
| 	boolean is(Predicate<ResourceKey<T>> predicate);
 | |
| 
 | |
| 	boolean is(TagKey<T> tagKey);
 | |
| 
 | |
| 	@Deprecated
 | |
| 	boolean is(Holder<T> holder);
 | |
| 
 | |
| 	Stream<TagKey<T>> tags();
 | |
| 
 | |
| 	Either<ResourceKey<T>, T> unwrap();
 | |
| 
 | |
| 	Optional<ResourceKey<T>> unwrapKey();
 | |
| 
 | |
| 	Holder.Kind kind();
 | |
| 
 | |
| 	boolean canSerializeIn(HolderOwner<T> owner);
 | |
| 
 | |
| 	default String getRegisteredName() {
 | |
| 		return (String)this.unwrapKey().map(resourceKey -> resourceKey.location().toString()).orElse("[unregistered]");
 | |
| 	}
 | |
| 
 | |
| 	static <T> Holder<T> direct(T value) {
 | |
| 		return new Holder.Direct<>(value);
 | |
| 	}
 | |
| 
 | |
| 	public record Direct<T>(T value) implements Holder<T> {
 | |
| 		@Override
 | |
| 		public boolean isBound() {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(ResourceLocation location) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(ResourceKey<T> resourceKey) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(TagKey<T> tagKey) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(Holder<T> holder) {
 | |
| 			return this.value.equals(holder.value());
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(Predicate<ResourceKey<T>> predicate) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Either<ResourceKey<T>, T> unwrap() {
 | |
| 			return Either.right(this.value);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Optional<ResourceKey<T>> unwrapKey() {
 | |
| 			return Optional.empty();
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Holder.Kind kind() {
 | |
| 			return Holder.Kind.DIRECT;
 | |
| 		}
 | |
| 
 | |
| 		public String toString() {
 | |
| 			return "Direct{" + this.value + "}";
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean canSerializeIn(HolderOwner<T> owner) {
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Stream<TagKey<T>> tags() {
 | |
| 			return Stream.of();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static enum Kind {
 | |
| 		REFERENCE,
 | |
| 		DIRECT;
 | |
| 	}
 | |
| 
 | |
| 	public static class Reference<T> implements Holder<T> {
 | |
| 		private final HolderOwner<T> owner;
 | |
| 		@Nullable
 | |
| 		private Set<TagKey<T>> tags;
 | |
| 		private final Holder.Reference.Type type;
 | |
| 		@Nullable
 | |
| 		private ResourceKey<T> key;
 | |
| 		@Nullable
 | |
| 		private T value;
 | |
| 
 | |
| 		protected Reference(Holder.Reference.Type type, HolderOwner<T> owner, @Nullable ResourceKey<T> key, @Nullable T value) {
 | |
| 			this.owner = owner;
 | |
| 			this.type = type;
 | |
| 			this.key = key;
 | |
| 			this.value = value;
 | |
| 		}
 | |
| 
 | |
| 		public static <T> Holder.Reference<T> createStandAlone(HolderOwner<T> owner, ResourceKey<T> key) {
 | |
| 			return new Holder.Reference<>(Holder.Reference.Type.STAND_ALONE, owner, key, null);
 | |
| 		}
 | |
| 
 | |
| 		@Deprecated
 | |
| 		public static <T> Holder.Reference<T> createIntrusive(HolderOwner<T> owner, @Nullable T value) {
 | |
| 			return new Holder.Reference<>(Holder.Reference.Type.INTRUSIVE, owner, null, value);
 | |
| 		}
 | |
| 
 | |
| 		public ResourceKey<T> 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 location) {
 | |
| 			return this.key().location().equals(location);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(ResourceKey<T> resourceKey) {
 | |
| 			return this.key() == resourceKey;
 | |
| 		}
 | |
| 
 | |
| 		private Set<TagKey<T>> boundTags() {
 | |
| 			if (this.tags == null) {
 | |
| 				throw new IllegalStateException("Tags not bound");
 | |
| 			} else {
 | |
| 				return this.tags;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(TagKey<T> tagKey) {
 | |
| 			return this.boundTags().contains(tagKey);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(Holder<T> holder) {
 | |
| 			return holder.is(this.key());
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean is(Predicate<ResourceKey<T>> predicate) {
 | |
| 			return predicate.test(this.key());
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean canSerializeIn(HolderOwner<T> owner) {
 | |
| 			return this.owner.canSerializeIn(owner);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Either<ResourceKey<T>, T> unwrap() {
 | |
| 			return Either.left(this.key());
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Optional<ResourceKey<T>> 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<T> key) {
 | |
| 			if (this.key != null && key != this.key) {
 | |
| 				throw new IllegalStateException("Can't change holder key: existing=" + this.key + ", new=" + key);
 | |
| 			} else {
 | |
| 				this.key = key;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		protected void bindValue(T value) {
 | |
| 			if (this.type == Holder.Reference.Type.INTRUSIVE && this.value != value) {
 | |
| 				throw new IllegalStateException("Can't change holder " + this.key + " value: existing=" + this.value + ", new=" + value);
 | |
| 			} else {
 | |
| 				this.value = value;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		void bindTags(Collection<TagKey<T>> tags) {
 | |
| 			this.tags = Set.copyOf(tags);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public Stream<TagKey<T>> tags() {
 | |
| 			return this.boundTags().stream();
 | |
| 		}
 | |
| 
 | |
| 		public String toString() {
 | |
| 			return "Reference{" + this.key + "=" + this.value + "}";
 | |
| 		}
 | |
| 
 | |
| 		protected static enum Type {
 | |
| 			STAND_ALONE,
 | |
| 			INTRUSIVE;
 | |
| 		}
 | |
| 	}
 | |
| }
 |