ConnectScreen.java

net.minecraft.client.gui.screens.ConnectScreen

信息

  • 全限定名:net.minecraft.client.gui.screens.ConnectScreen
  • 类型:public class
  • 包:net.minecraft.client.gui.screens
  • 源码路径:src/main/java/net/minecraft/client/gui/screens/ConnectScreen.java
  • 起始行号:L39
  • 继承:Screen
  • 职责:

    TODO

字段/常量

  • UNIQUE_THREAD_ID

    • 类型: AtomicInteger
    • 修饰符: private static final
    • 源码定位: L40
    • 说明:

      TODO

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L41
    • 说明:

      TODO

  • NARRATION_DELAY_MS

    • 类型: long
    • 修饰符: private static final
    • 源码定位: L42
    • 说明:

      TODO

  • ABORT_CONNECTION

    • 类型: Component
    • 修饰符: public static final
    • 源码定位: L43
    • 说明:

      TODO

  • UNKNOWN_HOST_MESSAGE

    • 类型: Component
    • 修饰符: public static final
    • 源码定位: L44
    • 说明:

      TODO

  • connection

    • 类型: Connection
    • 修饰符: private volatile
    • 源码定位: L45
    • 说明:

      TODO

  • channelFuture

    • 类型: ChannelFuture
    • 修饰符: private
    • 源码定位: L46
    • 说明:

      TODO

  • aborted

    • 类型: boolean
    • 修饰符: private volatile
    • 源码定位: L47
    • 说明:

      TODO

  • parent

    • 类型: Screen
    • 修饰符: private final
    • 源码定位: L48
    • 说明:

      TODO

  • status

    • 类型: Component
    • 修饰符: private
    • 源码定位: L49
    • 说明:

      TODO

  • lastNarration

    • 类型: long
    • 修饰符: private
    • 源码定位: L50
    • 说明:

      TODO

  • connectFailedTitle

    • 类型: Component
    • 修饰符: private final
    • 源码定位: L51
    • 说明:

      TODO

内部类/嵌套类型

构造器

private ConnectScreen(Screen parent, Component connectFailedTitle) @ L53

  • 构造器名:ConnectScreen
  • 源码定位:L53
  • 修饰符:private

参数:

  • parent: Screen
  • connectFailedTitle: Component

说明:

TODO

方法

下面的方法块按源码顺序生成。

public static void startConnecting(Screen parent, Minecraft minecraft, ServerAddress hostAndPort, ServerData data, boolean isQuickPlay, TransferState transferState) @ L59

  • 方法名:startConnecting
  • 源码定位:L59
  • 返回类型:void
  • 修饰符:public static

参数:

  • parent: Screen
  • minecraft: Minecraft
  • hostAndPort: ServerAddress
  • data: ServerData
  • isQuickPlay: boolean
  • transferState: TransferState

说明:

TODO

private void connect(Minecraft minecraft, ServerAddress hostAndPort, ServerData server, TransferState transferState) @ L88

  • 方法名:connect
  • 源码定位:L88
  • 返回类型:void
  • 修饰符:private

参数:

  • minecraft: Minecraft
  • hostAndPort: ServerAddress
  • server: ServerData
  • transferState: TransferState

说明:

TODO

private void updateStatus(Component status) @ L203

  • 方法名:updateStatus
  • 源码定位:L203
  • 返回类型:void
  • 修饰符:private

参数:

  • status: Component

说明:

TODO

public void tick() @ L207

  • 方法名:tick
  • 源码定位:L207
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public boolean shouldCloseOnEsc() @ L218

  • 方法名:shouldCloseOnEsc
  • 源码定位:L218
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

protected void init() @ L223

  • 方法名:init
  • 源码定位:L223
  • 返回类型:void
  • 修饰符:protected

参数:

说明:

TODO

