Connection.java
net.minecraft.network.Connection
信息
- 全限定名:net.minecraft.network.Connection
- 类型:public class
- 包:net.minecraft.network
- 源码路径:src/main/java/net/minecraft/network/Connection.java
- 起始行号:L58
- 继承:SimpleChannelInboundHandler<Packet<?>>
- 职责:
TODO
字段/常量
-
AVERAGE_PACKETS_SMOOTHING- 类型:
float - 修饰符:
private static final - 源码定位:
L59 - 说明:
TODO
- 类型:
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L60 - 说明:
TODO
- 类型:
-
ROOT_MARKER- 类型:
Marker - 修饰符:
public static final - 源码定位:
L61 - 说明:
TODO
- 类型:
-
PACKET_MARKER- 类型:
Marker - 修饰符:
public static final - 源码定位:
L62 - 说明:
TODO
- 类型:
-
PACKET_RECEIVED_MARKER- 类型:
Marker - 修饰符:
public static final - 源码定位:
L63 - 说明:
TODO
- 类型:
-
PACKET_SENT_MARKER- 类型:
Marker - 修饰符:
public static final - 源码定位:
L64 - 说明:
TODO
- 类型:
-
INITIAL_PROTOCOL- 类型:
ProtocolInfo<ServerHandshakePacketListener> - 修饰符:
private static final - 源码定位:
L65 - 说明:
TODO
- 类型:
-
receiving- 类型:
PacketFlow - 修饰符:
private final - 源码定位:
L66 - 说明:
TODO
- 类型:
-
sendLoginDisconnect- 类型:
boolean - 修饰符:
private volatile - 源码定位:
L67 - 说明:
TODO
- 类型:
-
pendingActions- 类型:
Queue<Consumer<Connection>> - 修饰符:
private final - 源码定位:
L68 - 说明:
TODO
- 类型:
-
channel- 类型:
Channel - 修饰符:
private - 源码定位:
L69 - 说明:
TODO
- 类型:
-
address- 类型:
SocketAddress - 修饰符:
private - 源码定位:
L70 - 说明:
TODO
- 类型:
-
disconnectListener- 类型:
PacketListener - 修饰符:
private volatile - 源码定位:
L71 - 说明:
TODO
- 类型:
-
packetListener- 类型:
PacketListener - 修饰符:
private volatile - 源码定位:
L72 - 说明:
TODO
- 类型:
-
disconnectionDetails- 类型:
DisconnectionDetails - 修饰符:
private - 源码定位:
L73 - 说明:
TODO
- 类型:
-
encrypted- 类型:
boolean - 修饰符:
private - 源码定位:
L74 - 说明:
TODO
- 类型:
-
disconnectionHandled- 类型:
boolean - 修饰符:
private - 源码定位:
L75 - 说明:
TODO
- 类型:
-
receivedPackets- 类型:
int - 修饰符:
private - 源码定位:
L76 - 说明:
TODO
- 类型:
-
sentPackets- 类型:
int - 修饰符:
private - 源码定位:
L77 - 说明:
TODO
- 类型:
-
averageReceivedPackets- 类型:
float - 修饰符:
private - 源码定位:
L78 - 说明:
TODO
- 类型:
-
averageSentPackets- 类型:
float - 修饰符:
private - 源码定位:
L79 - 说明:
TODO
- 类型:
-
tickCount- 类型:
int - 修饰符:
private - 源码定位:
L80 - 说明:
TODO
- 类型:
-
handlingFault- 类型:
boolean - 修饰符:
private - 源码定位:
L81 - 说明:
TODO
- 类型:
-
delayedDisconnect- 类型:
DisconnectionDetails - 修饰符:
private volatile - 源码定位:
L82 - 说明:
TODO
- 类型:
-
bandwidthDebugMonitor- 类型:
BandwidthDebugMonitor - 修饰符:
private - 源码定位:
L83 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public Connection(PacketFlow receiving) @ L85
- 构造器名:Connection
- 源码定位:L85
- 修饰符:public
参数:
- receiving: PacketFlow
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void channelActive(ChannelHandlerContext ctx) @ L89
- 方法名:channelActive
- 源码定位:L89
- 返回类型:void
- 修饰符:public
参数:
- ctx: ChannelHandlerContext
说明:
TODO
public void channelInactive(ChannelHandlerContext ctx) @ L99
- 方法名:channelInactive
- 源码定位:L99
- 返回类型:void
- 修饰符:public
参数:
- ctx: ChannelHandlerContext
说明:
TODO
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) @ L104
- 方法名:exceptionCaught
- 源码定位:L104
- 返回类型:void
- 修饰符:public
参数:
- ctx: ChannelHandlerContext
- cause: Throwable
说明:
TODO
protected void channelRead0(ChannelHandlerContext ctx, Packet<?> packet) @ L146
- 方法名:channelRead0
- 源码定位:L146
- 返回类型:void
- 修饰符:protected
参数:
- ctx: ChannelHandlerContext
- packet: Packet<?>
说明:
TODO
private static <T extends PacketListener> void genericsFtw(Packet<T> packet, PacketListener listener) @ L169
- 方法名:genericsFtw
- 源码定位:L169
- 返回类型:
void - 修饰符:private static
参数:
- packet: Packet
- listener: PacketListener
说明:
TODO
private void validateListener(ProtocolInfo<?> protocol, PacketListener packetListener) @ L173
- 方法名:validateListener
- 源码定位:L173
- 返回类型:void
- 修饰符:private
参数:
- protocol: ProtocolInfo<?>
- packetListener: PacketListener
说明:
TODO
private static void syncAfterConfigurationChange(ChannelFuture future) @ L186
- 方法名:syncAfterConfigurationChange
- 源码定位:L186
- 返回类型:void
- 修饰符:private static
参数:
- future: ChannelFuture
说明:
TODO
public <T extends PacketListener> void setupInboundProtocol(ProtocolInfo<T> protocol, T packetListener) @ L198
- 方法名:setupInboundProtocol
- 源码定位:L198
- 返回类型:
void - 修饰符:public
参数:
- protocol: ProtocolInfo
- packetListener: T
说明:
TODO
public void setupOutboundProtocol(ProtocolInfo<?> protocol) @ L216
- 方法名:setupOutboundProtocol
- 源码定位:L216
- 返回类型:void
- 修饰符:public
参数:
- protocol: ProtocolInfo<?>
说明:
TODO
public void setListenerForServerboundHandshake(PacketListener packetListener) @ L232
- 方法名:setListenerForServerboundHandshake
- 源码定位:L232
- 返回类型:void
- 修饰符:public
参数:
- packetListener: PacketListener
说明:
TODO
public void initiateServerboundStatusConnection(String hostName, int port, ClientStatusPacketListener listener) @ L244
- 方法名:initiateServerboundStatusConnection
- 源码定位:L244
- 返回类型:void
- 修饰符:public
参数:
- hostName: String
- port: int
- listener: ClientStatusPacketListener
说明:
TODO
public void initiateServerboundPlayConnection(String hostName, int port, ClientLoginPacketListener listener) @ L248
- 方法名:initiateServerboundPlayConnection
- 源码定位:L248
- 返回类型:void
- 修饰符:public
参数:
- hostName: String
- port: int
- listener: ClientLoginPacketListener
说明:
TODO
public <S extends ServerboundPacketListener,C extends ClientboundPacketListener> void initiateServerboundPlayConnection(String hostName, int port, ProtocolInfo<S> outbound, ProtocolInfo<C> inbound, C listener, boolean transfer) @ L252
- 方法名:initiateServerboundPlayConnection
- 源码定位:L252
- 返回类型:<S extends ServerboundPacketListener,C extends ClientboundPacketListener> void
- 修饰符:public
参数:
- hostName: String
- port: int
- outbound: ProtocolInfo
- inbound: ProtocolInfo
- listener: C
- transfer: boolean
说明:
TODO
private <S extends ServerboundPacketListener,C extends ClientboundPacketListener> void initiateServerboundConnection(String hostName, int port, ProtocolInfo<S> outbound, ProtocolInfo<C> inbound, C listener, ClientIntent intent) @ L258
- 方法名:initiateServerboundConnection
- 源码定位:L258
- 返回类型:<S extends ServerboundPacketListener,C extends ClientboundPacketListener> void
- 修饰符:private
参数:
- hostName: String
- port: int
- outbound: ProtocolInfo
- inbound: ProtocolInfo
- listener: C
- intent: ClientIntent
说明:
TODO
public void send(Packet<?> packet) @ L273
- 方法名:send
- 源码定位:L273
- 返回类型:void
- 修饰符:public
参数:
- packet: Packet<?>
说明:
TODO
public void send(Packet<?> packet, ChannelFutureListener listener) @ L277
- 方法名:send
- 源码定位:L277
- 返回类型:void
- 修饰符:public
参数:
- packet: Packet<?>
- listener: ChannelFutureListener
说明:
TODO
public void send(Packet<?> packet, ChannelFutureListener listener, boolean flush) @ L281
- 方法名:send
- 源码定位:L281
- 返回类型:void
- 修饰符:public
参数:
- packet: Packet<?>
- listener: ChannelFutureListener
- flush: boolean
说明:
TODO
public void runOnceConnected(Consumer<Connection> action) @ L290
- 方法名:runOnceConnected
- 源码定位:L290
- 返回类型:void
- 修饰符:public
参数:
- action: Consumer
说明:
TODO
private void sendPacket(Packet<?> packet, ChannelFutureListener listener, boolean flush) @ L299
- 方法名:sendPacket
- 源码定位:L299
- 返回类型:void
- 修饰符:private
参数:
- packet: Packet<?>
- listener: ChannelFutureListener
- flush: boolean
说明:
TODO
private void doSendPacket(Packet<?> packet, ChannelFutureListener listener, boolean flush) @ L308
- 方法名:doSendPacket
- 源码定位:L308
- 返回类型:void
- 修饰符:private
参数:
- packet: Packet<?>
- listener: ChannelFutureListener
- flush: boolean
说明:
TODO
public void flushChannel() @ L319
- 方法名:flushChannel
- 源码定位:L319
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private void flush() @ L327
- 方法名:flush
- 源码定位:L327
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
private void flushQueue() @ L335
- 方法名:flushQueue
- 源码定位:L335
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
public void tick() @ L346
- 方法名:tick
- 源码定位:L346
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
protected void tickSecond() @ L369
- 方法名:tickSecond
- 源码定位:L369
- 返回类型:void
- 修饰符:protected
参数:
- 无
说明:
TODO
public SocketAddress getRemoteAddress() @ L376
- 方法名:getRemoteAddress
- 源码定位:L376
- 返回类型:SocketAddress
- 修饰符:public
参数:
- 无
说明:
TODO
public String getLoggableAddress(boolean logIPs) @ L380
- 方法名:getLoggableAddress
- 源码定位:L380
- 返回类型:String
- 修饰符:public
参数:
- logIPs: boolean
说明:
TODO
public void disconnect(Component reason) @ L388
- 方法名:disconnect
- 源码定位:L388
- 返回类型:void
- 修饰符:public
参数:
- reason: Component
说明:
TODO
public void disconnect(DisconnectionDetails details) @ L392
- 方法名:disconnect
- 源码定位:L392
- 返回类型:void
- 修饰符:public
参数:
- details: DisconnectionDetails
说明:
TODO
public boolean isMemoryConnection() @ L403
- 方法名:isMemoryConnection
- 源码定位:L403
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public PacketFlow getReceiving() @ L407
- 方法名:getReceiving
- 源码定位:L407
- 返回类型:PacketFlow
- 修饰符:public
参数:
- 无
说明:
TODO
public PacketFlow getSending() @ L411
- 方法名:getSending
- 源码定位:L411
- 返回类型:PacketFlow
- 修饰符:public
参数:
- 无
说明:
TODO
public static Connection connectToServer(InetSocketAddress address, EventLoopGroupHolder eventLoopGroupHolder, LocalSampleLogger bandwidthLogger) @ L415
- 方法名:connectToServer
- 源码定位:L415
- 返回类型:Connection
- 修饰符:public static
参数:
- address: InetSocketAddress
- eventLoopGroupHolder: EventLoopGroupHolder
- bandwidthLogger: LocalSampleLogger
说明:
TODO
public static ChannelFuture connect(InetSocketAddress address, EventLoopGroupHolder eventLoopGroupHolder, Connection connection) @ L426
- 方法名:connect
- 源码定位:L426
- 返回类型:ChannelFuture
- 修饰符:public static
参数:
- address: InetSocketAddress
- eventLoopGroupHolder: EventLoopGroupHolder
- connection: Connection
说明:
TODO
private static String outboundHandlerName(boolean configureOutbound) @ L442
- 方法名:outboundHandlerName
- 源码定位:L442
- 返回类型:String
- 修饰符:private static
参数:
- configureOutbound: boolean
说明:
TODO
private static String inboundHandlerName(boolean configureInbound) @ L446
- 方法名:inboundHandlerName
- 源码定位:L446
- 返回类型:String
- 修饰符:private static
参数:
- configureInbound: boolean
说明:
TODO
public void configurePacketHandler(ChannelPipeline pipeline) @ L450
- 方法名:configurePacketHandler
- 源码定位:L450
- 返回类型:void
- 修饰符:public
参数:
- pipeline: ChannelPipeline
说明:
TODO
public static void configureSerialization(ChannelPipeline pipeline, PacketFlow inboundDirection, boolean local, BandwidthDebugMonitor monitor) @ L463
- 方法名:configureSerialization
- 源码定位:L463
- 返回类型:void
- 修饰符:public static
参数:
- pipeline: ChannelPipeline
- inboundDirection: PacketFlow
- local: boolean
- monitor: BandwidthDebugMonitor
说明:
TODO
private static ChannelOutboundHandler createFrameEncoder(boolean local) @ L480
- 方法名:createFrameEncoder
- 源码定位:L480
- 返回类型:ChannelOutboundHandler
- 修饰符:private static
参数:
- local: boolean
说明:
TODO
private static ChannelInboundHandler createFrameDecoder(BandwidthDebugMonitor monitor, boolean local) @ L484
- 方法名:createFrameDecoder
- 源码定位:L484
- 返回类型:ChannelInboundHandler
- 修饰符:private static
参数:
- monitor: BandwidthDebugMonitor
- local: boolean
说明:
TODO
public static void configureInMemoryPipeline(ChannelPipeline pipeline, PacketFlow packetFlow) @ L492
- 方法名:configureInMemoryPipeline
- 源码定位:L492
- 返回类型:void
- 修饰符:public static
参数:
- pipeline: ChannelPipeline
- packetFlow: PacketFlow
说明:
TODO
public static Connection connectToLocalServer(SocketAddress address) @ L496
- 方法名:connectToLocalServer
- 源码定位:L496
- 返回类型:Connection
- 修饰符:public static
参数:
- address: SocketAddress
说明:
TODO
public void setEncryptionKey(Cipher decryptCipher, Cipher encryptCipher) @ L509
- 方法名:setEncryptionKey
- 源码定位:L509
- 返回类型:void
- 修饰符:public
参数:
- decryptCipher: Cipher
- encryptCipher: Cipher
说明:
TODO
public boolean isEncrypted() @ L515
- 方法名:isEncrypted
- 源码定位:L515
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isConnected() @ L519
- 方法名:isConnected
- 源码定位:L519
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isConnecting() @ L523
- 方法名:isConnecting
- 源码定位:L523
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public PacketListener getPacketListener() @ L527
- 方法名:getPacketListener
- 源码定位:L527
- 返回类型:PacketListener
- 修饰符:public
参数:
- 无
说明:
TODO
public DisconnectionDetails getDisconnectionDetails() @ L531
- 方法名:getDisconnectionDetails
- 源码定位:L531
- 返回类型:DisconnectionDetails
- 修饰符:public
参数:
- 无
说明:
TODO
public void setReadOnly() @ L535
- 方法名:setReadOnly
- 源码定位:L535
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void setupCompression(int threshold, boolean validateDecompressed) @ L541
- 方法名:setupCompression
- 源码定位:L541
- 返回类型:void
- 修饰符:public
参数:
- threshold: int
- validateDecompressed: boolean
说明:
TODO
public void handleDisconnection() @ L565
- 方法名:handleDisconnection
- 源码定位:L565
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public float getAverageReceivedPackets() @ L583
- 方法名:getAverageReceivedPackets
- 源码定位:L583
- 返回类型:float
- 修饰符:public
参数:
- 无
说明:
TODO
public float getAverageSentPackets() @ L587
- 方法名:getAverageSentPackets
- 源码定位:L587
- 返回类型:float
- 修饰符:public
参数:
- 无
说明:
TODO
public void setBandwidthLogger(LocalSampleLogger bandwidthLogger) @ L591
- 方法名:setBandwidthLogger
- 源码定位:L591
- 返回类型:void
- 修饰符:public
参数:
- bandwidthLogger: LocalSampleLogger
说明:
TODO
代码
public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
private static final float AVERAGE_PACKETS_SMOOTHING = 0.75F;
private static final Logger LOGGER = LogUtils.getLogger();
public static final Marker ROOT_MARKER = MarkerFactory.getMarker("NETWORK");
public static final Marker PACKET_MARKER = Util.make(MarkerFactory.getMarker("NETWORK_PACKETS"), m -> m.add(ROOT_MARKER));
public static final Marker PACKET_RECEIVED_MARKER = Util.make(MarkerFactory.getMarker("PACKET_RECEIVED"), m -> m.add(PACKET_MARKER));
public static final Marker PACKET_SENT_MARKER = Util.make(MarkerFactory.getMarker("PACKET_SENT"), m -> m.add(PACKET_MARKER));
private static final ProtocolInfo<ServerHandshakePacketListener> INITIAL_PROTOCOL = HandshakeProtocols.SERVERBOUND;
private final PacketFlow receiving;
private volatile boolean sendLoginDisconnect = true;
private final Queue<Consumer<Connection>> pendingActions = Queues.newConcurrentLinkedQueue();
private Channel channel;
private SocketAddress address;
private volatile @Nullable PacketListener disconnectListener;
private volatile @Nullable PacketListener packetListener;
private @Nullable DisconnectionDetails disconnectionDetails;
private boolean encrypted;
private boolean disconnectionHandled;
private int receivedPackets;
private int sentPackets;
private float averageReceivedPackets;
private float averageSentPackets;
private int tickCount;
private boolean handlingFault;
private volatile @Nullable DisconnectionDetails delayedDisconnect;
private @Nullable BandwidthDebugMonitor bandwidthDebugMonitor;
public Connection(PacketFlow receiving) {
this.receiving = receiving;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
this.channel = ctx.channel();
this.address = this.channel.remoteAddress();
if (this.delayedDisconnect != null) {
this.disconnect(this.delayedDisconnect);
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
this.disconnect(Component.translatable("disconnect.endOfStream"));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (cause instanceof SkipPacketException) {
LOGGER.debug("Skipping packet due to errors", cause.getCause());
} else {
boolean isFirstFault = !this.handlingFault;
this.handlingFault = true;
if (this.channel.isOpen()) {
if (cause instanceof TimeoutException) {
LOGGER.debug("Timeout", cause);
this.disconnect(Component.translatable("disconnect.timeout"));
} else {
Component reason = Component.translatable("disconnect.genericReason", "Internal Exception: " + cause);
PacketListener listener = this.packetListener;
DisconnectionDetails details;
if (listener != null) {
details = listener.createDisconnectionInfo(reason, cause);
} else {
details = new DisconnectionDetails(reason);
}
if (isFirstFault) {
LOGGER.debug("Failed to sent packet", cause);
if (this.getSending() == PacketFlow.CLIENTBOUND) {
Packet<?> packet = (Packet<?>)(this.sendLoginDisconnect
? new ClientboundLoginDisconnectPacket(reason)
: new ClientboundDisconnectPacket(reason));
this.send(packet, PacketSendListener.thenRun(() -> this.disconnect(details)));
} else {
this.disconnect(details);
}
this.setReadOnly();
} else {
LOGGER.debug("Double fault", cause);
this.disconnect(details);
}
}
}
}
}
protected void channelRead0(ChannelHandlerContext ctx, Packet<?> packet) {
if (this.channel.isOpen()) {
PacketListener packetListener = this.packetListener;
if (packetListener == null) {
throw new IllegalStateException("Received a packet before the packet listener was initialized");
} else {
if (packetListener.shouldHandleMessage(packet)) {
try {
genericsFtw(packet, packetListener);
} catch (RunningOnDifferentThreadException var5) {
} catch (RejectedExecutionException var6) {
this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
} catch (ClassCastException var7) {
LOGGER.error("Received {} that couldn't be processed", packet.getClass(), var7);
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_packet"));
}
this.receivedPackets++;
}
}
}
}
private static <T extends PacketListener> void genericsFtw(Packet<T> packet, PacketListener listener) {
packet.handle((T)listener);
}
private void validateListener(ProtocolInfo<?> protocol, PacketListener packetListener) {
Objects.requireNonNull(packetListener, "packetListener");
PacketFlow listenerFlow = packetListener.flow();
if (listenerFlow != this.receiving) {
throw new IllegalStateException("Trying to set listener for wrong side: connection is " + this.receiving + ", but listener is " + listenerFlow);
} else {
ConnectionProtocol listenerProtocol = packetListener.protocol();
if (protocol.id() != listenerProtocol) {
throw new IllegalStateException("Listener protocol (" + listenerProtocol + ") does not match requested one " + protocol);
}
}
}
private static void syncAfterConfigurationChange(ChannelFuture future) {
try {
future.syncUninterruptibly();
} catch (Exception var2) {
if (var2 instanceof ClosedChannelException) {
LOGGER.info("Connection closed during protocol change");
} else {
throw var2;
}
}
}
public <T extends PacketListener> void setupInboundProtocol(ProtocolInfo<T> protocol, T packetListener) {
this.validateListener(protocol, packetListener);
if (protocol.flow() != this.getReceiving()) {
throw new IllegalStateException("Invalid inbound protocol: " + protocol.id());
} else {
this.packetListener = packetListener;
this.disconnectListener = null;
UnconfiguredPipelineHandler.InboundConfigurationTask configMessage = UnconfiguredPipelineHandler.setupInboundProtocol(protocol);
BundlerInfo bundlerInfo = protocol.bundlerInfo();
if (bundlerInfo != null) {
PacketBundlePacker newBundler = new PacketBundlePacker(bundlerInfo);
configMessage = configMessage.andThen(ctx -> ctx.pipeline().addAfter("decoder", "bundler", newBundler));
}
syncAfterConfigurationChange(this.channel.writeAndFlush(configMessage));
}
}
public void setupOutboundProtocol(ProtocolInfo<?> protocol) {
if (protocol.flow() != this.getSending()) {
throw new IllegalStateException("Invalid outbound protocol: " + protocol.id());
} else {
UnconfiguredPipelineHandler.OutboundConfigurationTask configMessage = UnconfiguredPipelineHandler.setupOutboundProtocol(protocol);
BundlerInfo bundlerInfo = protocol.bundlerInfo();
if (bundlerInfo != null) {
PacketBundleUnpacker newUnbundler = new PacketBundleUnpacker(bundlerInfo);
configMessage = configMessage.andThen(ctx -> ctx.pipeline().addAfter("encoder", "unbundler", newUnbundler));
}
boolean isLoginProtocol = protocol.id() == ConnectionProtocol.LOGIN;
syncAfterConfigurationChange(this.channel.writeAndFlush(configMessage.andThen(ctx -> this.sendLoginDisconnect = isLoginProtocol)));
}
}
public void setListenerForServerboundHandshake(PacketListener packetListener) {
if (this.packetListener != null) {
throw new IllegalStateException("Listener already set");
} else if (this.receiving == PacketFlow.SERVERBOUND
&& packetListener.flow() == PacketFlow.SERVERBOUND
&& packetListener.protocol() == INITIAL_PROTOCOL.id()) {
this.packetListener = packetListener;
} else {
throw new IllegalStateException("Invalid initial listener");
}
}
public void initiateServerboundStatusConnection(String hostName, int port, ClientStatusPacketListener listener) {
this.initiateServerboundConnection(hostName, port, StatusProtocols.SERVERBOUND, StatusProtocols.CLIENTBOUND, listener, ClientIntent.STATUS);
}
public void initiateServerboundPlayConnection(String hostName, int port, ClientLoginPacketListener listener) {
this.initiateServerboundConnection(hostName, port, LoginProtocols.SERVERBOUND, LoginProtocols.CLIENTBOUND, listener, ClientIntent.LOGIN);
}
public <S extends ServerboundPacketListener, C extends ClientboundPacketListener> void initiateServerboundPlayConnection(
String hostName, int port, ProtocolInfo<S> outbound, ProtocolInfo<C> inbound, C listener, boolean transfer
) {
this.initiateServerboundConnection(hostName, port, outbound, inbound, listener, transfer ? ClientIntent.TRANSFER : ClientIntent.LOGIN);
}
private <S extends ServerboundPacketListener, C extends ClientboundPacketListener> void initiateServerboundConnection(
String hostName, int port, ProtocolInfo<S> outbound, ProtocolInfo<C> inbound, C listener, ClientIntent intent
) {
if (outbound.id() != inbound.id()) {
throw new IllegalStateException("Mismatched initial protocols");
} else {
this.disconnectListener = listener;
this.runOnceConnected(connection -> {
this.setupInboundProtocol(inbound, listener);
connection.sendPacket(new ClientIntentionPacket(SharedConstants.getCurrentVersion().protocolVersion(), hostName, port, intent), null, true);
this.setupOutboundProtocol(outbound);
});
}
}
public void send(Packet<?> packet) {
this.send(packet, null);
}
public void send(Packet<?> packet, @Nullable ChannelFutureListener listener) {
this.send(packet, listener, true);
}
public void send(Packet<?> packet, @Nullable ChannelFutureListener listener, boolean flush) {
if (this.isConnected()) {
this.flushQueue();
this.sendPacket(packet, listener, flush);
} else {
this.pendingActions.add(connection -> connection.sendPacket(packet, listener, flush));
}
}
public void runOnceConnected(Consumer<Connection> action) {
if (this.isConnected()) {
this.flushQueue();
action.accept(this);
} else {
this.pendingActions.add(action);
}
}
private void sendPacket(Packet<?> packet, @Nullable ChannelFutureListener listener, boolean flush) {
this.sentPackets++;
if (this.channel.eventLoop().inEventLoop()) {
this.doSendPacket(packet, listener, flush);
} else {
this.channel.eventLoop().execute(() -> this.doSendPacket(packet, listener, flush));
}
}
private void doSendPacket(Packet<?> packet, @Nullable ChannelFutureListener listener, boolean flush) {
if (listener != null) {
ChannelFuture future = flush ? this.channel.writeAndFlush(packet) : this.channel.write(packet);
future.addListener(listener);
} else if (flush) {
this.channel.writeAndFlush(packet, this.channel.voidPromise());
} else {
this.channel.write(packet, this.channel.voidPromise());
}
}
public void flushChannel() {
if (this.isConnected()) {
this.flush();
} else {
this.pendingActions.add(Connection::flush);
}
}
private void flush() {
if (this.channel.eventLoop().inEventLoop()) {
this.channel.flush();
} else {
this.channel.eventLoop().execute(() -> this.channel.flush());
}
}
private void flushQueue() {
if (this.channel != null && this.channel.isOpen()) {
synchronized (this.pendingActions) {
Consumer<Connection> pendingAction;
while ((pendingAction = this.pendingActions.poll()) != null) {
pendingAction.accept(this);
}
}
}
}
public void tick() {
this.flushQueue();
if (this.packetListener instanceof TickablePacketListener tickable) {
tickable.tick();
}
if (!this.isConnected() && !this.disconnectionHandled) {
this.handleDisconnection();
}
if (this.channel != null) {
this.channel.flush();
}
if (this.tickCount++ % 20 == 0) {
this.tickSecond();
}
if (this.bandwidthDebugMonitor != null) {
this.bandwidthDebugMonitor.tick();
}
}
protected void tickSecond() {
this.averageSentPackets = Mth.lerp(0.75F, (float)this.sentPackets, this.averageSentPackets);
this.averageReceivedPackets = Mth.lerp(0.75F, (float)this.receivedPackets, this.averageReceivedPackets);
this.sentPackets = 0;
this.receivedPackets = 0;
}
public SocketAddress getRemoteAddress() {
return this.address;
}
public String getLoggableAddress(boolean logIPs) {
if (this.address == null) {
return "local";
} else {
return logIPs ? this.address.toString() : "IP hidden";
}
}
public void disconnect(Component reason) {
this.disconnect(new DisconnectionDetails(reason));
}
public void disconnect(DisconnectionDetails details) {
if (this.channel == null) {
this.delayedDisconnect = details;
}
if (this.isConnected()) {
this.channel.close().awaitUninterruptibly();
this.disconnectionDetails = details;
}
}
public boolean isMemoryConnection() {
return this.channel instanceof LocalChannel || this.channel instanceof LocalServerChannel;
}
public PacketFlow getReceiving() {
return this.receiving;
}
public PacketFlow getSending() {
return this.receiving.getOpposite();
}
public static Connection connectToServer(InetSocketAddress address, EventLoopGroupHolder eventLoopGroupHolder, @Nullable LocalSampleLogger bandwidthLogger) {
Connection connection = new Connection(PacketFlow.CLIENTBOUND);
if (bandwidthLogger != null) {
connection.setBandwidthLogger(bandwidthLogger);
}
ChannelFuture connect = connect(address, eventLoopGroupHolder, connection);
connect.syncUninterruptibly();
return connection;
}
public static ChannelFuture connect(InetSocketAddress address, EventLoopGroupHolder eventLoopGroupHolder, Connection connection) {
return new Bootstrap().group(eventLoopGroupHolder.eventLoopGroup()).handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.config().setOption(ChannelOption.TCP_NODELAY, true);
} catch (ChannelException var3) {
}
ChannelPipeline pipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
Connection.configureSerialization(pipeline, PacketFlow.CLIENTBOUND, false, connection.bandwidthDebugMonitor);
connection.configurePacketHandler(pipeline);
}
}).channel(eventLoopGroupHolder.channelCls()).connect(address.getAddress(), address.getPort());
}
private static String outboundHandlerName(boolean configureOutbound) {
return configureOutbound ? "encoder" : "outbound_config";
}
private static String inboundHandlerName(boolean configureInbound) {
return configureInbound ? "decoder" : "inbound_config";
}
public void configurePacketHandler(ChannelPipeline pipeline) {
pipeline.addLast("hackfix", new ChannelOutboundHandlerAdapter() {
{
Objects.requireNonNull(Connection.this);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
super.write(ctx, msg, promise);
}
}).addLast("packet_handler", this);
}
public static void configureSerialization(ChannelPipeline pipeline, PacketFlow inboundDirection, boolean local, @Nullable BandwidthDebugMonitor monitor) {
PacketFlow outboundDirection = inboundDirection.getOpposite();
boolean configureInbound = inboundDirection == PacketFlow.SERVERBOUND;
boolean configureOutbound = outboundDirection == PacketFlow.SERVERBOUND;
pipeline.addLast("splitter", createFrameDecoder(monitor, local))
.addLast(new FlowControlHandler())
.addLast(
inboundHandlerName(configureInbound),
(ChannelHandler)(configureInbound ? new PacketDecoder<>(INITIAL_PROTOCOL) : new UnconfiguredPipelineHandler.Inbound())
)
.addLast("prepender", createFrameEncoder(local))
.addLast(
outboundHandlerName(configureOutbound),
(ChannelHandler)(configureOutbound ? new PacketEncoder<>(INITIAL_PROTOCOL) : new UnconfiguredPipelineHandler.Outbound())
);
}
private static ChannelOutboundHandler createFrameEncoder(boolean local) {
return (ChannelOutboundHandler)(local ? new LocalFrameEncoder() : new Varint21LengthFieldPrepender());
}
private static ChannelInboundHandler createFrameDecoder(@Nullable BandwidthDebugMonitor monitor, boolean local) {
if (!local) {
return new Varint21FrameDecoder(monitor);
} else {
return (ChannelInboundHandler)(monitor != null ? new MonitoredLocalFrameDecoder(monitor) : new LocalFrameDecoder());
}
}
public static void configureInMemoryPipeline(ChannelPipeline pipeline, PacketFlow packetFlow) {
configureSerialization(pipeline, packetFlow, true, null);
}
public static Connection connectToLocalServer(SocketAddress address) {
final Connection connection = new Connection(PacketFlow.CLIENTBOUND);
new Bootstrap().group(EventLoopGroupHolder.local().eventLoopGroup()).handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
ChannelPipeline pipeline = channel.pipeline();
Connection.configureInMemoryPipeline(pipeline, PacketFlow.CLIENTBOUND);
connection.configurePacketHandler(pipeline);
}
}).channel(EventLoopGroupHolder.local().channelCls()).connect(address).syncUninterruptibly();
return connection;
}
public void setEncryptionKey(Cipher decryptCipher, Cipher encryptCipher) {
this.encrypted = true;
this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptCipher));
this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptCipher));
}
public boolean isEncrypted() {
return this.encrypted;
}
public boolean isConnected() {
return this.channel != null && this.channel.isOpen();
}
public boolean isConnecting() {
return this.channel == null;
}
public @Nullable PacketListener getPacketListener() {
return this.packetListener;
}
public @Nullable DisconnectionDetails getDisconnectionDetails() {
return this.disconnectionDetails;
}
public void setReadOnly() {
if (this.channel != null) {
this.channel.config().setAutoRead(false);
}
}
public void setupCompression(int threshold, boolean validateDecompressed) {
if (threshold >= 0) {
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder compressionDecoder) {
compressionDecoder.setThreshold(threshold, validateDecompressed);
} else {
this.channel.pipeline().addAfter("splitter", "decompress", new CompressionDecoder(threshold, validateDecompressed));
}
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder compressionEncoder) {
compressionEncoder.setThreshold(threshold);
} else {
this.channel.pipeline().addAfter("prepender", "compress", new CompressionEncoder(threshold));
}
} else {
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
this.channel.pipeline().remove("decompress");
}
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
this.channel.pipeline().remove("compress");
}
}
}
public void handleDisconnection() {
if (this.channel != null && !this.channel.isOpen()) {
if (this.disconnectionHandled) {
LOGGER.warn("handleDisconnection() called twice");
} else {
this.disconnectionHandled = true;
PacketListener packetListener = this.getPacketListener();
PacketListener disconnectListener = packetListener != null ? packetListener : this.disconnectListener;
if (disconnectListener != null) {
DisconnectionDetails details = Objects.requireNonNullElseGet(
this.getDisconnectionDetails(), () -> new DisconnectionDetails(Component.translatable("multiplayer.disconnect.generic"))
);
disconnectListener.onDisconnect(details);
}
}
}
}
public float getAverageReceivedPackets() {
return this.averageReceivedPackets;
}
public float getAverageSentPackets() {
return this.averageSentPackets;
}
public void setBandwidthLogger(LocalSampleLogger bandwidthLogger) {
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(bandwidthLogger);
}
}引用的其他类
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SharedConstants.getCurrentVersion()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
BandwidthDebugMonitor()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
CipherDecoder()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
CipherEncoder()
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
CompressionDecoder()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
CompressionEncoder()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用/返回值 - 关联成员:
DisconnectionDetails()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
LocalFrameDecoder()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
LocalFrameEncoder()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
MonitoredLocalFrameDecoder()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
PacketBundlePacker()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
PacketBundleUnpacker()
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
PacketSendListener.thenRun()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
Inbound(), Outbound(), UnconfiguredPipelineHandler.Inbound(), UnconfiguredPipelineHandler.Outbound(), UnconfiguredPipelineHandler.setupInboundProtocol(), UnconfiguredPipelineHandler.setupOutboundProtocol()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
Varint21FrameDecoder()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
Varint21LengthFieldPrepender()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
Component.translatable()
- 引用位置:
-
- 引用位置:
参数/继承
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ClientboundDisconnectPacket()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ClientIntentionPacket()
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
ClientboundLoginDisconnectPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundLoginDisconnectPacket()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
EventLoopGroupHolder.local()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.lerp()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.make()
- 引用位置:
-
- 引用位置:
参数
- 引用位置: