diff --git a/src/main/java/fi/dy/masa/malilib/network/ClientPlayHandler.java b/src/main/java/fi/dy/masa/malilib/network/ClientPlayHandler.java index 09d811cc4a..fe8ffe1ae8 100644 --- a/src/main/java/fi/dy/masa/malilib/network/ClientPlayHandler.java +++ b/src/main/java/fi/dy/masa/malilib/network/ClientPlayHandler.java @@ -1,6 +1,7 @@ package fi.dy.masa.malilib.network; import com.google.common.collect.ArrayListMultimap; +import org.jetbrains.annotations.ApiStatus; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.packet.CustomPayload; import net.minecraft.util.Identifier; @@ -44,9 +45,7 @@ public

void unregisterClientPlayHandler(IPluginClientP } } - /** - * API CALLS DO NOT USE ANYWHERE ELSE (DANGEROUS!) - */ + @ApiStatus.Internal public void reset(Identifier channel) { if (this.handlers.isEmpty() == false) @@ -57,46 +56,4 @@ public void reset(Identifier channel) } } } - - /** - * API CALLS DO NOT USE ANYWHERE ELSE (DANGEROUS!) - */ - public void decodeNbtCompound(Identifier channel, NbtCompound data) - { - if (!this.handlers.isEmpty()) - { - for (IPluginClientPlayHandler handler : this.handlers.get(channel)) - { - handler.decodeNbtCompound(channel, data); - } - } - } - - /** - * API CALLS DO NOT USE ANYWHERE ELSE (DANGEROUS!) - */ - public void decodeByteBuf(Identifier channel, MaLiLibBuf data) - { - if (!this.handlers.isEmpty()) - { - for (IPluginClientPlayHandler handler : this.handlers.get(channel)) - { - handler.decodeByteBuf(channel, data); - } - } - } - - /** - * API CALLS DO NOT USE ANYWHERE ELSE (DANGEROUS!) - */ - public void decodeObject(Identifier channel, D data1) - { - if (!this.handlers.isEmpty()) - { - for (IPluginClientPlayHandler handler : this.handlers.get(channel)) - { - handler.decodeObject(channel, data1); - } - } - } } diff --git a/src/main/java/fi/dy/masa/malilib/network/IPluginClientPlayHandler.java b/src/main/java/fi/dy/masa/malilib/network/IPluginClientPlayHandler.java index 5d50d81aa3..43f2c79e54 100644 --- a/src/main/java/fi/dy/masa/malilib/network/IPluginClientPlayHandler.java +++ b/src/main/java/fi/dy/masa/malilib/network/IPluginClientPlayHandler.java @@ -8,11 +8,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.packet.CustomPayload; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import fi.dy.masa.malilib.MaLiLib; @@ -172,6 +175,22 @@ default void encodeNbtCompound(NbtCompound data) {} default void encodeByteBuf(MaLiLibBuf data) {} default void encodeObject(D data1) {} + // UNSTABLE TESTING ONLY -- DO NOT USE + /** + * Used as an iterative "wrapper" for Payload Splitter to receive a packet with + * @param handler (networkHandler only used with Reading Session) + * @param buf (Buffer to receive) + */ + default void decodeWithSplitter(ClientPlayNetworkHandler handler, PacketByteBuf buf) {} + + // UNSTABLE TESTING ONLY -- DO NOT USE + /** + * Used as an iterative "wrapper" for Payload Splitter to send individual Packets + * @param buf (Sliced Buffer to send) + */ + default void encodeWithSplitter(PacketByteBuf buf) {} + // UNSTABLE TESTING ONLY -- DO NOT USE + /** * Sends the Payload to the server using the Fabric-API interface. * - diff --git a/src/main/java/fi/dy/masa/malilib/network/PayloadSplitter.java b/src/main/java/fi/dy/masa/malilib/network/PayloadSplitter.java new file mode 100644 index 0000000000..7b4495b098 --- /dev/null +++ b/src/main/java/fi/dy/masa/malilib/network/PayloadSplitter.java @@ -0,0 +1,140 @@ +package fi.dy.masa.malilib.network; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; +import io.netty.buffer.Unpooled; +import org.jetbrains.annotations.ApiStatus; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; + +/** + * Network packet splitter code from QuickCarpet by skyrising + * @author skyrising + * + */ +@ApiStatus.Experimental +public class PayloadSplitter +{ + public static final int MAX_TOTAL_PER_PACKET_S2C = 1048576; + public static final int MAX_PAYLOAD_PER_PACKET_S2C = MAX_TOTAL_PER_PACKET_S2C - 5; + public static final int MAX_TOTAL_PER_PACKET_C2S = 32767; + public static final int MAX_PAYLOAD_PER_PACKET_C2S = MAX_TOTAL_PER_PACKET_C2S - 5; + public static final int DEFAULT_MAX_RECEIVE_SIZE_C2S = 1048576; + public static final int DEFAULT_MAX_RECEIVE_SIZE_S2C = 67108864; + + private static final Map, ReadingSession> READING_SESSIONS = new HashMap<>(); + + @ApiStatus.Experimental + public static boolean send(IPluginClientPlayHandler handler, Identifier channel, PacketByteBuf packet) + { + //ClientPlayNetworking.send(channel, packet); + //send(packet, MAX_PAYLOAD_PER_PACKET_C2S, buf -> networkHandler.sendPacket(new CustomPayloadC2SPacket(new PacketByteBufPayload(channel, buf)))); + return send(handler, packet, MAX_PAYLOAD_PER_PACKET_C2S); + } + + @ApiStatus.Experimental + private static boolean send(IPluginClientPlayHandler handler, PacketByteBuf packet, int payloadLimit) + { + int len = packet.writerIndex(); + + packet.resetReaderIndex(); + + for (int offset = 0; offset < len; offset += payloadLimit) + { + int thisLen = Math.min(len - offset, payloadLimit); + PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer(thisLen)); + + buf.resetWriterIndex(); + + if (offset == 0) + { + buf.writeVarInt(len); + } + + buf.writeBytes(packet, thisLen); + + //ClientPlayNetworking.send(channel, buf); + handler.encodeWithSplitter(buf); + } + + packet.release(); + + return true; + } + + @ApiStatus.Experimental + public static void receive(IPluginClientPlayHandler handler, + PacketByteBuf buf, + ClientPlayNetworkHandler networkHandler) + { + handler.decodeWithSplitter(networkHandler, receive(handler.getPayloadChannel(), buf, DEFAULT_MAX_RECEIVE_SIZE_S2C, networkHandler)); + } + + @Nullable + @ApiStatus.Experimental + private static PacketByteBuf receive(Identifier channel, + PacketByteBuf buf, + int maxLength, + ClientPlayPacketListener networkHandler) + { + Pair key = new Pair<>(networkHandler, channel); + + return READING_SESSIONS.computeIfAbsent(key, ReadingSession::new).receive(readPayload(buf), maxLength); + } + + @ApiStatus.Experimental + public static PacketByteBuf readPayload(PacketByteBuf byteBuf) + { + PacketByteBuf newBuf = new PacketByteBuf(Unpooled.buffer()); + newBuf.writeBytes(byteBuf.copy()); + byteBuf.skipBytes(byteBuf.readableBytes()); + return newBuf; + } + + @ApiStatus.Experimental + private static class ReadingSession + { + private final Pair key; + private int expectedSize = -1; + private PacketByteBuf received; + + @ApiStatus.Experimental + private ReadingSession(Pair key) + { + this.key = key; + } + + @Nullable + @ApiStatus.Experimental + private PacketByteBuf receive(PacketByteBuf data, int maxLength) + { + if (this.expectedSize < 0) + { + this.expectedSize = data.readVarInt(); + + if (this.expectedSize > maxLength) + { + throw new IllegalArgumentException("Payload too large"); + } + + this.received = new PacketByteBuf(Unpooled.buffer(this.expectedSize)); + } + + this.received.writeBytes(data.readBytes(data.readableBytes())); + + if (this.received.writerIndex() >= this.expectedSize) + { + READING_SESSIONS.remove(this.key); + return this.received; + } + + return null; + } + } +}