package net.minecraft.network.codec; 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.serialization.Codec; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.EncoderException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.OptionalInt; import java.util.UUID; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; import java.util.function.ToIntFunction; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.EndTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.Utf8String; import net.minecraft.network.VarInt; import net.minecraft.network.VarLong; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; import org.joml.Quaternionf; import org.joml.Vector3f; public interface ByteBufCodecs { int MAX_INITIAL_COLLECTION_SIZE = 65536; StreamCodec BOOL = new StreamCodec() { public Boolean decode(ByteBuf p_332480_) { return p_332480_.readBoolean(); } public void encode(ByteBuf p_332710_, Boolean p_330535_) { p_332710_.writeBoolean(p_330535_); } }; StreamCodec BYTE = new StreamCodec() { public Byte decode(ByteBuf p_332150_) { return p_332150_.readByte(); } public void encode(ByteBuf p_328538_, Byte p_327835_) { p_328538_.writeByte(p_327835_); } }; StreamCodec ROTATION_BYTE = BYTE.map(Mth::unpackDegrees, Mth::packDegrees); StreamCodec SHORT = new StreamCodec() { public Short decode(ByteBuf p_331682_) { return p_331682_.readShort(); } public void encode(ByteBuf p_329734_, Short p_332862_) { p_329734_.writeShort(p_332862_); } }; StreamCodec UNSIGNED_SHORT = new StreamCodec() { public Integer decode(ByteBuf p_333416_) { return p_333416_.readUnsignedShort(); } public void encode(ByteBuf p_334768_, Integer p_335195_) { p_334768_.writeShort(p_335195_); } }; StreamCodec INT = new StreamCodec() { public Integer decode(ByteBuf p_334363_) { return p_334363_.readInt(); } public void encode(ByteBuf p_328174_, Integer p_329350_) { p_328174_.writeInt(p_329350_); } }; StreamCodec VAR_INT = new StreamCodec() { public Integer decode(ByteBuf p_334861_) { return VarInt.read(p_334861_); } public void encode(ByteBuf p_333121_, Integer p_329976_) { VarInt.write(p_333121_, p_329976_); } }; StreamCodec OPTIONAL_VAR_INT = VAR_INT.map( p_358482_ -> p_358482_ == 0 ? OptionalInt.empty() : OptionalInt.of(p_358482_ - 1), p_358481_ -> p_358481_.isPresent() ? p_358481_.getAsInt() + 1 : 0 ); StreamCodec LONG = new StreamCodec() { public Long decode(ByteBuf p_330259_) { return p_330259_.readLong(); } public void encode(ByteBuf p_332625_, Long p_327681_) { p_332625_.writeLong(p_327681_); } }; StreamCodec VAR_LONG = new StreamCodec() { public Long decode(ByteBuf p_335511_) { return VarLong.read(p_335511_); } public void encode(ByteBuf p_331177_, Long p_364567_) { VarLong.write(p_331177_, p_364567_); } }; StreamCodec FLOAT = new StreamCodec() { public Float decode(ByteBuf p_330378_) { return p_330378_.readFloat(); } public void encode(ByteBuf p_329698_, Float p_365105_) { p_329698_.writeFloat(p_365105_); } }; StreamCodec DOUBLE = new StreamCodec() { public Double decode(ByteBuf p_331124_) { return p_331124_.readDouble(); } public void encode(ByteBuf p_327898_, Double p_363039_) { p_327898_.writeDouble(p_363039_); } }; StreamCodec BYTE_ARRAY = new StreamCodec() { public byte[] decode(ByteBuf p_333794_) { return FriendlyByteBuf.readByteArray(p_333794_); } public void encode(ByteBuf p_327981_, byte[] p_368580_) { FriendlyByteBuf.writeByteArray(p_327981_, p_368580_); } }; StreamCodec LONG_ARRAY = new StreamCodec() { public long[] decode(ByteBuf p_329846_) { return FriendlyByteBuf.readLongArray(p_329846_); } public void encode(ByteBuf p_336297_, long[] p_397679_) { FriendlyByteBuf.writeLongArray(p_336297_, p_397679_); } }; StreamCodec STRING_UTF8 = stringUtf8(32767); StreamCodec TAG = tagCodec(() -> NbtAccounter.create(2097152L)); StreamCodec TRUSTED_TAG = tagCodec(NbtAccounter::unlimitedHeap); StreamCodec COMPOUND_TAG = compoundTagCodec(() -> NbtAccounter.create(2097152L)); StreamCodec TRUSTED_COMPOUND_TAG = compoundTagCodec(NbtAccounter::unlimitedHeap); StreamCodec> OPTIONAL_COMPOUND_TAG = new StreamCodec>() { public Optional decode(ByteBuf p_328716_) { return Optional.ofNullable(FriendlyByteBuf.readNbt(p_328716_)); } public void encode(ByteBuf p_327986_, Optional p_393792_) { FriendlyByteBuf.writeNbt(p_327986_, p_393792_.orElse(null)); } }; StreamCodec VECTOR3F = new StreamCodec() { public Vector3f decode(ByteBuf p_335035_) { return FriendlyByteBuf.readVector3f(p_335035_); } public void encode(ByteBuf p_328446_, Vector3f p_394463_) { FriendlyByteBuf.writeVector3f(p_328446_, p_394463_); } }; StreamCodec QUATERNIONF = new StreamCodec() { public Quaternionf decode(ByteBuf p_331156_) { return FriendlyByteBuf.readQuaternion(p_331156_); } public void encode(ByteBuf p_328803_, Quaternionf p_392816_) { FriendlyByteBuf.writeQuaternion(p_328803_, p_392816_); } }; StreamCodec CONTAINER_ID = new StreamCodec() { public Integer decode(ByteBuf p_329844_) { return FriendlyByteBuf.readContainerId(p_329844_); } public void encode(ByteBuf p_335209_, Integer p_393774_) { FriendlyByteBuf.writeContainerId(p_335209_, p_393774_); } }; StreamCodec GAME_PROFILE_PROPERTIES = new StreamCodec() { private static final int MAX_PROPERTY_NAME_LENGTH = 64; private static final int MAX_PROPERTY_VALUE_LENGTH = 32767; private static final int MAX_PROPERTY_SIGNATURE_LENGTH = 1024; private static final int MAX_PROPERTIES = 16; public PropertyMap decode(ByteBuf p_395955_) { int i = ByteBufCodecs.readCount(p_395955_, 16); PropertyMap propertymap = new PropertyMap(); for (int j = 0; j < i; j++) { String s = Utf8String.read(p_395955_, 64); String s1 = Utf8String.read(p_395955_, 32767); String s2 = FriendlyByteBuf.readNullable(p_395955_, p_392203_ -> Utf8String.read(p_392203_, 1024)); Property property = new Property(s, s1, s2); propertymap.put(property.name(), property); } return propertymap; } public void encode(ByteBuf p_395895_, PropertyMap p_393829_) { ByteBufCodecs.writeCount(p_395895_, p_393829_.size(), 16); for (Property property : p_393829_.values()) { Utf8String.write(p_395895_, property.name(), 64); Utf8String.write(p_395895_, property.value(), 32767); FriendlyByteBuf.writeNullable(p_395895_, property.signature(), (p_392569_, p_396118_) -> Utf8String.write(p_392569_, p_396118_, 1024)); } } }; StreamCodec GAME_PROFILE = new StreamCodec() { public GameProfile decode(ByteBuf p_397129_) { UUID uuid = UUIDUtil.STREAM_CODEC.decode(p_397129_); String s = Utf8String.read(p_397129_, 16); GameProfile gameprofile = new GameProfile(uuid, s); gameprofile.getProperties().putAll(ByteBufCodecs.GAME_PROFILE_PROPERTIES.decode(p_397129_)); return gameprofile; } public void encode(ByteBuf p_393289_, GameProfile p_397987_) { UUIDUtil.STREAM_CODEC.encode(p_393289_, p_397987_.getId()); Utf8String.write(p_393289_, p_397987_.getName(), 16); ByteBufCodecs.GAME_PROFILE_PROPERTIES.encode(p_393289_, p_397987_.getProperties()); } }; static StreamCodec byteArray(final int p_329369_) { return new StreamCodec() { public byte[] decode(ByteBuf p_330658_) { return FriendlyByteBuf.readByteArray(p_330658_, p_329369_); } public void encode(ByteBuf p_332407_, byte[] p_327934_) { if (p_327934_.length > p_329369_) { throw new EncoderException("ByteArray with size " + p_327934_.length + " is bigger than allowed " + p_329369_); } else { FriendlyByteBuf.writeByteArray(p_332407_, p_327934_); } } }; } static StreamCodec stringUtf8(final int p_332577_) { return new StreamCodec() { public String decode(ByteBuf p_363937_) { return Utf8String.read(p_363937_, p_332577_); } public void encode(ByteBuf p_367629_, String p_392026_) { Utf8String.write(p_367629_, p_392026_, p_332577_); } }; } static StreamCodec tagCodec(final Supplier p_334674_) { return new StreamCodec() { public Tag decode(ByteBuf p_397230_) { Tag tag = FriendlyByteBuf.readNbt(p_397230_, p_334674_.get()); if (tag == null) { throw new DecoderException("Expected non-null compound tag"); } else { return tag; } } public void encode(ByteBuf p_397825_, Tag p_393534_) { if (p_393534_ == EndTag.INSTANCE) { throw new EncoderException("Expected non-null compound tag"); } else { FriendlyByteBuf.writeNbt(p_397825_, p_393534_); } } }; } static StreamCodec compoundTagCodec(Supplier p_334293_) { return tagCodec(p_334293_).map(p_329005_ -> { if (p_329005_ instanceof CompoundTag compoundtag) { return compoundtag; } else { throw new DecoderException("Not a compound tag: " + p_329005_); } }, p_331817_ -> (Tag)p_331817_); } static StreamCodec fromCodecTrusted(Codec p_332454_) { return fromCodec(p_332454_, NbtAccounter::unlimitedHeap); } static StreamCodec fromCodec(Codec p_330766_) { return fromCodec(p_330766_, () -> NbtAccounter.create(2097152L)); } static StreamCodec fromCodec(Codec p_332152_, Supplier p_333221_) { return tagCodec(p_333221_) .map( p_328837_ -> p_332152_.parse(NbtOps.INSTANCE, p_328837_) .getOrThrow(p_328190_ -> new DecoderException("Failed to decode: " + p_328190_ + " " + p_328837_)), p_329084_ -> p_332152_.encodeStart(NbtOps.INSTANCE, (T)p_329084_) .getOrThrow(p_332410_ -> new EncoderException("Failed to encode: " + p_332410_ + " " + p_329084_)) ); } static StreamCodec fromCodecWithRegistriesTrusted(Codec p_331690_) { return fromCodecWithRegistries(p_331690_, NbtAccounter::unlimitedHeap); } static StreamCodec fromCodecWithRegistries(Codec p_334037_) { return fromCodecWithRegistries(p_334037_, () -> NbtAccounter.create(2097152L)); } static StreamCodec fromCodecWithRegistries(final Codec p_332747_, Supplier p_329046_) { final StreamCodec streamcodec = tagCodec(p_329046_); return new StreamCodec() { public T decode(RegistryFriendlyByteBuf p_391179_) { Tag tag = streamcodec.decode(p_391179_); RegistryOps registryops = p_391179_.registryAccess().createSerializationContext(NbtOps.INSTANCE); return p_332747_.parse(registryops, tag).getOrThrow(p_395940_ -> new DecoderException("Failed to decode: " + p_395940_ + " " + tag)); } public void encode(RegistryFriendlyByteBuf p_397169_, T p_396882_) { RegistryOps registryops = p_397169_.registryAccess().createSerializationContext(NbtOps.INSTANCE); Tag tag = p_332747_.encodeStart(registryops, p_396882_) .getOrThrow(p_392233_ -> new EncoderException("Failed to encode: " + p_392233_ + " " + p_396882_)); streamcodec.encode(p_397169_, tag); } }; } static StreamCodec> optional(final StreamCodec p_333614_) { return new StreamCodec>() { public Optional decode(B p_336330_) { return p_336330_.readBoolean() ? Optional.of(p_333614_.decode(p_336330_)) : Optional.empty(); } public void encode(B p_329166_, Optional p_391573_) { if (p_391573_.isPresent()) { p_329166_.writeBoolean(true); p_333614_.encode(p_329166_, p_391573_.get()); } else { p_329166_.writeBoolean(false); } } }; } static int readCount(ByteBuf p_335948_, int p_329745_) { int i = VarInt.read(p_335948_); if (i > p_329745_) { throw new DecoderException(i + " elements exceeded max size of: " + p_329745_); } else { return i; } } static void writeCount(ByteBuf p_332743_, int p_332779_, int p_330804_) { if (p_332779_ > p_330804_) { throw new EncoderException(p_332779_ + " elements exceeded max size of: " + p_330804_); } else { VarInt.write(p_332743_, p_332779_); } } static > StreamCodec collection(IntFunction p_329603_, StreamCodec p_335274_) { return collection(p_329603_, p_335274_, Integer.MAX_VALUE); } static > StreamCodec collection( final IntFunction p_330282_, final StreamCodec p_329504_, final int p_331395_ ) { return new StreamCodec() { public C decode(B p_328010_) { int i = ByteBufCodecs.readCount(p_328010_, p_331395_); C c = p_330282_.apply(Math.min(i, 65536)); for (int j = 0; j < i; j++) { c.add(p_329504_.decode(p_328010_)); } return c; } public void encode(B p_335266_, C p_391188_) { ByteBufCodecs.writeCount(p_335266_, p_391188_.size(), p_331395_); for (V v : p_391188_) { p_329504_.encode(p_335266_, v); } } }; } static > StreamCodec.CodecOperation collection(IntFunction p_333333_) { return p_331526_ -> collection(p_333333_, p_331526_); } static StreamCodec.CodecOperation> list() { return p_331787_ -> collection(ArrayList::new, p_331787_); } static StreamCodec.CodecOperation> list(int p_331728_) { return p_328420_ -> collection(ArrayList::new, p_328420_, p_331728_); } static > StreamCodec map( IntFunction p_329613_, StreamCodec p_335749_, StreamCodec p_332695_ ) { return map(p_329613_, p_335749_, p_332695_, Integer.MAX_VALUE); } static > StreamCodec map( final IntFunction p_331225_, final StreamCodec p_334555_, final StreamCodec p_330391_, final int p_331122_ ) { return new StreamCodec() { public void encode(B p_362090_, M p_396250_) { ByteBufCodecs.writeCount(p_362090_, p_396250_.size(), p_331122_); p_396250_.forEach((p_389932_, p_389933_) -> { p_334555_.encode(p_362090_, (K)p_389932_); p_330391_.encode(p_362090_, (V)p_389933_); }); } public M decode(B p_365796_) { int i = ByteBufCodecs.readCount(p_365796_, p_331122_); M m = (M)p_331225_.apply(Math.min(i, 65536)); for (int j = 0; j < i; j++) { K k = p_334555_.decode(p_365796_); V v = p_330391_.decode(p_365796_); m.put(k, v); } return m; } }; } static StreamCodec> either( final StreamCodec p_330563_, final StreamCodec p_328664_ ) { return new StreamCodec>() { public Either decode(B p_368316_) { return p_368316_.readBoolean() ? Either.left(p_330563_.decode(p_368316_)) : Either.right(p_328664_.decode(p_368316_)); } public void encode(B p_361972_, Either p_394208_) { p_394208_.ifLeft(p_392082_ -> { p_361972_.writeBoolean(true); p_330563_.encode(p_361972_, (L)p_392082_); }).ifRight(p_392370_ -> { p_361972_.writeBoolean(false); p_328664_.encode(p_361972_, (R)p_392370_); }); } }; } static StreamCodec.CodecOperation lengthPrefixed(int p_393461_, BiFunction p_397581_) { return p_389928_ -> new StreamCodec() { public V decode(B p_391476_) { int i = VarInt.read(p_391476_); if (i > p_393461_) { throw new DecoderException("Buffer size " + i + " is larger than allowed limit of " + p_393461_); } else { int j = p_391476_.readerIndex(); B b = (B)((ByteBuf)p_397581_.apply(p_391476_, p_391476_.slice(j, i))); p_391476_.readerIndex(j + i); return (V)p_389928_.decode(b); } } public void encode(B p_391889_, V p_362272_) { B b = (B)((ByteBuf)p_397581_.apply(p_391889_, p_391889_.alloc().buffer())); try { p_389928_.encode(b, p_362272_); int i = b.readableBytes(); if (i > p_393461_) { throw new EncoderException("Buffer size " + i + " is larger than allowed limit of " + p_393461_); } VarInt.write(p_391889_, i); p_391889_.writeBytes(b); } finally { b.release(); } } }; } static StreamCodec.CodecOperation lengthPrefixed(int p_396380_) { return lengthPrefixed(p_396380_, (p_389924_, p_389925_) -> new RegistryFriendlyByteBuf(p_389925_, p_389924_.registryAccess())); } static StreamCodec idMapper(final IntFunction p_333433_, final ToIntFunction p_334959_) { return new StreamCodec() { public T decode(ByteBuf p_393204_) { int i = VarInt.read(p_393204_); return p_333433_.apply(i); } public void encode(ByteBuf p_391372_, T p_394895_) { int i = p_334959_.applyAsInt(p_394895_); VarInt.write(p_391372_, i); } }; } static StreamCodec idMapper(IdMap p_332036_) { return idMapper(p_332036_::byIdOrThrow, p_332036_::getIdOrThrow); } private static StreamCodec registry( final ResourceKey> p_332046_, final Function, IdMap> p_332827_ ) { return new StreamCodec() { private IdMap getRegistryOrThrow(RegistryFriendlyByteBuf p_391225_) { return p_332827_.apply(p_391225_.registryAccess().lookupOrThrow(p_332046_)); } public R decode(RegistryFriendlyByteBuf p_362854_) { int i = VarInt.read(p_362854_); return (R)this.getRegistryOrThrow(p_362854_).byIdOrThrow(i); } public void encode(RegistryFriendlyByteBuf p_362273_, R p_391276_) { int i = this.getRegistryOrThrow(p_362273_).getIdOrThrow(p_391276_); VarInt.write(p_362273_, i); } }; } static StreamCodec registry(ResourceKey> p_332712_) { return registry(p_332712_, p_335792_ -> p_335792_); } static StreamCodec> holderRegistry(ResourceKey> p_332639_) { return registry(p_332639_, Registry::asHolderIdMap); } static StreamCodec> holder( final ResourceKey> p_335347_, final StreamCodec p_329304_ ) { return new StreamCodec>() { private static final int DIRECT_HOLDER_ID = 0; private IdMap> getRegistryOrThrow(RegistryFriendlyByteBuf p_393125_) { return p_393125_.registryAccess().lookupOrThrow(p_335347_).asHolderIdMap(); } public Holder decode(RegistryFriendlyByteBuf p_393260_) { int i = VarInt.read(p_393260_); return i == 0 ? Holder.direct(p_329304_.decode(p_393260_)) : (Holder)this.getRegistryOrThrow(p_393260_).byIdOrThrow(i - 1); } public void encode(RegistryFriendlyByteBuf p_392751_, Holder p_397139_) { switch (p_397139_.kind()) { case REFERENCE: int i = this.getRegistryOrThrow(p_392751_).getIdOrThrow(p_397139_); VarInt.write(p_392751_, i + 1); break; case DIRECT: VarInt.write(p_392751_, 0); p_329304_.encode(p_392751_, p_397139_.value()); } } }; } static StreamCodec> holderSet(final ResourceKey> p_328506_) { return new StreamCodec>() { private static final int NAMED_SET = -1; private final StreamCodec> holderCodec = ByteBufCodecs.holderRegistry(p_328506_); public HolderSet decode(RegistryFriendlyByteBuf p_391777_) { int i = VarInt.read(p_391777_) - 1; if (i == -1) { Registry registry = p_391777_.registryAccess().lookupOrThrow(p_328506_); return registry.get(TagKey.create(p_328506_, ResourceLocation.STREAM_CODEC.decode(p_391777_))).orElseThrow(); } else { List> list = new ArrayList<>(Math.min(i, 65536)); for (int j = 0; j < i; j++) { list.add(this.holderCodec.decode(p_391777_)); } return HolderSet.direct(list); } } public void encode(RegistryFriendlyByteBuf p_393392_, HolderSet p_396616_) { Optional> optional = p_396616_.unwrapKey(); if (optional.isPresent()) { VarInt.write(p_393392_, 0); ResourceLocation.STREAM_CODEC.encode(p_393392_, optional.get().location()); } else { VarInt.write(p_393392_, p_396616_.size() + 1); for (Holder holder : p_396616_) { this.holderCodec.encode(p_393392_, holder); } } } }; } }