All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.minestom.server.network.NetworkBuffer Maven / Gradle / Ivy

There is a newer version: 7320437640
Show newest version
package net.minestom.server.network;

import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.text.Component;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.EntityPose;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.ProtocolObject;
import net.minestom.server.registry.Registries;
import net.minestom.server.utils.Direction;
import net.minestom.server.utils.Unit;
import net.minestom.server.utils.crypto.KeyUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnknownNullability;

import javax.crypto.Cipher;
import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
import java.security.PublicKey;
import java.time.Instant;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.zip.DataFormatException;

public sealed interface NetworkBuffer permits NetworkBufferImpl {
    Type UNIT = new NetworkBufferTypeImpl.UnitType();
    Type BOOLEAN = new NetworkBufferTypeImpl.BooleanType();
    Type BYTE = new NetworkBufferTypeImpl.ByteType();
    Type SHORT = new NetworkBufferTypeImpl.ShortType();
    Type UNSIGNED_SHORT = new NetworkBufferTypeImpl.UnsignedShortType();
    Type INT = new NetworkBufferTypeImpl.IntType();
    Type LONG = new NetworkBufferTypeImpl.LongType();
    Type FLOAT = new NetworkBufferTypeImpl.FloatType();
    Type DOUBLE = new NetworkBufferTypeImpl.DoubleType();
    Type VAR_INT = new NetworkBufferTypeImpl.VarIntType();
    Type VAR_INT_3 = new NetworkBufferTypeImpl.VarInt3Type();
    Type VAR_LONG = new NetworkBufferTypeImpl.VarLongType();
    Type RAW_BYTES = new NetworkBufferTypeImpl.RawBytesType(-1);
    Type STRING = new NetworkBufferTypeImpl.StringType();
    Type STRING_TERMINATED = new NetworkBufferTypeImpl.StringTerminatedType();
    Type NBT = new NetworkBufferTypeImpl.NbtType();
    @SuppressWarnings({"unchecked", "rawtypes"})
    Type NBT_COMPOUND = (Type) new NetworkBufferTypeImpl.NbtType();
    Type BLOCK_POSITION = new NetworkBufferTypeImpl.BlockPositionType();
    Type COMPONENT = new ComponentNetworkBufferTypeImpl();
    Type JSON_COMPONENT = new NetworkBufferTypeImpl.JsonComponentType();
    Type UUID = new NetworkBufferTypeImpl.UUIDType();
    Type POS = new NetworkBufferTypeImpl.PosType();

    Type BYTE_ARRAY = new NetworkBufferTypeImpl.ByteArrayType();
    Type LONG_ARRAY = new NetworkBufferTypeImpl.LongArrayType();
    Type VAR_INT_ARRAY = new NetworkBufferTypeImpl.VarIntArrayType();
    Type VAR_LONG_ARRAY = new NetworkBufferTypeImpl.VarLongArrayType();

    Type BITSET = LONG_ARRAY.transform(BitSet::valueOf, BitSet::toLongArray);
    Type INSTANT_MS = LONG.transform(Instant::ofEpochMilli, Instant::toEpochMilli);
    Type PUBLIC_KEY = BYTE_ARRAY.transform(KeyUtils::publicRSAKeyFrom, PublicKey::getEncoded);

    static  @NotNull Type> RegistryKey(@NotNull Function> selector) {
        return new NetworkBufferTypeImpl.RegistryTypeType<>(selector);
    }

    // METADATA
    Type VILLAGER_DATA = new NetworkBufferTypeImpl.VillagerDataType();
    Type VECTOR3 = new NetworkBufferTypeImpl.Vector3Type();
    Type VECTOR3D = new NetworkBufferTypeImpl.Vector3DType();
    Type VECTOR3B = new NetworkBufferTypeImpl.Vector3BType();
    Type QUATERNION = new NetworkBufferTypeImpl.QuaternionType();

    Type<@Nullable Component> OPT_CHAT = COMPONENT.optional();
    Type<@Nullable Point> OPT_BLOCK_POSITION = BLOCK_POSITION.optional();
    Type<@Nullable UUID> OPT_UUID = UUID.optional();

    Type DIRECTION = Enum(Direction.class);
    Type POSE = Enum(EntityPose.class);

    // Combinators

    static > @NotNull Type Enum(@NotNull Class enumClass) {
        final E[] values = enumClass.getEnumConstants();
        return VAR_INT.transform(integer -> values[integer], Enum::ordinal);
    }

    static > @NotNull Type> EnumSet(@NotNull Class enumClass) {
        return new NetworkBufferTypeImpl.EnumSetType<>(enumClass, enumClass.getEnumConstants());
    }

    static @NotNull Type FixedBitSet(int length) {
        return new NetworkBufferTypeImpl.FixedBitSetType(length);
    }

    static @NotNull Type FixedRawBytes(int length) {
        return new NetworkBufferTypeImpl.RawBytesType(length);
    }

    static  @NotNull Type Lazy(@NotNull Supplier<@NotNull Type> supplier) {
        return new NetworkBufferTypeImpl.LazyType<>(supplier);
    }

     void write(@NotNull Type type, @UnknownNullability T value) throws IndexOutOfBoundsException;

     @UnknownNullability T read(@NotNull Type type) throws IndexOutOfBoundsException;

     void writeAt(long index, @NotNull Type type, @UnknownNullability T value) throws IndexOutOfBoundsException;

     @UnknownNullability T readAt(long index, @NotNull Type type) throws IndexOutOfBoundsException;

    void copyTo(long srcOffset, byte @NotNull [] dest, long destOffset, long length);

    byte @NotNull [] extractBytes(@NotNull Consumer<@NotNull NetworkBuffer> extractor);

    @NotNull NetworkBuffer clear();

    long writeIndex();

    long readIndex();

    @NotNull NetworkBuffer writeIndex(long writeIndex);

    @NotNull NetworkBuffer readIndex(long readIndex);

    @NotNull NetworkBuffer index(long readIndex, long writeIndex);

    long advanceWrite(long length);

    long advanceRead(long length);

    long readableBytes();

    long writableBytes();

    long capacity();

    void readOnly();

    boolean isReadOnly();

    void resize(long newSize);

    void ensureWritable(long length);

    void compact();

    NetworkBuffer copy(long index, long length, long readIndex, long writeIndex);

    default NetworkBuffer copy(long index, long length) {
        return copy(index, length, readIndex(), writeIndex());
    }

    int readChannel(ReadableByteChannel channel) throws IOException;

    boolean writeChannel(SocketChannel channel) throws IOException;

    void cipher(Cipher cipher, long start, long length);

    long compress(long start, long length, NetworkBuffer output);

    long decompress(long start, long length, NetworkBuffer output) throws DataFormatException;

    @Nullable Registries registries();

    interface Type {
        void write(@NotNull NetworkBuffer buffer, T value);

        T read(@NotNull NetworkBuffer buffer);

        default long sizeOf(@NotNull T value, @Nullable Registries registries) {
            return NetworkBufferTypeImpl.sizeOf(this, value, registries);
        }

        default long sizeOf(@NotNull T value) {
            return sizeOf(value, null);
        }

        default  @NotNull Type transform(@NotNull Function to, @NotNull Function from) {
            return new NetworkBufferTypeImpl.TransformType<>(this, to, from);
        }

        default  @NotNull Type> mapValue(@NotNull Type valueType, int maxSize) {
            return new NetworkBufferTypeImpl.MapType<>(this, valueType, maxSize);
        }

        default  @NotNull Type> mapValue(@NotNull Type valueType) {
            return mapValue(valueType, Integer.MAX_VALUE);
        }

        default @NotNull Type> list(int maxSize) {
            return new NetworkBufferTypeImpl.ListType<>(this, maxSize);
        }

        default @NotNull Type> list() {
            return list(Integer.MAX_VALUE);
        }

        default @NotNull Type optional() {
            return new NetworkBufferTypeImpl.OptionalType<>(this);
        }
    }

    static @NotNull Builder builder(long size) {
        return new NetworkBufferImpl.Builder(size);
    }

    static @NotNull NetworkBuffer staticBuffer(long size, Registries registries) {
        return builder(size).registry(registries).build();
    }

    static @NotNull NetworkBuffer staticBuffer(long size) {
        return staticBuffer(size, null);
    }

    static @NotNull NetworkBuffer resizableBuffer(long initialSize, Registries registries) {
        return builder(initialSize)
                .autoResize(AutoResize.DOUBLE)
                .registry(registries)
                .build();
    }

    static @NotNull NetworkBuffer resizableBuffer(int initialSize) {
        return resizableBuffer(initialSize, null);
    }

    static @NotNull NetworkBuffer resizableBuffer(Registries registries) {
        return resizableBuffer(256, registries);
    }

    static @NotNull NetworkBuffer resizableBuffer() {
        return resizableBuffer(null);
    }

    static @NotNull NetworkBuffer wrap(byte @NotNull [] bytes, int readIndex, int writeIndex, @Nullable Registries registries) {
        return NetworkBufferImpl.wrap(bytes, readIndex, writeIndex, registries);
    }

    static @NotNull NetworkBuffer wrap(byte @NotNull [] bytes, int readIndex, int writeIndex) {
        return wrap(bytes, readIndex, writeIndex, null);
    }

    sealed interface Builder permits NetworkBufferImpl.Builder {
        @NotNull Builder autoResize(@Nullable AutoResize autoResize);

        @NotNull Builder registry(@Nullable Registries registries);

        @NotNull NetworkBuffer build();
    }

    @FunctionalInterface
    interface AutoResize {
        AutoResize DOUBLE = (capacity, targetSize) -> Math.max(capacity * 2, targetSize);

        long resize(long capacity, long targetSize);
    }

    static byte[] makeArray(@NotNull Consumer<@NotNull NetworkBuffer> writing, @Nullable Registries registries) {
        NetworkBuffer buffer = resizableBuffer(256, registries);
        writing.accept(buffer);
        return buffer.read(RAW_BYTES);
    }

    static byte[] makeArray(@NotNull Consumer<@NotNull NetworkBuffer> writing) {
        return makeArray(writing, null);
    }

    static  byte[] makeArray(@NotNull Type type, @NotNull T value, @Nullable Registries registries) {
        return makeArray(buffer -> buffer.write(type, value), registries);
    }

    static  byte[] makeArray(@NotNull Type type, @NotNull T value) {
        return makeArray(type, value, null);
    }

    static void copy(NetworkBuffer srcBuffer, long srcOffset,
                     NetworkBuffer dstBuffer, long dstOffset, long length) {
        NetworkBufferImpl.copy(srcBuffer, srcOffset, dstBuffer, dstOffset, length);
    }

    static boolean equals(NetworkBuffer buffer1, NetworkBuffer buffer2) {
        return NetworkBufferImpl.equals(buffer1, buffer2);
    }
}