package net.minecraft.util; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.common.primitives.UnsignedBytes; import com.google.gson.JsonElement; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.Decoder; import com.mojang.serialization.Dynamic; import com.mojang.serialization.DynamicOps; import com.mojang.serialization.JavaOps; import com.mojang.serialization.JsonOps; import com.mojang.serialization.Lifecycle; import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapLike; import com.mojang.serialization.RecordBuilder; import com.mojang.serialization.Codec.ResultFunction; import com.mojang.serialization.DataResult.Error; import com.mojang.serialization.codecs.BaseMapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatList; import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import java.time.Instant; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; import java.util.Arrays; import java.util.Base64; import java.util.BitSet; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.ToIntFunction; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.stream.LongStream; import java.util.stream.Stream; import net.minecraft.Util; import net.minecraft.core.HolderSet; import net.minecraft.core.UUIDUtil; import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.mutable.MutableObject; import org.joml.AxisAngle4f; import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3f; import org.joml.Vector4f; public class ExtraCodecs { public static final Codec JSON = converter(JsonOps.INSTANCE); public static final Codec JAVA = converter(JavaOps.INSTANCE); public static final Codec VECTOR3F = Codec.FLOAT .listOf() .comapFlatMap( p_326507_ -> Util.fixedSize((List)p_326507_, 3).map(p_253489_ -> new Vector3f(p_253489_.get(0), p_253489_.get(1), p_253489_.get(2))), p_269787_ -> List.of(p_269787_.x(), p_269787_.y(), p_269787_.z()) ); public static final Codec VECTOR4F = Codec.FLOAT .listOf() .comapFlatMap( p_326501_ -> Util.fixedSize((List)p_326501_, 4) .map(p_326509_ -> new Vector4f(p_326509_.get(0), p_326509_.get(1), p_326509_.get(2), p_326509_.get(3))), p_326511_ -> List.of(p_326511_.x(), p_326511_.y(), p_326511_.z(), p_326511_.w()) ); public static final Codec QUATERNIONF_COMPONENTS = Codec.FLOAT .listOf() .comapFlatMap( p_326503_ -> Util.fixedSize((List)p_326503_, 4) .map(p_341245_ -> new Quaternionf(p_341245_.get(0), p_341245_.get(1), p_341245_.get(2), p_341245_.get(3)).normalize()), p_269780_ -> List.of(p_269780_.x, p_269780_.y, p_269780_.z, p_269780_.w) ); public static final Codec AXISANGLE4F = RecordCodecBuilder.create( p_269774_ -> p_269774_.group( Codec.FLOAT.fieldOf("angle").forGetter(p_269776_ -> p_269776_.angle), VECTOR3F.fieldOf("axis").forGetter(p_269778_ -> new Vector3f(p_269778_.x, p_269778_.y, p_269778_.z)) ) .apply(p_269774_, AxisAngle4f::new) ); public static final Codec QUATERNIONF = Codec.withAlternative(QUATERNIONF_COMPONENTS, AXISANGLE4F.xmap(Quaternionf::new, AxisAngle4f::new)); public static final Codec MATRIX4F = Codec.FLOAT .listOf() .comapFlatMap(p_326510_ -> Util.fixedSize((List)p_326510_, 16).map(p_269777_ -> { Matrix4f matrix4f = new Matrix4f(); for (int i = 0; i < p_269777_.size(); i++) { matrix4f.setRowColumn(i >> 2, i & 3, p_269777_.get(i)); } return matrix4f.determineProperties(); }), p_269775_ -> { FloatList floatlist = new FloatArrayList(16); for (int i = 0; i < 16; i++) { floatlist.add(p_269775_.getRowColumn(i >> 2, i & 3)); } return floatlist; }); public static final Codec RGB_COLOR_CODEC = Codec.withAlternative( Codec.INT, VECTOR3F, p_358806_ -> ARGB.colorFromFloat(1.0F, p_358806_.x(), p_358806_.y(), p_358806_.z()) ); public static final Codec ARGB_COLOR_CODEC = Codec.withAlternative( Codec.INT, VECTOR4F, p_358801_ -> ARGB.colorFromFloat(p_358801_.w(), p_358801_.x(), p_358801_.y(), p_358801_.z()) ); public static final Codec UNSIGNED_BYTE = Codec.BYTE .flatComapMap( UnsignedBytes::toInt, p_326500_ -> p_326500_ > 255 ? DataResult.error(() -> "Unsigned byte was too large: " + p_326500_ + " > 255") : DataResult.success(p_326500_.byteValue()) ); public static final Codec NON_NEGATIVE_INT = intRangeWithMessage(0, Integer.MAX_VALUE, p_275703_ -> "Value must be non-negative: " + p_275703_); public static final Codec POSITIVE_INT = intRangeWithMessage(1, Integer.MAX_VALUE, p_274847_ -> "Value must be positive: " + p_274847_); public static final Codec NON_NEGATIVE_FLOAT = floatRangeMinInclusiveWithMessage(0.0F, Float.MAX_VALUE, p_274876_ -> "Value must be non-negative: " + p_274876_); public static final Codec POSITIVE_FLOAT = floatRangeMinExclusiveWithMessage(0.0F, Float.MAX_VALUE, p_368583_ -> "Value must be positive: " + p_368583_); public static final Codec PATTERN = Codec.STRING.comapFlatMap(p_274857_ -> { try { return DataResult.success(Pattern.compile(p_274857_)); } catch (PatternSyntaxException patternsyntaxexception) { return DataResult.error(() -> "Invalid regex pattern '" + p_274857_ + "': " + patternsyntaxexception.getMessage()); } }, Pattern::pattern); public static final Codec INSTANT_ISO8601 = temporalCodec(DateTimeFormatter.ISO_INSTANT).xmap(Instant::from, Function.identity()); public static final Codec BASE64_STRING = Codec.STRING.comapFlatMap(p_274852_ -> { try { return DataResult.success(Base64.getDecoder().decode(p_274852_)); } catch (IllegalArgumentException illegalargumentexception) { return DataResult.error(() -> "Malformed base64 string"); } }, p_216180_ -> Base64.getEncoder().encodeToString(p_216180_)); public static final Codec ESCAPED_STRING = Codec.STRING .comapFlatMap(p_296617_ -> DataResult.success(StringEscapeUtils.unescapeJava(p_296617_)), StringEscapeUtils::escapeJava); public static final Codec TAG_OR_ELEMENT_ID = Codec.STRING .comapFlatMap( p_326502_ -> p_326502_.startsWith("#") ? ResourceLocation.read(p_326502_.substring(1)).map(p_216182_ -> new ExtraCodecs.TagOrElementLocation(p_216182_, true)) : ResourceLocation.read(p_326502_).map(p_216165_ -> new ExtraCodecs.TagOrElementLocation(p_216165_, false)), ExtraCodecs.TagOrElementLocation::decoratedId ); public static final Function, OptionalLong> toOptionalLong = p_216176_ -> p_216176_.map(OptionalLong::of).orElseGet(OptionalLong::empty); public static final Function> fromOptionalLong = p_216178_ -> p_216178_.isPresent() ? Optional.of(p_216178_.getAsLong()) : Optional.empty(); public static final Codec BIT_SET = Codec.LONG_STREAM .xmap(p_253514_ -> BitSet.valueOf(p_253514_.toArray()), p_253493_ -> Arrays.stream(p_253493_.toLongArray())); private static final Codec PROPERTY = RecordCodecBuilder.create( p_326504_ -> p_326504_.group( Codec.STRING.fieldOf("name").forGetter(Property::name), Codec.STRING.fieldOf("value").forGetter(Property::value), Codec.STRING.lenientOptionalFieldOf("signature").forGetter(p_296611_ -> Optional.ofNullable(p_296611_.signature())) ) .apply(p_326504_, (p_253494_, p_253495_, p_253496_) -> new Property(p_253494_, p_253495_, p_253496_.orElse(null))) ); public static final Codec PROPERTY_MAP = Codec.either(Codec.unboundedMap(Codec.STRING, Codec.STRING.listOf()), PROPERTY.listOf()) .xmap(p_253515_ -> { PropertyMap propertymap = new PropertyMap(); p_253515_.ifLeft(p_253506_ -> p_253506_.forEach((p_253500_, p_253501_) -> { for (String s : p_253501_) { propertymap.put(p_253500_, new Property(p_253500_, s)); } })).ifRight(p_296607_ -> { for (Property property : p_296607_) { propertymap.put(property.name(), property); } }); return propertymap; }, p_253504_ -> Either.right(p_253504_.values().stream().toList())); public static final Codec PLAYER_NAME = Codec.string(0, 16) .validate( p_326493_ -> StringUtil.isValidPlayerName(p_326493_) ? DataResult.success(p_326493_) : DataResult.error(() -> "Player name contained disallowed characters: '" + p_326493_ + "'") ); private static final MapCodec GAME_PROFILE_WITHOUT_PROPERTIES = RecordCodecBuilder.mapCodec( p_326508_ -> p_326508_.group(UUIDUtil.AUTHLIB_CODEC.fieldOf("id").forGetter(GameProfile::getId), PLAYER_NAME.fieldOf("name").forGetter(GameProfile::getName)) .apply(p_326508_, GameProfile::new) ); public static final Codec GAME_PROFILE = RecordCodecBuilder.create( p_326512_ -> p_326512_.group( GAME_PROFILE_WITHOUT_PROPERTIES.forGetter(Function.identity()), PROPERTY_MAP.lenientOptionalFieldOf("properties", new PropertyMap()).forGetter(GameProfile::getProperties) ) .apply(p_326512_, (p_253518_, p_253519_) -> { p_253519_.forEach((p_253511_, p_253512_) -> p_253518_.getProperties().put(p_253511_, p_253512_)); return p_253518_; }) ); public static final Codec NON_EMPTY_STRING = Codec.STRING .validate(p_274858_ -> p_274858_.isEmpty() ? DataResult.error(() -> "Expected non-empty string") : DataResult.success(p_274858_)); public static final Codec CODEPOINT = Codec.STRING.comapFlatMap(p_284688_ -> { int[] aint = p_284688_.codePoints().toArray(); return aint.length != 1 ? DataResult.error(() -> "Expected one codepoint, got: " + p_284688_) : DataResult.success(aint[0]); }, Character::toString); public static final Codec RESOURCE_PATH_CODEC = Codec.STRING .validate( p_296613_ -> !ResourceLocation.isValidPath(p_296613_) ? DataResult.error(() -> "Invalid string to use as a resource path element: " + p_296613_) : DataResult.success(p_296613_) ); public static Codec converter(DynamicOps p_310943_) { return Codec.PASSTHROUGH.xmap(p_308959_ -> p_308959_.convert(p_310943_).getValue(), p_308962_ -> new Dynamic<>(p_310943_, (T)p_308962_)); } public static Codec intervalCodec( Codec

p_184362_, String p_184363_, String p_184364_, BiFunction> p_184365_, Function p_184366_, Function p_184367_ ) { Codec codec = Codec.list(p_184362_).comapFlatMap(p_326514_ -> Util.fixedSize((List

)p_326514_, 2).flatMap(p_184445_ -> { P p = p_184445_.get(0); P p1 = p_184445_.get(1); return p_184365_.apply(p, p1); }), p_184459_ -> ImmutableList.of(p_184366_.apply((I)p_184459_), p_184367_.apply((I)p_184459_))); Codec codec1 = RecordCodecBuilder.>create( p_184360_ -> p_184360_.group(p_184362_.fieldOf(p_184363_).forGetter(Pair::getFirst), p_184362_.fieldOf(p_184364_).forGetter(Pair::getSecond)) .apply(p_184360_, Pair::of) ) .comapFlatMap( p_184392_ -> p_184365_.apply((P)p_184392_.getFirst(), (P)p_184392_.getSecond()), p_184449_ -> Pair.of(p_184366_.apply((I)p_184449_), p_184367_.apply((I)p_184449_)) ); Codec codec2 = Codec.withAlternative(codec, codec1); return Codec.either(p_184362_, codec2) .comapFlatMap(p_184389_ -> p_184389_.map(p_184395_ -> p_184365_.apply((P)p_184395_, (P)p_184395_), DataResult::success), p_184411_ -> { P p = p_184366_.apply((I)p_184411_); P p1 = p_184367_.apply((I)p_184411_); return Objects.equals(p, p1) ? Either.left(p) : Either.right((I)p_184411_); }); } public static ResultFunction orElsePartial(final A p_184382_) { return new ResultFunction() { @Override public DataResult> apply(DynamicOps p_184466_, T p_184467_, DataResult> p_184468_) { MutableObject mutableobject = new MutableObject<>(); Optional> optional = p_184468_.resultOrPartial(mutableobject::setValue); return optional.isPresent() ? p_184468_ : DataResult.error(() -> "(" + mutableobject.getValue() + " -> using default)", Pair.of(p_184382_, p_184467_)); } @Override public DataResult coApply(DynamicOps p_184470_, A p_184471_, DataResult p_184472_) { return p_184472_; } @Override public String toString() { return "OrElsePartial[" + p_184382_ + "]"; } }; } public static Codec idResolverCodec(ToIntFunction p_184422_, IntFunction p_184423_, int p_184424_) { return Codec.INT .flatXmap( p_184414_ -> Optional.ofNullable(p_184423_.apply(p_184414_)) .map(DataResult::success) .orElseGet(() -> DataResult.error(() -> "Unknown element id: " + p_184414_)), p_274850_ -> { int i = p_184422_.applyAsInt((E)p_274850_); return i == p_184424_ ? DataResult.error(() -> "Element with unknown id: " + p_274850_) : DataResult.success(i); } ); } public static Codec idResolverCodec(Codec p_376599_, Function p_378105_, Function p_376561_) { return p_376599_.flatXmap(p_374893_ -> { E e = p_378105_.apply((I)p_374893_); return e == null ? DataResult.error(() -> "Unknown element id: " + p_374893_) : DataResult.success(e); }, p_374900_ -> { I i = p_376561_.apply((E)p_374900_); return i == null ? DataResult.error(() -> "Element with unknown id: " + p_374900_) : DataResult.success(i); }); } public static Codec orCompressed(final Codec p_184426_, final Codec p_184427_) { return new Codec() { @Override public DataResult encode(E p_184483_, DynamicOps p_184484_, T p_184485_) { return p_184484_.compressMaps() ? p_184427_.encode(p_184483_, p_184484_, p_184485_) : p_184426_.encode(p_184483_, p_184484_, p_184485_); } @Override public DataResult> decode(DynamicOps p_184480_, T p_184481_) { return p_184480_.compressMaps() ? p_184427_.decode(p_184480_, p_184481_) : p_184426_.decode(p_184480_, p_184481_); } @Override public String toString() { return p_184426_ + " orCompressed " + p_184427_; } }; } public static MapCodec orCompressed(final MapCodec p_311419_, final MapCodec p_312369_) { return new MapCodec() { @Override public RecordBuilder encode(E p_310450_, DynamicOps p_312581_, RecordBuilder p_310094_) { return p_312581_.compressMaps() ? p_312369_.encode(p_310450_, p_312581_, p_310094_) : p_311419_.encode(p_310450_, p_312581_, p_310094_); } @Override public DataResult decode(DynamicOps p_312833_, MapLike p_309452_) { return p_312833_.compressMaps() ? p_312369_.decode(p_312833_, p_309452_) : p_311419_.decode(p_312833_, p_309452_); } @Override public Stream keys(DynamicOps p_311885_) { return p_312369_.keys(p_311885_); } @Override public String toString() { return p_311419_ + " orCompressed " + p_312369_; } }; } public static Codec overrideLifecycle(Codec p_184369_, final Function p_184370_, final Function p_184371_) { return p_184369_.mapResult(new ResultFunction() { @Override public DataResult> apply(DynamicOps p_310634_, T p_310147_, DataResult> p_311056_) { return p_311056_.result().map(p_326518_ -> p_311056_.setLifecycle(p_184370_.apply(p_326518_.getFirst()))).orElse(p_311056_); } @Override public DataResult coApply(DynamicOps p_311101_, E p_309590_, DataResult p_309495_) { return p_309495_.setLifecycle(p_184371_.apply(p_309590_)); } @Override public String toString() { return "WithLifecycle[" + p_184370_ + " " + p_184371_ + "]"; } }); } public static Codec overrideLifecycle(Codec p_331277_, Function p_331041_) { return overrideLifecycle(p_331277_, p_331041_, p_331041_); } public static ExtraCodecs.StrictUnboundedMapCodec strictUnboundedMap(Codec p_298880_, Codec p_297369_) { return new ExtraCodecs.StrictUnboundedMapCodec<>(p_298880_, p_297369_); } public static Codec> compactListCodec(Codec p_375826_) { return compactListCodec(p_375826_, p_375826_.listOf()); } public static Codec> compactListCodec(Codec p_378656_, Codec> p_377134_) { return Codec.either(p_377134_, p_378656_) .xmap( p_374901_ -> p_374901_.map(p_374891_ -> p_374891_, List::of), p_374897_ -> p_374897_.size() == 1 ? Either.right(p_374897_.getFirst()) : Either.left((List)p_374897_) ); } private static Codec intRangeWithMessage(int p_144634_, int p_144635_, Function p_144636_) { return Codec.INT .validate( p_274889_ -> p_274889_.compareTo(p_144634_) >= 0 && p_274889_.compareTo(p_144635_) <= 0 ? DataResult.success(p_274889_) : DataResult.error(() -> p_144636_.apply(p_274889_)) ); } public static Codec intRange(int p_270883_, int p_270323_) { return intRangeWithMessage(p_270883_, p_270323_, p_269784_ -> "Value must be within range [" + p_270883_ + ";" + p_270323_ + "]: " + p_269784_); } private static Codec floatRangeMinInclusiveWithMessage(float p_367913_, float p_363196_, Function p_366905_) { return Codec.FLOAT .validate( p_358800_ -> p_358800_.compareTo(p_367913_) >= 0 && p_358800_.compareTo(p_363196_) <= 0 ? DataResult.success(p_358800_) : DataResult.error(() -> p_366905_.apply(p_358800_)) ); } private static Codec floatRangeMinExclusiveWithMessage(float p_184351_, float p_184352_, Function p_184353_) { return Codec.FLOAT .validate( p_274865_ -> p_274865_.compareTo(p_184351_) > 0 && p_274865_.compareTo(p_184352_) <= 0 ? DataResult.success(p_274865_) : DataResult.error(() -> p_184353_.apply(p_274865_)) ); } public static Codec floatRange(float p_375431_, float p_376877_) { return floatRangeMinInclusiveWithMessage(p_375431_, p_376877_, p_374896_ -> "Value must be within range [" + p_375431_ + ";" + p_376877_ + "]: " + p_374896_); } public static Codec> nonEmptyList(Codec> p_144638_) { return p_144638_.validate(p_274853_ -> p_274853_.isEmpty() ? DataResult.error(() -> "List must have contents") : DataResult.success(p_274853_)); } public static Codec> nonEmptyHolderSet(Codec> p_203983_) { return p_203983_.validate( p_274860_ -> p_274860_.unwrap().right().filter(List::isEmpty).isPresent() ? DataResult.error(() -> "List must have contents") : DataResult.success(p_274860_) ); } public static > Codec nonEmptyMap(Codec p_365784_) { return p_365784_.validate(p_358805_ -> p_358805_.isEmpty() ? DataResult.error(() -> "Map must have contents") : DataResult.success(p_358805_)); } public static MapCodec retrieveContext(final Function, DataResult> p_203977_) { class ContextRetrievalCodec extends MapCodec { @Override public RecordBuilder encode(E p_203993_, DynamicOps p_203994_, RecordBuilder p_203995_) { return p_203995_; } @Override public DataResult decode(DynamicOps p_203990_, MapLike p_203991_) { return p_203977_.apply(p_203990_); } @Override public String toString() { return "ContextRetrievalCodec[" + p_203977_ + "]"; } @Override public Stream keys(DynamicOps p_203997_) { return Stream.empty(); } } return new ContextRetrievalCodec(); } public static , T> Function> ensureHomogenous(Function p_203985_) { return p_203980_ -> { Iterator iterator = p_203980_.iterator(); if (iterator.hasNext()) { T t = p_203985_.apply(iterator.next()); while (iterator.hasNext()) { E e = iterator.next(); T t1 = p_203985_.apply(e); if (t1 != t) { return DataResult.error(() -> "Mixed type list: element " + e + " had type " + t1 + ", but list is of type " + t); } } } return DataResult.success(p_203980_, Lifecycle.stable()); }; } public static Codec catchDecoderException(final Codec p_216186_) { return Codec.of(p_216186_, new Decoder() { @Override public DataResult> decode(DynamicOps p_309963_, T p_309877_) { try { return p_216186_.decode(p_309963_, p_309877_); } catch (Exception exception) { return DataResult.error(() -> "Caught exception decoding " + p_309877_ + ": " + exception.getMessage()); } } }); } public static Codec temporalCodec(DateTimeFormatter p_216171_) { return Codec.STRING.comapFlatMap(p_296605_ -> { try { return DataResult.success(p_216171_.parse(p_296605_)); } catch (Exception exception) { return DataResult.error(exception::getMessage); } }, p_216171_::format); } public static MapCodec asOptionalLong(MapCodec> p_216167_) { return p_216167_.xmap(toOptionalLong, fromOptionalLong); } public static Codec> sizeLimitedMap(Codec> p_331930_, int p_328430_) { return p_331930_.validate( p_326506_ -> p_326506_.size() > p_328430_ ? DataResult.error(() -> "Map is too long: " + p_326506_.size() + ", expected range [0-" + p_328430_ + "]") : DataResult.success(p_326506_) ); } public static Codec> object2BooleanMap(Codec p_300841_) { return Codec.unboundedMap(p_300841_, Codec.BOOL).xmap(Object2BooleanOpenHashMap::new, Object2ObjectOpenHashMap::new); } @Deprecated public static MapCodec dispatchOptionalValue( final String p_311089_, final String p_310965_, final Codec p_310912_, final Function p_311760_, final Function> p_312960_ ) { return new MapCodec() { @Override public Stream keys(DynamicOps p_310901_) { return Stream.of(p_310901_.createString(p_311089_), p_310901_.createString(p_310965_)); } @Override public DataResult decode(DynamicOps p_310472_, MapLike p_310342_) { T t = p_310342_.get(p_311089_); return t == null ? DataResult.error(() -> "Missing \"" + p_311089_ + "\" in: " + p_310342_) : p_310912_.decode(p_310472_, t).flatMap(p_326527_ -> { T t1 = Objects.requireNonNullElseGet(p_310342_.get(p_310965_), p_310472_::emptyMap); return p_312960_.apply(p_326527_.getFirst()).decode(p_310472_, t1).map(Pair::getFirst); }); } @Override public RecordBuilder encode(V p_309380_, DynamicOps p_311460_, RecordBuilder p_311592_) { K k = (K)p_311760_.apply(p_309380_); p_311592_.add(p_311089_, p_310912_.encodeStart(p_311460_, k)); DataResult dataresult = this.encode((Codec)p_312960_.apply(k), p_309380_, p_311460_); if (dataresult.result().isEmpty() || !Objects.equals(dataresult.result().get(), p_311460_.emptyMap())) { p_311592_.add(p_310965_, dataresult); } return p_311592_; } private DataResult encode(Codec p_313212_, V p_310224_, DynamicOps p_311229_) { return p_313212_.encodeStart(p_311229_, (V2)p_310224_); } }; } public static Codec> optionalEmptyMap(final Codec p_329455_) { return new Codec>() { @Override public DataResult, T>> decode(DynamicOps p_331677_, T p_335846_) { return isEmptyMap(p_331677_, p_335846_) ? DataResult.success(Pair.of(Optional.empty(), p_335846_)) : p_329455_.decode(p_331677_, p_335846_).map(p_333523_ -> p_333523_.mapFirst(Optional::of)); } private static boolean isEmptyMap(DynamicOps p_336166_, T p_333395_) { Optional> optional = p_336166_.getMap(p_333395_).result(); return optional.isPresent() && optional.get().entries().findAny().isEmpty(); } public DataResult encode(Optional p_332665_, DynamicOps p_329533_, T p_335687_) { return p_332665_.isEmpty() ? DataResult.success(p_329533_.emptyMap()) : p_329455_.encode(p_332665_.get(), p_329533_, p_335687_); } }; } public static class LateBoundIdMapper { private final BiMap idToValue = HashBiMap.create(); public Codec codec(Codec p_375672_) { BiMap bimap = this.idToValue.inverse(); return ExtraCodecs.idResolverCodec(p_375672_, this.idToValue::get, bimap::get); } public ExtraCodecs.LateBoundIdMapper put(I p_378774_, V p_377522_) { Objects.requireNonNull(p_377522_, () -> "Value for " + p_378774_ + " is null"); this.idToValue.put(p_378774_, p_377522_); return this; } } public static record StrictUnboundedMapCodec(Codec keyCodec, Codec elementCodec) implements Codec>, BaseMapCodec { @Override public DataResult> decode(DynamicOps p_298061_, MapLike p_299914_) { Builder builder = ImmutableMap.builder(); for (Pair pair : p_299914_.entries().toList()) { DataResult dataresult = this.keyCodec().parse(p_298061_, pair.getFirst()); DataResult dataresult1 = this.elementCodec().parse(p_298061_, pair.getSecond()); DataResult> dataresult2 = dataresult.apply2stable(Pair::of, dataresult1); Optional>> optional = dataresult2.error(); if (optional.isPresent()) { String s = optional.get().message(); return DataResult.error(() -> dataresult.result().isPresent() ? "Map entry '" + dataresult.result().get() + "' : " + s : s); } if (!dataresult2.result().isPresent()) { return DataResult.error(() -> "Empty or invalid map contents are not allowed"); } Pair pair1 = dataresult2.result().get(); builder.put(pair1.getFirst(), pair1.getSecond()); } Map map = builder.build(); return DataResult.success(map); } @Override public DataResult, T>> decode(DynamicOps p_299262_, T p_297460_) { return p_299262_.getMap(p_297460_) .setLifecycle(Lifecycle.stable()) .flatMap(p_297301_ -> this.decode(p_299262_, (MapLike)p_297301_)) .map(p_300226_ -> Pair.of((Map)p_300226_, p_297460_)); } public DataResult encode(Map p_301091_, DynamicOps p_298442_, T p_300447_) { return this.encode(p_301091_, p_298442_, p_298442_.mapBuilder()).build(p_300447_); } @Override public String toString() { return "StrictUnboundedMapCodec[" + this.keyCodec + " -> " + this.elementCodec + "]"; } @Override public Codec keyCodec() { return this.keyCodec; } @Override public Codec elementCodec() { return this.elementCodec; } } public static record TagOrElementLocation(ResourceLocation id, boolean tag) { @Override public String toString() { return this.decoratedId(); } private String decoratedId() { return this.tag ? "#" + this.id : this.id.toString(); } } }