/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.ImmutableMultimap * com.google.common.collect.ImmutableMultimap$Builder * com.google.common.collect.Multimap * com.google.gson.Gson * com.google.gson.GsonBuilder * com.google.gson.JsonElement * com.google.gson.JsonSyntaxException * com.mojang.authlib.GameProfile * com.mojang.authlib.properties.Property * com.mojang.authlib.properties.PropertyMap * com.mojang.datafixers.util.Either * com.mojang.serialization.Codec * com.mojang.serialization.DynamicOps * io.netty.buffer.ByteBuf * io.netty.handler.codec.DecoderException * io.netty.handler.codec.EncoderException * org.joml.Quaternionfc * org.joml.Vector3fc */ package net.minecraft.network.codec; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonSyntaxException; 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 com.mojang.serialization.DynamicOps; 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.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.HolderLookup; 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.network.codec.StreamCodec; import net.minecraft.resources.Identifier; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.tags.TagKey; import net.minecraft.util.ARGB; import net.minecraft.util.LenientJsonParser; import net.minecraft.util.Mth; import org.joml.Quaternionfc; import org.joml.Vector3fc; public interface ByteBufCodecs { public static final int MAX_INITIAL_COLLECTION_SIZE = 65536; public static final StreamCodec BOOL = new StreamCodec(){ @Override public Boolean decode(ByteBuf input) { return input.readBoolean(); } @Override public void encode(ByteBuf output, Boolean value) { output.writeBoolean(value.booleanValue()); } }; public static final StreamCodec BYTE = new StreamCodec(){ @Override public Byte decode(ByteBuf input) { return input.readByte(); } @Override public void encode(ByteBuf output, Byte value) { output.writeByte((int)value.byteValue()); } }; public static final StreamCodec ROTATION_BYTE = BYTE.map(Mth::unpackDegrees, Mth::packDegrees); public static final StreamCodec SHORT = new StreamCodec(){ @Override public Short decode(ByteBuf input) { return input.readShort(); } @Override public void encode(ByteBuf output, Short value) { output.writeShort((int)value.shortValue()); } }; public static final StreamCodec UNSIGNED_SHORT = new StreamCodec(){ @Override public Integer decode(ByteBuf input) { return input.readUnsignedShort(); } @Override public void encode(ByteBuf output, Integer value) { output.writeShort(value.intValue()); } }; public static final StreamCodec INT = new StreamCodec(){ @Override public Integer decode(ByteBuf input) { return input.readInt(); } @Override public void encode(ByteBuf output, Integer value) { output.writeInt(value.intValue()); } }; public static final StreamCodec VAR_INT = new StreamCodec(){ @Override public Integer decode(ByteBuf input) { return VarInt.read(input); } @Override public void encode(ByteBuf output, Integer value) { VarInt.write(output, value); } }; public static final StreamCodec OPTIONAL_VAR_INT = VAR_INT.map(i -> i == 0 ? OptionalInt.empty() : OptionalInt.of(i - 1), o -> o.isPresent() ? o.getAsInt() + 1 : 0); public static final StreamCodec LONG = new StreamCodec(){ @Override public Long decode(ByteBuf input) { return input.readLong(); } @Override public void encode(ByteBuf output, Long value) { output.writeLong(value.longValue()); } }; public static final StreamCodec VAR_LONG = new StreamCodec(){ @Override public Long decode(ByteBuf input) { return VarLong.read(input); } @Override public void encode(ByteBuf output, Long value) { VarLong.write(output, value); } }; public static final StreamCodec FLOAT = new StreamCodec(){ @Override public Float decode(ByteBuf input) { return Float.valueOf(input.readFloat()); } @Override public void encode(ByteBuf output, Float value) { output.writeFloat(value.floatValue()); } }; public static final StreamCodec DOUBLE = new StreamCodec(){ @Override public Double decode(ByteBuf input) { return input.readDouble(); } @Override public void encode(ByteBuf output, Double value) { output.writeDouble(value.doubleValue()); } }; public static final StreamCodec BYTE_ARRAY = new StreamCodec(){ @Override public byte[] decode(ByteBuf input) { return FriendlyByteBuf.readByteArray(input); } @Override public void encode(ByteBuf output, byte[] value) { FriendlyByteBuf.writeByteArray(output, value); } }; public static final StreamCodec LONG_ARRAY = new StreamCodec(){ @Override public long[] decode(ByteBuf input) { return FriendlyByteBuf.readLongArray(input); } @Override public void encode(ByteBuf output, long[] value) { FriendlyByteBuf.writeLongArray(output, value); } }; public static final StreamCodec STRING_UTF8 = ByteBufCodecs.stringUtf8(Short.MAX_VALUE); public static final StreamCodec TAG = ByteBufCodecs.tagCodec(() -> NbtAccounter.create(0x200000L)); public static final StreamCodec TRUSTED_TAG = ByteBufCodecs.tagCodec(NbtAccounter::unlimitedHeap); public static final StreamCodec COMPOUND_TAG = ByteBufCodecs.compoundTagCodec(() -> NbtAccounter.create(0x200000L)); public static final StreamCodec TRUSTED_COMPOUND_TAG = ByteBufCodecs.compoundTagCodec(NbtAccounter::unlimitedHeap); public static final StreamCodec> OPTIONAL_COMPOUND_TAG = new StreamCodec>(){ @Override public Optional decode(ByteBuf input) { return Optional.ofNullable(FriendlyByteBuf.readNbt(input)); } @Override public void encode(ByteBuf output, Optional value) { FriendlyByteBuf.writeNbt(output, value.orElse(null)); } }; public static final StreamCodec VECTOR3F = new StreamCodec(){ @Override public Vector3fc decode(ByteBuf input) { return FriendlyByteBuf.readVector3f(input); } @Override public void encode(ByteBuf output, Vector3fc value) { FriendlyByteBuf.writeVector3f(output, value); } }; public static final StreamCodec QUATERNIONF = new StreamCodec(){ @Override public Quaternionfc decode(ByteBuf input) { return FriendlyByteBuf.readQuaternion(input); } @Override public void encode(ByteBuf output, Quaternionfc value) { FriendlyByteBuf.writeQuaternion(output, value); } }; public static final StreamCodec CONTAINER_ID = new StreamCodec(){ @Override public Integer decode(ByteBuf input) { return FriendlyByteBuf.readContainerId(input); } @Override public void encode(ByteBuf output, Integer value) { FriendlyByteBuf.writeContainerId(output, value); } }; public static final StreamCodec GAME_PROFILE_PROPERTIES = new StreamCodec(){ private static final int MAX_PROPERTY_NAME_LENGTH = 64; private static final int MAX_PROPERTY_VALUE_LENGTH = Short.MAX_VALUE; private static final int MAX_PROPERTY_SIGNATURE_LENGTH = 1024; private static final int MAX_PROPERTIES = 16; @Override public PropertyMap decode(ByteBuf input) { int propertyCount = ByteBufCodecs.readCount(input, 16); ImmutableMultimap.Builder result = ImmutableMultimap.builder(); for (int i = 0; i < propertyCount; ++i) { String name = Utf8String.read(input, 64); String value = Utf8String.read(input, Short.MAX_VALUE); String signature = FriendlyByteBuf.readNullable(input, in -> Utf8String.read(in, 1024)); Property property = new Property(name, value, signature); result.put((Object)property.name(), (Object)property); } return new PropertyMap((Multimap)result.build()); } @Override public void encode(ByteBuf output, PropertyMap properties) { ByteBufCodecs.writeCount(output, properties.size(), 16); for (Property property : properties.values()) { Utf8String.write(output, property.name(), 64); Utf8String.write(output, property.value(), Short.MAX_VALUE); FriendlyByteBuf.writeNullable(output, property.signature(), (out, signature) -> Utf8String.write(out, signature, 1024)); } } }; public static final StreamCodec PLAYER_NAME = ByteBufCodecs.stringUtf8(16); public static final StreamCodec GAME_PROFILE = StreamCodec.composite(UUIDUtil.STREAM_CODEC, GameProfile::id, PLAYER_NAME, GameProfile::name, GAME_PROFILE_PROPERTIES, GameProfile::properties, GameProfile::new); public static final StreamCodec RGB_COLOR = new StreamCodec(){ @Override public Integer decode(ByteBuf input) { return ARGB.color(input.readByte() & 0xFF, input.readByte() & 0xFF, input.readByte() & 0xFF); } @Override public void encode(ByteBuf output, Integer value) { output.writeByte(ARGB.red(value)); output.writeByte(ARGB.green(value)); output.writeByte(ARGB.blue(value)); } }; public static StreamCodec byteArray(final int maxSize) { return new StreamCodec(){ @Override public byte[] decode(ByteBuf input) { return FriendlyByteBuf.readByteArray(input, maxSize); } @Override public void encode(ByteBuf output, byte[] value) { if (value.length > maxSize) { throw new EncoderException("ByteArray with size " + value.length + " is bigger than allowed " + maxSize); } FriendlyByteBuf.writeByteArray(output, value); } }; } public static StreamCodec stringUtf8(final int maxStringLength) { return new StreamCodec(){ @Override public String decode(ByteBuf input) { return Utf8String.read(input, maxStringLength); } @Override public void encode(ByteBuf output, String value) { Utf8String.write(output, value, maxStringLength); } }; } public static StreamCodec> optionalTagCodec(final Supplier accounter) { return new StreamCodec>(){ @Override public Optional decode(ByteBuf input) { return Optional.ofNullable(FriendlyByteBuf.readNbt(input, (NbtAccounter)accounter.get())); } @Override public void encode(ByteBuf output, Optional value) { FriendlyByteBuf.writeNbt(output, value.orElse(null)); } }; } public static StreamCodec tagCodec(final Supplier accounter) { return new StreamCodec(){ @Override public Tag decode(ByteBuf input) { Tag result = FriendlyByteBuf.readNbt(input, (NbtAccounter)accounter.get()); if (result == null) { throw new DecoderException("Expected non-null compound tag"); } return result; } @Override public void encode(ByteBuf output, Tag value) { if (value == EndTag.INSTANCE) { throw new EncoderException("Expected non-null compound tag"); } FriendlyByteBuf.writeNbt(output, value); } }; } public static StreamCodec compoundTagCodec(Supplier accounter) { return ByteBufCodecs.tagCodec(accounter).map(tag -> { if (tag instanceof CompoundTag) { CompoundTag compoundTag = (CompoundTag)tag; return compoundTag; } throw new DecoderException("Not a compound tag: " + String.valueOf(tag)); }, compoundTag -> compoundTag); } public static StreamCodec fromCodecTrusted(Codec codec) { return ByteBufCodecs.fromCodec(codec, NbtAccounter::unlimitedHeap); } public static StreamCodec fromCodec(Codec codec) { return ByteBufCodecs.fromCodec(codec, () -> NbtAccounter.create(0x200000L)); } public static StreamCodec.CodecOperation fromCodec(final DynamicOps ops, final Codec codec) { return original -> new StreamCodec(){ @Override public V decode(B input) { Object payload = original.decode(input); return codec.parse(ops, payload).getOrThrow(msg -> new DecoderException("Failed to decode: " + msg + " " + String.valueOf(payload))); } @Override public void encode(B output, V value) { Object payload = codec.encodeStart(ops, value).getOrThrow(msg -> new EncoderException("Failed to encode: " + msg + " " + String.valueOf(value))); original.encode(output, payload); } }; } public static StreamCodec fromCodec(Codec codec, Supplier accounter) { return ByteBufCodecs.tagCodec(accounter).apply(ByteBufCodecs.fromCodec(NbtOps.INSTANCE, codec)); } public static StreamCodec fromCodecWithRegistriesTrusted(Codec codec) { return ByteBufCodecs.fromCodecWithRegistries(codec, NbtAccounter::unlimitedHeap); } public static StreamCodec fromCodecWithRegistries(Codec codec) { return ByteBufCodecs.fromCodecWithRegistries(codec, () -> NbtAccounter.create(0x200000L)); } public static StreamCodec fromCodecWithRegistries(final Codec codec, Supplier accounter) { final StreamCodec tagCodec = ByteBufCodecs.tagCodec(accounter); return new StreamCodec(){ @Override public T decode(RegistryFriendlyByteBuf input) { Tag tag = (Tag)tagCodec.decode(input); RegistryOps ops = input.registryAccess().createSerializationContext(NbtOps.INSTANCE); return codec.parse(ops, (Object)tag).getOrThrow(msg -> new DecoderException("Failed to decode: " + msg + " " + String.valueOf(tag))); } @Override public void encode(RegistryFriendlyByteBuf output, T value) { RegistryOps ops = output.registryAccess().createSerializationContext(NbtOps.INSTANCE); Tag tag = (Tag)codec.encodeStart(ops, value).getOrThrow(msg -> new EncoderException("Failed to encode: " + msg + " " + String.valueOf(value))); tagCodec.encode(output, tag); } }; } public static StreamCodec> optional(final StreamCodec original) { return new StreamCodec>(){ @Override public Optional decode(B input) { if (input.readBoolean()) { return Optional.of(original.decode(input)); } return Optional.empty(); } @Override public void encode(B output, Optional value) { if (value.isPresent()) { output.writeBoolean(true); original.encode(output, value.get()); } else { output.writeBoolean(false); } } }; } public static int readCount(ByteBuf input, int maxSize) { int count = VarInt.read(input); if (count > maxSize) { throw new DecoderException(count + " elements exceeded max size of: " + maxSize); } return count; } public static void writeCount(ByteBuf output, int count, int maxSize) { if (count > maxSize) { throw new EncoderException(count + " elements exceeded max size of: " + maxSize); } VarInt.write(output, count); } public static > StreamCodec collection(IntFunction constructor, StreamCodec elementCodec) { return ByteBufCodecs.collection(constructor, elementCodec, Integer.MAX_VALUE); } public static > StreamCodec collection(final IntFunction constructor, final StreamCodec elementCodec, final int maxSize) { return new StreamCodec(){ @Override public C decode(B input) { int count = ByteBufCodecs.readCount(input, maxSize); Collection result = (Collection)constructor.apply(Math.min(count, 65536)); for (int i = 0; i < count; ++i) { result.add(elementCodec.decode(input)); } return result; } @Override public void encode(B output, C value) { ByteBufCodecs.writeCount(output, value.size(), maxSize); for (Object element : value) { elementCodec.encode(output, element); } } }; } public static > StreamCodec.CodecOperation collection(IntFunction constructor) { return original -> ByteBufCodecs.collection(constructor, original); } public static StreamCodec.CodecOperation> list() { return original -> ByteBufCodecs.collection(ArrayList::new, original); } public static StreamCodec.CodecOperation> list(int maxSize) { return original -> ByteBufCodecs.collection(ArrayList::new, original, maxSize); } public static > StreamCodec map(IntFunction constructor, StreamCodec keyCodec, StreamCodec valueCodec) { return ByteBufCodecs.map(constructor, keyCodec, valueCodec, Integer.MAX_VALUE); } public static > StreamCodec map(final IntFunction constructor, final StreamCodec keyCodec, final StreamCodec valueCodec, final int maxSize) { return new StreamCodec(){ @Override public void encode(B output, M map) { ByteBufCodecs.writeCount(output, map.size(), maxSize); map.forEach((k, v) -> { keyCodec.encode(output, k); valueCodec.encode(output, v); }); } @Override public M decode(B input) { int count = ByteBufCodecs.readCount(input, maxSize); Map result = (Map)constructor.apply(Math.min(count, 65536)); for (int i = 0; i < count; ++i) { Object key = keyCodec.decode(input); Object value = valueCodec.decode(input); result.put(key, value); } return result; } }; } public static StreamCodec> either(final StreamCodec leftCodec, final StreamCodec rightCodec) { return new StreamCodec>(){ @Override public Either decode(B input) { if (input.readBoolean()) { return Either.left(leftCodec.decode(input)); } return Either.right(rightCodec.decode(input)); } @Override public void encode(B output, Either value) { value.ifLeft(left -> { output.writeBoolean(true); leftCodec.encode(output, left); }).ifRight(right -> { output.writeBoolean(false); rightCodec.encode(output, right); }); } }; } public static StreamCodec.CodecOperation lengthPrefixed(final int maxSize, final BiFunction decorator) { return original -> new StreamCodec(){ @Override public V decode(B input) { int size = VarInt.read(input); if (size > maxSize) { throw new DecoderException("Buffer size " + size + " is larger than allowed limit of " + maxSize); } int index = input.readerIndex(); ByteBuf limitedSlice = (ByteBuf)decorator.apply(input, input.slice(index, size)); input.readerIndex(index + size); return original.decode(limitedSlice); } /* * WARNING - Removed try catching itself - possible behaviour change. */ @Override public void encode(B output, V value) { ByteBuf scratchBuffer = (ByteBuf)decorator.apply(output, output.alloc().buffer()); try { original.encode(scratchBuffer, value); int size = scratchBuffer.readableBytes(); if (size > maxSize) { throw new EncoderException("Buffer size " + size + " is larger than allowed limit of " + maxSize); } VarInt.write(output, size); output.writeBytes(scratchBuffer); } finally { scratchBuffer.release(); } } }; } public static StreamCodec.CodecOperation lengthPrefixed(int maxSize) { return ByteBufCodecs.lengthPrefixed(maxSize, (parent, child) -> child); } public static StreamCodec.CodecOperation registryFriendlyLengthPrefixed(int maxSize) { return ByteBufCodecs.lengthPrefixed(maxSize, (parent, child) -> new RegistryFriendlyByteBuf((ByteBuf)child, parent.registryAccess())); } public static StreamCodec idMapper(final IntFunction byId, final ToIntFunction toId) { return new StreamCodec(){ @Override public T decode(ByteBuf input) { int id = VarInt.read(input); return byId.apply(id); } @Override public void encode(ByteBuf output, T value) { int id = toId.applyAsInt(value); VarInt.write(output, id); } }; } public static StreamCodec idMapper(IdMap mapper) { return ByteBufCodecs.idMapper(mapper::byIdOrThrow, mapper::getIdOrThrow); } private static StreamCodec registry(final ResourceKey> registryKey, final Function, IdMap> mapExtractor) { return new StreamCodec(){ private IdMap getRegistryOrThrow(RegistryFriendlyByteBuf input) { return (IdMap)mapExtractor.apply(input.registryAccess().lookupOrThrow(registryKey)); } @Override public R decode(RegistryFriendlyByteBuf input) { int id = VarInt.read(input); return this.getRegistryOrThrow(input).byIdOrThrow(id); } @Override public void encode(RegistryFriendlyByteBuf output, R value) { int id = this.getRegistryOrThrow(output).getIdOrThrow(value); VarInt.write(output, id); } }; } public static StreamCodec registry(ResourceKey> registryKey) { return ByteBufCodecs.registry(registryKey, r -> r); } public static StreamCodec> holderRegistry(ResourceKey> registryKey) { return ByteBufCodecs.registry(registryKey, Registry::asHolderIdMap); } public static StreamCodec> holder(final ResourceKey> registryKey, final StreamCodec directCodec) { return new StreamCodec>(){ private static final int DIRECT_HOLDER_ID = 0; private IdMap> getRegistryOrThrow(RegistryFriendlyByteBuf input) { return input.registryAccess().lookupOrThrow(registryKey).asHolderIdMap(); } @Override public Holder decode(RegistryFriendlyByteBuf input) { int id = VarInt.read(input); if (id == 0) { return Holder.direct(directCodec.decode(input)); } return this.getRegistryOrThrow(input).byIdOrThrow(id - 1); } @Override public void encode(RegistryFriendlyByteBuf output, Holder holder) { switch (holder.kind()) { case REFERENCE: { int id = this.getRegistryOrThrow(output).getIdOrThrow(holder); VarInt.write(output, id + 1); break; } case DIRECT: { VarInt.write(output, 0); directCodec.encode(output, holder.value()); } } } }; } public static StreamCodec> holderSet(final ResourceKey> registryKey) { return new StreamCodec>(){ private static final int NAMED_SET = -1; private final StreamCodec> holderCodec; { this.holderCodec = ByteBufCodecs.holderRegistry(registryKey); } @Override public HolderSet decode(RegistryFriendlyByteBuf input) { int count = VarInt.read(input) - 1; if (count == -1) { HolderLookup.RegistryLookup registry = input.registryAccess().lookupOrThrow(registryKey); return (HolderSet)registry.get(TagKey.create(registryKey, (Identifier)Identifier.STREAM_CODEC.decode(input))).orElseThrow(); } ArrayList holders = new ArrayList(Math.min(count, 65536)); for (int i = 0; i < count; ++i) { holders.add((Holder)this.holderCodec.decode(input)); } return HolderSet.direct(holders); } @Override public void encode(RegistryFriendlyByteBuf output, HolderSet value) { Optional key = value.unwrapKey(); if (key.isPresent()) { VarInt.write(output, 0); Identifier.STREAM_CODEC.encode(output, key.get().location()); } else { VarInt.write(output, value.size() + 1); for (Holder holder : value) { this.holderCodec.encode(output, holder); } } } }; } public static StreamCodec lenientJson(final int maxStringLength) { return new StreamCodec(){ private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); @Override public JsonElement decode(ByteBuf input) { String payload = Utf8String.read(input, maxStringLength); try { return LenientJsonParser.parse(payload); } catch (JsonSyntaxException e) { throw new DecoderException("Failed to parse JSON", (Throwable)e); } } @Override public void encode(ByteBuf output, JsonElement value) { String payload = GSON.toJson(value); Utf8String.write(output, payload, maxStringLength); } }; } }