package net.minecraft.resources; 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.DynamicOps; import java.util.ArrayList; import java.util.List; import java.util.Optional; import net.minecraft.core.Holder; import net.minecraft.core.HolderGetter; import net.minecraft.core.HolderOwner; import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.tags.TagKey; import net.minecraft.util.ExtraCodecs; public class HolderSetCodec implements Codec> { private final ResourceKey> registryKey; private final Codec> elementCodec; private final Codec>> homogenousListCodec; private final Codec, List>>> registryAwareCodec; private static Codec>> homogenousList(Codec> p_206668_, boolean p_206669_) { Codec>> codec = p_206668_.listOf().validate(ExtraCodecs.ensureHomogenous(Holder::kind)); return p_206669_ ? codec : ExtraCodecs.compactListCodec(p_206668_, codec); } public static Codec> create(ResourceKey> p_206686_, Codec> p_206687_, boolean p_206688_) { return new HolderSetCodec<>(p_206686_, p_206687_, p_206688_); } private HolderSetCodec(ResourceKey> p_206660_, Codec> p_206661_, boolean p_206662_) { this.registryKey = p_206660_; this.elementCodec = p_206661_; this.homogenousListCodec = homogenousList(p_206661_, p_206662_); this.registryAwareCodec = Codec.either(TagKey.hashedCodec(p_206660_), this.homogenousListCodec); } @Override public DataResult, T>> decode(DynamicOps p_206696_, T p_206697_) { if (p_206696_ instanceof RegistryOps registryops) { Optional> optional = registryops.getter(this.registryKey); if (optional.isPresent()) { HolderGetter holdergetter = optional.get(); return this.registryAwareCodec .decode(p_206696_, p_206697_) .flatMap( p_326147_ -> { DataResult> dataresult = p_326147_.getFirst() .map( p_326145_ -> lookupTag(holdergetter, (TagKey)p_326145_), p_326140_ -> DataResult.success(HolderSet.direct((List>)p_326140_)) ); return dataresult.map(p_326149_ -> Pair.of((HolderSet)p_326149_, (T)p_326147_.getSecond())); } ); } } return this.decodeWithoutRegistry(p_206696_, p_206697_); } private static DataResult> lookupTag(HolderGetter p_331398_, TagKey p_328227_) { return (DataResult)p_331398_.get(p_328227_) .map(DataResult::success) .orElseGet(() -> DataResult.error(() -> "Missing tag: '" + p_328227_.location() + "' in '" + p_328227_.registry().location() + "'")); } public DataResult encode(HolderSet p_206674_, DynamicOps p_206675_, T p_206676_) { if (p_206675_ instanceof RegistryOps registryops) { Optional> optional = registryops.owner(this.registryKey); if (optional.isPresent()) { if (!p_206674_.canSerializeIn(optional.get())) { return DataResult.error(() -> "HolderSet " + p_206674_ + " is not valid in current registry set"); } return this.registryAwareCodec.encode(p_206674_.unwrap().mapRight(List::copyOf), p_206675_, p_206676_); } } return this.encodeWithoutRegistry(p_206674_, p_206675_, p_206676_); } private DataResult, T>> decodeWithoutRegistry(DynamicOps p_206671_, T p_206672_) { return this.elementCodec.listOf().decode(p_206671_, p_206672_).flatMap(p_206666_ -> { List> list = new ArrayList<>(); for (Holder holder : p_206666_.getFirst()) { if (!(holder instanceof Holder.Direct direct)) { return DataResult.error(() -> "Can't decode element " + holder + " without registry"); } list.add(direct); } return DataResult.success(new Pair<>(HolderSet.direct(list), p_206666_.getSecond())); }); } private DataResult encodeWithoutRegistry(HolderSet p_206690_, DynamicOps p_206691_, T p_206692_) { return this.homogenousListCodec.encode(p_206690_.stream().toList(), p_206691_, p_206692_); } }