120 lines
4.8 KiB
Java
120 lines
4.8 KiB
Java
package net.minecraft.network.protocol;
|
|
|
|
import io.netty.buffer.ByteBuf;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Function;
|
|
import net.minecraft.network.ClientboundPacketListener;
|
|
import net.minecraft.network.ConnectionProtocol;
|
|
import net.minecraft.network.PacketListener;
|
|
import net.minecraft.network.ProtocolInfo;
|
|
import net.minecraft.network.ServerboundPacketListener;
|
|
import net.minecraft.network.codec.StreamCodec;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class ProtocolInfoBuilder<T extends PacketListener, B extends ByteBuf> {
|
|
final ConnectionProtocol protocol;
|
|
final PacketFlow flow;
|
|
private final List<ProtocolInfoBuilder.CodecEntry<T, ?, B>> codecs = new ArrayList();
|
|
@Nullable
|
|
private BundlerInfo bundlerInfo;
|
|
|
|
public ProtocolInfoBuilder(ConnectionProtocol protocol, PacketFlow flow) {
|
|
this.protocol = protocol;
|
|
this.flow = flow;
|
|
}
|
|
|
|
public <P extends Packet<? super T>> ProtocolInfoBuilder<T, B> addPacket(PacketType<P> type, StreamCodec<? super B, P> serializer) {
|
|
this.codecs.add(new ProtocolInfoBuilder.CodecEntry<>(type, serializer));
|
|
return this;
|
|
}
|
|
|
|
public <P extends BundlePacket<? super T>, D extends BundleDelimiterPacket<? super T>> ProtocolInfoBuilder<T, B> withBundlePacket(
|
|
PacketType<P> type, Function<Iterable<Packet<? super T>>, P> bundler, D packet
|
|
) {
|
|
StreamCodec<ByteBuf, D> streamCodec = StreamCodec.unit(packet);
|
|
PacketType<D> packetType = (PacketType<D>)packet.type();
|
|
this.codecs.add(new ProtocolInfoBuilder.CodecEntry<>(packetType, streamCodec));
|
|
this.bundlerInfo = BundlerInfo.createForPacket(type, bundler, packet);
|
|
return this;
|
|
}
|
|
|
|
StreamCodec<ByteBuf, Packet<? super T>> buildPacketCodec(Function<ByteBuf, B> bufferFactory, List<ProtocolInfoBuilder.CodecEntry<T, ?, B>> codecs) {
|
|
ProtocolCodecBuilder<ByteBuf, T> protocolCodecBuilder = new ProtocolCodecBuilder<>(this.flow);
|
|
|
|
for (ProtocolInfoBuilder.CodecEntry<T, ?, B> codecEntry : codecs) {
|
|
codecEntry.addToBuilder(protocolCodecBuilder, bufferFactory);
|
|
}
|
|
|
|
return protocolCodecBuilder.build();
|
|
}
|
|
|
|
public ProtocolInfo<T> build(Function<ByteBuf, B> bufferFactory) {
|
|
return new ProtocolInfoBuilder.Implementation<>(this.protocol, this.flow, this.buildPacketCodec(bufferFactory, this.codecs), this.bundlerInfo);
|
|
}
|
|
|
|
public ProtocolInfo.Unbound<T, B> buildUnbound() {
|
|
final List<ProtocolInfoBuilder.CodecEntry<T, ?, B>> list = List.copyOf(this.codecs);
|
|
final BundlerInfo bundlerInfo = this.bundlerInfo;
|
|
return new ProtocolInfo.Unbound<T, B>() {
|
|
@Override
|
|
public ProtocolInfo<T> bind(Function<ByteBuf, B> bufferFactory) {
|
|
return new ProtocolInfoBuilder.Implementation<>(
|
|
ProtocolInfoBuilder.this.protocol, ProtocolInfoBuilder.this.flow, ProtocolInfoBuilder.this.buildPacketCodec(bufferFactory, list), bundlerInfo
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public ConnectionProtocol id() {
|
|
return ProtocolInfoBuilder.this.protocol;
|
|
}
|
|
|
|
@Override
|
|
public PacketFlow flow() {
|
|
return ProtocolInfoBuilder.this.flow;
|
|
}
|
|
|
|
@Override
|
|
public void listPackets(ProtocolInfo.Unbound.PacketVisitor visitor) {
|
|
for (int i = 0; i < list.size(); i++) {
|
|
ProtocolInfoBuilder.CodecEntry<T, ?, B> codecEntry = (ProtocolInfoBuilder.CodecEntry<T, ?, B>)list.get(i);
|
|
visitor.accept(codecEntry.type, i);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private static <L extends PacketListener, B extends ByteBuf> ProtocolInfo.Unbound<L, B> protocol(
|
|
ConnectionProtocol protocol, PacketFlow flow, Consumer<ProtocolInfoBuilder<L, B>> setup
|
|
) {
|
|
ProtocolInfoBuilder<L, B> protocolInfoBuilder = new ProtocolInfoBuilder<>(protocol, flow);
|
|
setup.accept(protocolInfoBuilder);
|
|
return protocolInfoBuilder.buildUnbound();
|
|
}
|
|
|
|
public static <T extends ServerboundPacketListener, B extends ByteBuf> ProtocolInfo.Unbound<T, B> serverboundProtocol(
|
|
ConnectionProtocol protocol, Consumer<ProtocolInfoBuilder<T, B>> setup
|
|
) {
|
|
return protocol(protocol, PacketFlow.SERVERBOUND, setup);
|
|
}
|
|
|
|
public static <T extends ClientboundPacketListener, B extends ByteBuf> ProtocolInfo.Unbound<T, B> clientboundProtocol(
|
|
ConnectionProtocol protocol, Consumer<ProtocolInfoBuilder<T, B>> setup
|
|
) {
|
|
return protocol(protocol, PacketFlow.CLIENTBOUND, setup);
|
|
}
|
|
|
|
record CodecEntry<T extends PacketListener, P extends Packet<? super T>, B extends ByteBuf>(PacketType<P> type, StreamCodec<? super B, P> serializer) {
|
|
|
|
public void addToBuilder(ProtocolCodecBuilder<ByteBuf, T> codecBuilder, Function<ByteBuf, B> bufferFactory) {
|
|
StreamCodec<ByteBuf, P> streamCodec = this.serializer.mapStream(bufferFactory);
|
|
codecBuilder.add(this.type, streamCodec);
|
|
}
|
|
}
|
|
|
|
record Implementation<L extends PacketListener>(
|
|
ConnectionProtocol id, PacketFlow flow, StreamCodec<ByteBuf, Packet<? super L>> codec, @Nullable BundlerInfo bundlerInfo
|
|
) implements ProtocolInfo<L> {
|
|
}
|
|
}
|