package net.minecraft.world.item; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import java.util.Optional; import java.util.function.Function; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.Registry; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceKey; public record EitherHolder(Optional> holder, ResourceKey key) { public EitherHolder(Holder holder) { this(Optional.of(holder), (ResourceKey)holder.unwrapKey().orElseThrow()); } public EitherHolder(ResourceKey key) { this(Optional.empty(), key); } public static Codec> codec(ResourceKey> registryKey, Codec> codec) { return Codec.either( codec, ResourceKey.codec(registryKey).comapFlatMap(resourceKey -> DataResult.error(() -> "Cannot parse as key without registry"), Function.identity()) ) .xmap(EitherHolder::fromEither, EitherHolder::asEither); } public static StreamCodec> streamCodec( ResourceKey> registryKey, StreamCodec> streamCodec ) { return StreamCodec.composite(ByteBufCodecs.either(streamCodec, ResourceKey.streamCodec(registryKey)), EitherHolder::asEither, EitherHolder::fromEither); } public Either, ResourceKey> asEither() { return (Either, ResourceKey>)this.holder.map(Either::left).orElseGet(() -> Either.right(this.key)); } public static EitherHolder fromEither(Either, ResourceKey> either) { return either.map(EitherHolder::new, EitherHolder::new); } public Optional unwrap(Registry registry) { return this.holder.map(Holder::value).or(() -> registry.getOptional(this.key)); } public Optional> unwrap(HolderLookup.Provider registries) { return this.holder.or(() -> registries.lookupOrThrow(this.key.registryKey()).get(this.key)); } }