public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L242

  • 方法名:extractRenderState
  • 源码定位:L242
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • mouseX: int
  • mouseY: int
  • a: float

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class ConnectScreen extends Screen {
    private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final long NARRATION_DELAY_MS = 2000L;
    public static final Component ABORT_CONNECTION = Component.translatable("connect.aborted");
    public static final Component UNKNOWN_HOST_MESSAGE = Component.translatable("disconnect.genericReason", Component.translatable("disconnect.unknownHost"));
    private volatile @Nullable Connection connection;
    private @Nullable ChannelFuture channelFuture;
    private volatile boolean aborted;
    private final Screen parent;
    private Component status = Component.translatable("connect.connecting");
    private long lastNarration = -1L;
    private final Component connectFailedTitle;
 
    private ConnectScreen(Screen parent, Component connectFailedTitle) {
        super(GameNarrator.NO_TITLE);
        this.parent = parent;
        this.connectFailedTitle = connectFailedTitle;
    }
 
    public static void startConnecting(
        Screen parent, Minecraft minecraft, ServerAddress hostAndPort, ServerData data, boolean isQuickPlay, @Nullable TransferState transferState
    ) {
        if (minecraft.screen instanceof ConnectScreen) {
            LOGGER.error("Attempt to connect while already connecting");
        } else {
            Component connectFailedTitle;
            if (transferState != null) {
                connectFailedTitle = CommonComponents.TRANSFER_CONNECT_FAILED;
            } else if (isQuickPlay) {
                connectFailedTitle = QuickPlay.ERROR_TITLE;
            } else {
                connectFailedTitle = CommonComponents.CONNECT_FAILED;
            }
 
            ConnectScreen screen = new ConnectScreen(parent, connectFailedTitle);
            if (transferState != null) {
                screen.updateStatus(Component.translatable("connect.transferring"));
            }
 
            minecraft.disconnectWithProgressScreen(false);
            minecraft.prepareForMultiplayer();
            minecraft.updateReportEnvironment(ReportEnvironment.thirdParty(data.ip));
            minecraft.quickPlayLog().setWorldData(QuickPlayLog.Type.MULTIPLAYER, data.ip, data.name);
            minecraft.setScreen(screen);
            screen.connect(minecraft, hostAndPort, data, transferState);
        }
    }
 
    private void connect(Minecraft minecraft, ServerAddress hostAndPort, ServerData server, @Nullable TransferState transferState) {
        LOGGER.info("Connecting to {}, {}", hostAndPort.getHost(), hostAndPort.getPort());
        Thread thread = new Thread("Server Connector #" + UNIQUE_THREAD_ID.incrementAndGet()) {
            {
                Objects.requireNonNull(ConnectScreen.this);
            }
 
            @Override
            public void run() {
                InetSocketAddress address = null;
 
                try {
                    if (ConnectScreen.this.aborted) {
                        return;
                    }
 
                    Optional<InetSocketAddress> resolvedAddress = ServerNameResolver.DEFAULT
                        .resolveAddress(hostAndPort)
                        .map(ResolvedServerAddress::asInetSocketAddress);
                    if (ConnectScreen.this.aborted) {
                        return;
                    }
 
                    if (resolvedAddress.isEmpty()) {
                        minecraft.execute(
                            () -> minecraft.setScreen(
                                new DisconnectedScreen(ConnectScreen.this.parent, ConnectScreen.this.connectFailedTitle, ConnectScreen.UNKNOWN_HOST_MESSAGE)
                            )
                        );
                        return;
                    }
 
                    address = resolvedAddress.get();
                    Connection pendingConnection;
                    synchronized (ConnectScreen.this) {
                        if (ConnectScreen.this.aborted) {
                            return;
                        }
 
                        pendingConnection = new Connection(PacketFlow.CLIENTBOUND);
                        pendingConnection.setBandwidthLogger(minecraft.getDebugOverlay().getBandwidthLogger());
                        ConnectScreen.this.channelFuture = Connection.connect(
                            address, EventLoopGroupHolder.remote(minecraft.options.useNativeTransport()), pendingConnection
                        );
                    }
 
                    ConnectScreen.this.channelFuture.syncUninterruptibly();
                    synchronized (ConnectScreen.this) {
                        if (ConnectScreen.this.aborted) {
                            pendingConnection.disconnect(ConnectScreen.ABORT_CONNECTION);
                            return;
                        }
 
                        ConnectScreen.this.connection = pendingConnection;
                        minecraft.getDownloadedPackSource().configureForServerControl(pendingConnection, convertPackStatus(server.getResourcePackStatus()));
                    }
 
                    ConnectScreen.this.connection
                        .initiateServerboundPlayConnection(
                            address.getHostName(),
                            address.getPort(),
                            LoginProtocols.SERVERBOUND,
                            LoginProtocols.CLIENTBOUND,
                            new ClientHandshakePacketListenerImpl(
                                ConnectScreen.this.connection,
                                minecraft,
                                server,
                                ConnectScreen.this.parent,
                                false,
                                null,
                                ConnectScreen.this::updateStatus,
                                new LevelLoadTracker(),
                                transferState
                            ),
                            transferState != null
                        );
                    ConnectScreen.this.connection.send(new ServerboundHelloPacket(minecraft.getUser().getName(), minecraft.getUser().getProfileId()));
                } catch (Exception var9) {
                    if (ConnectScreen.this.aborted) {
                        return;
                    }
 
                    Exception cause;
                    if (var9.getCause() instanceof Exception originalCause) {
                        cause = originalCause;
                    } else {
                        cause = var9;
                    }
 
                    ConnectScreen.LOGGER.error("Couldn't connect to server", (Throwable)var9);
                    String message = address == null
                        ? cause.getMessage()
                        : cause.getMessage().replaceAll(address.getHostName() + ":" + address.getPort(), "").replaceAll(address.toString(), "");
                    minecraft.execute(
                        () -> minecraft.setScreen(
                            new DisconnectedScreen(
                                ConnectScreen.this.parent, ConnectScreen.this.connectFailedTitle, Component.translatable("disconnect.genericReason", message)
                            )
                        )
                    );
                }
            }
 
            private static ServerPackManager.PackPromptStatus convertPackStatus(ServerData.ServerPackStatus resourcePackStatus) {
                return switch (resourcePackStatus) {
                    case ENABLED -> ServerPackManager.PackPromptStatus.ALLOWED;
                    case DISABLED -> ServerPackManager.PackPromptStatus.DECLINED;
                    case PROMPT -> ServerPackManager.PackPromptStatus.PENDING;
                };
            }
        };
        thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
        thread.start();
    }
 
    private void updateStatus(Component status) {
        this.status = status;
    }
 
    @Override
    public void tick() {
        if (this.connection != null) {
            if (this.connection.isConnected()) {
                this.connection.tick();
            } else {
                this.connection.handleDisconnection();
            }
        }
    }
 
    @Override
    public boolean shouldCloseOnEsc() {
        return false;
    }
 
    @Override
    protected void init() {
        this.addRenderableWidget(Button.builder(CommonComponents.GUI_CANCEL, button -> {
            synchronized (this) {
                this.aborted = true;
                if (this.channelFuture != null) {
                    this.channelFuture.cancel(true);
                    this.channelFuture = null;
                }
 
                if (this.connection != null) {
                    this.connection.disconnect(ABORT_CONNECTION);
                }
            }
 
            this.minecraft.setScreen(this.parent);
        }).bounds(this.width / 2 - 100, this.height / 4 + 120 + 12, 200, 20).build());
    }
 
    @Override
    public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
        super.extractRenderState(graphics, mouseX, mouseY, a);
        long current = Util.getMillis();
        if (current - this.lastNarration > 2000L) {
            this.lastNarration = current;
            this.minecraft.getNarrator().saySystemNow(Component.translatable("narrator.joining"));
        }
 
        graphics.centeredText(this.font, this.status, this.width / 2, this.height / 2 - 50, -1);
    }
}

引用的其他类