113 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.util;
 | |
| 
 | |
| import com.mojang.datafixers.util.Pair;
 | |
| import com.mojang.serialization.Codec;
 | |
| import com.mojang.serialization.DataResult;
 | |
| import com.mojang.serialization.DynamicOps;
 | |
| import com.mojang.serialization.Keyable;
 | |
| import java.util.Arrays;
 | |
| import java.util.Map;
 | |
| import java.util.Objects;
 | |
| import java.util.function.Function;
 | |
| import java.util.function.Supplier;
 | |
| import java.util.function.ToIntFunction;
 | |
| import java.util.stream.Collectors;
 | |
| import java.util.stream.Stream;
 | |
| import net.minecraft.Util;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| public interface StringRepresentable {
 | |
| 	int PRE_BUILT_MAP_THRESHOLD = 16;
 | |
| 
 | |
| 	String getSerializedName();
 | |
| 
 | |
| 	static <E extends Enum<E> & StringRepresentable> StringRepresentable.EnumCodec<E> fromEnum(Supplier<E[]> elementsSupplier) {
 | |
| 		return fromEnumWithMapping(elementsSupplier, string -> string);
 | |
| 	}
 | |
| 
 | |
| 	static <E extends Enum<E> & StringRepresentable> StringRepresentable.EnumCodec<E> fromEnumWithMapping(
 | |
| 		Supplier<E[]> enumValues, Function<String, String> keyFunction
 | |
| 	) {
 | |
| 		E[] enums = (E[])enumValues.get();
 | |
| 		Function<String, E> function = createNameLookup(enums, keyFunction);
 | |
| 		return new StringRepresentable.EnumCodec<>(enums, function);
 | |
| 	}
 | |
| 
 | |
| 	static <T extends StringRepresentable> Codec<T> fromValues(Supplier<T[]> valuesSupplier) {
 | |
| 		T[] stringRepresentables = (T[])valuesSupplier.get();
 | |
| 		Function<String, T> function = createNameLookup(stringRepresentables, string -> string);
 | |
| 		ToIntFunction<T> toIntFunction = Util.createIndexLookup(Arrays.asList(stringRepresentables));
 | |
| 		return new StringRepresentable.StringRepresentableCodec<>(stringRepresentables, function, toIntFunction);
 | |
| 	}
 | |
| 
 | |
| 	static <T extends StringRepresentable> Function<String, T> createNameLookup(T[] values, Function<String, String> keyFunction) {
 | |
| 		if (values.length > 16) {
 | |
| 			Map<String, T> map = (Map<String, T>)Arrays.stream(values)
 | |
| 				.collect(
 | |
| 					Collectors.toMap(stringRepresentable -> (String)keyFunction.apply(stringRepresentable.getSerializedName()), stringRepresentable -> stringRepresentable)
 | |
| 				);
 | |
| 			return string -> string == null ? null : (StringRepresentable)map.get(string);
 | |
| 		} else {
 | |
| 			return string -> {
 | |
| 				for (T stringRepresentable : values) {
 | |
| 					if (((String)keyFunction.apply(stringRepresentable.getSerializedName())).equals(string)) {
 | |
| 						return stringRepresentable;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return null;
 | |
| 			};
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static Keyable keys(StringRepresentable[] serializables) {
 | |
| 		return new Keyable() {
 | |
| 			@Override
 | |
| 			public <T> Stream<T> keys(DynamicOps<T> dynamicOps) {
 | |
| 				return Arrays.stream(serializables).map(StringRepresentable::getSerializedName).map(dynamicOps::createString);
 | |
| 			}
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	public static class EnumCodec<E extends Enum<E> & StringRepresentable> extends StringRepresentable.StringRepresentableCodec<E> {
 | |
| 		private final Function<String, E> resolver;
 | |
| 
 | |
| 		public EnumCodec(E[] values, Function<String, E> resolver) {
 | |
| 			super(values, resolver, object -> ((Enum)object).ordinal());
 | |
| 			this.resolver = resolver;
 | |
| 		}
 | |
| 
 | |
| 		@Nullable
 | |
| 		public E byName(@Nullable String name) {
 | |
| 			return (E)this.resolver.apply(name);
 | |
| 		}
 | |
| 
 | |
| 		public E byName(@Nullable String name, E defaultValue) {
 | |
| 			return (E)Objects.requireNonNullElse(this.byName(name), defaultValue);
 | |
| 		}
 | |
| 
 | |
| 		public E byName(@Nullable String name, Supplier<? extends E> defaultValue) {
 | |
| 			return (E)Objects.requireNonNullElseGet(this.byName(name), defaultValue);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static class StringRepresentableCodec<S extends StringRepresentable> implements Codec<S> {
 | |
| 		private final Codec<S> codec;
 | |
| 
 | |
| 		public StringRepresentableCodec(S[] values, Function<String, S> nameLookup, ToIntFunction<S> indexLookup) {
 | |
| 			this.codec = ExtraCodecs.orCompressed(
 | |
| 				Codec.stringResolver(StringRepresentable::getSerializedName, nameLookup),
 | |
| 				ExtraCodecs.idResolverCodec(indexLookup, i -> i >= 0 && i < values.length ? values[i] : null, -1)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public <T> DataResult<Pair<S, T>> decode(DynamicOps<T> dynamicOps, T object) {
 | |
| 			return this.codec.decode(dynamicOps, object);
 | |
| 		}
 | |
| 
 | |
| 		public <T> DataResult<T> encode(S input, DynamicOps<T> ops, T prefix) {
 | |
| 			return this.codec.encode(input, ops, prefix);
 | |
| 		}
 | |
| 	}
 | |
| }
 |