Skip to content

Commit

Permalink
1.21-rc1 (Payload Splitter Test Interface)
Browse files Browse the repository at this point in the history
  • Loading branch information
sakura-ryoko committed Jun 10, 2024
1 parent eacaa4f commit 2ea7b52
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 45 deletions.
47 changes: 2 additions & 45 deletions src/main/java/fi/dy/masa/malilib/network/ClientPlayHandler.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -44,9 +45,7 @@ public <P extends CustomPayload> void unregisterClientPlayHandler(IPluginClientP
}
}

/**
* API CALLS DO NOT USE ANYWHERE ELSE (DANGEROUS!)
*/
@ApiStatus.Internal
public void reset(Identifier channel)
{
if (this.handlers.isEmpty() == false)
Expand All @@ -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<T> 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<T> handler : this.handlers.get(channel))
{
handler.decodeByteBuf(channel, data);
}
}
}

/**
* API CALLS DO NOT USE ANYWHERE ELSE (DANGEROUS!)
*/
public <D> void decodeObject(Identifier channel, D data1)
{
if (!this.handlers.isEmpty())
{
for (IPluginClientPlayHandler<T> handler : this.handlers.get(channel))
{
handler.decodeObject(channel, data1);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -172,6 +175,22 @@ default void encodeNbtCompound(NbtCompound data) {}
default void encodeByteBuf(MaLiLibBuf data) {}
default <D> 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.
* -
Expand Down
140 changes: 140 additions & 0 deletions src/main/java/fi/dy/masa/malilib/network/PayloadSplitter.java
Original file line number Diff line number Diff line change
@@ -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<Pair<PacketListener, Identifier>, ReadingSession> READING_SESSIONS = new HashMap<>();

@ApiStatus.Experimental
public static <T extends CustomPayload> boolean send(IPluginClientPlayHandler<T> 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 <T extends CustomPayload> boolean send(IPluginClientPlayHandler<T> 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 <T extends CustomPayload> void receive(IPluginClientPlayHandler<T> 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<PacketListener, Identifier> 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<PacketListener, Identifier> key;
private int expectedSize = -1;
private PacketByteBuf received;

@ApiStatus.Experimental
private ReadingSession(Pair<PacketListener, Identifier> 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;
}
}
}

0 comments on commit 2ea7b52

Please sign in to comment.