243 lines
11 KiB
Java
243 lines
11 KiB
Java
package net.minecraft.client.gui.screens;
|
|
|
|
import com.mojang.logging.LogUtils;
|
|
import io.netty.channel.ChannelFuture;
|
|
import java.net.InetSocketAddress;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.DefaultUncaughtExceptionHandler;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.GameNarrator;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.components.Button;
|
|
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
|
|
import net.minecraft.client.multiplayer.ServerData;
|
|
import net.minecraft.client.multiplayer.TransferState;
|
|
import net.minecraft.client.multiplayer.chat.report.ReportEnvironment;
|
|
import net.minecraft.client.multiplayer.resolver.ResolvedServerAddress;
|
|
import net.minecraft.client.multiplayer.resolver.ServerAddress;
|
|
import net.minecraft.client.multiplayer.resolver.ServerNameResolver;
|
|
import net.minecraft.client.quickplay.QuickPlay;
|
|
import net.minecraft.client.quickplay.QuickPlayLog;
|
|
import net.minecraft.client.resources.server.ServerPackManager;
|
|
import net.minecraft.network.Connection;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.protocol.PacketFlow;
|
|
import net.minecraft.network.protocol.login.LoginProtocols;
|
|
import net.minecraft.network.protocol.login.ServerboundHelloPacket;
|
|
import net.minecraftforge.api.distmarker.Dist;
|
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
import org.slf4j.Logger;
|
|
|
|
@OnlyIn(Dist.CLIENT)
|
|
public class ConnectScreen extends Screen {
|
|
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
|
|
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"));
|
|
@Nullable
|
|
volatile Connection connection;
|
|
@Nullable
|
|
ChannelFuture channelFuture;
|
|
volatile boolean aborted;
|
|
final Screen parent;
|
|
private Component status = Component.translatable("connect.connecting");
|
|
private long lastNarration = -1L;
|
|
final Component connectFailedTitle;
|
|
|
|
private ConnectScreen(Screen p_279215_, Component p_279228_) {
|
|
super(GameNarrator.NO_TITLE);
|
|
this.parent = p_279215_;
|
|
this.connectFailedTitle = p_279228_;
|
|
}
|
|
|
|
public static void startConnecting(
|
|
Screen p_279473_, Minecraft p_279200_, ServerAddress p_279150_, ServerData p_279481_, boolean p_279117_, @Nullable TransferState p_329293_
|
|
) {
|
|
if (p_279200_.screen instanceof ConnectScreen) {
|
|
LOGGER.error("Attempt to connect while already connecting");
|
|
} else {
|
|
Component component;
|
|
if (p_329293_ != null) {
|
|
component = CommonComponents.TRANSFER_CONNECT_FAILED;
|
|
} else if (p_279117_) {
|
|
component = QuickPlay.ERROR_TITLE;
|
|
} else {
|
|
component = CommonComponents.CONNECT_FAILED;
|
|
}
|
|
|
|
ConnectScreen connectscreen = new ConnectScreen(p_279473_, component);
|
|
if (p_329293_ != null) {
|
|
connectscreen.updateStatus(Component.translatable("connect.transferring"));
|
|
}
|
|
|
|
p_279200_.disconnect();
|
|
p_279200_.prepareForMultiplayer();
|
|
p_279200_.updateReportEnvironment(ReportEnvironment.thirdParty(p_279481_.ip));
|
|
p_279200_.quickPlayLog().setWorldData(QuickPlayLog.Type.MULTIPLAYER, p_279481_.ip, p_279481_.name);
|
|
p_279200_.setScreen(connectscreen);
|
|
connectscreen.connect(p_279200_, p_279150_, p_279481_, p_329293_);
|
|
}
|
|
}
|
|
|
|
private void connect(final Minecraft p_251955_, final ServerAddress p_249536_, final ServerData p_252078_, @Nullable final TransferState p_330037_) {
|
|
LOGGER.info("Connecting to {}, {}", p_249536_.getHost(), p_249536_.getPort());
|
|
Thread thread = new Thread("Server Connector #" + UNIQUE_THREAD_ID.incrementAndGet()) {
|
|
@Override
|
|
public void run() {
|
|
InetSocketAddress inetsocketaddress = null;
|
|
|
|
try {
|
|
if (ConnectScreen.this.aborted) {
|
|
return;
|
|
}
|
|
|
|
Optional<InetSocketAddress> optional = ServerNameResolver.DEFAULT.resolveAddress(p_249536_).map(ResolvedServerAddress::asInetSocketAddress);
|
|
if (ConnectScreen.this.aborted) {
|
|
return;
|
|
}
|
|
|
|
if (optional.isEmpty()) {
|
|
p_251955_.execute(
|
|
() -> p_251955_.setScreen(new DisconnectedScreen(ConnectScreen.this.parent, ConnectScreen.this.connectFailedTitle, ConnectScreen.UNKNOWN_HOST_MESSAGE))
|
|
);
|
|
return;
|
|
}
|
|
|
|
inetsocketaddress = optional.get();
|
|
Connection connection;
|
|
synchronized (ConnectScreen.this) {
|
|
if (ConnectScreen.this.aborted) {
|
|
return;
|
|
}
|
|
|
|
connection = new Connection(PacketFlow.CLIENTBOUND);
|
|
connection.setBandwidthLogger(p_251955_.getDebugOverlay().getBandwidthLogger());
|
|
ConnectScreen.this.channelFuture = Connection.connect(inetsocketaddress, p_251955_.options.useNativeTransport(), connection);
|
|
}
|
|
|
|
ConnectScreen.this.channelFuture.syncUninterruptibly();
|
|
synchronized (ConnectScreen.this) {
|
|
if (ConnectScreen.this.aborted) {
|
|
connection.disconnect(ConnectScreen.ABORT_CONNECTION);
|
|
return;
|
|
}
|
|
|
|
ConnectScreen.this.connection = connection;
|
|
p_251955_.getDownloadedPackSource().configureForServerControl(connection, convertPackStatus(p_252078_.getResourcePackStatus()));
|
|
}
|
|
|
|
ConnectScreen.this.connection
|
|
.initiateServerboundPlayConnection(
|
|
inetsocketaddress.getHostName(),
|
|
inetsocketaddress.getPort(),
|
|
LoginProtocols.SERVERBOUND,
|
|
LoginProtocols.CLIENTBOUND,
|
|
new ClientHandshakePacketListenerImpl(
|
|
ConnectScreen.this.connection,
|
|
p_251955_,
|
|
p_252078_,
|
|
ConnectScreen.this.parent,
|
|
false,
|
|
null,
|
|
ConnectScreen.this::updateStatus,
|
|
p_330037_
|
|
),
|
|
p_330037_ != null
|
|
);
|
|
ConnectScreen.this.connection.send(new ServerboundHelloPacket(p_251955_.getUser().getName(), p_251955_.getUser().getProfileId()));
|
|
} catch (Exception exception2) {
|
|
if (ConnectScreen.this.aborted) {
|
|
return;
|
|
}
|
|
|
|
Exception exception;
|
|
if (exception2.getCause() instanceof Exception exception1) {
|
|
exception = exception1;
|
|
} else {
|
|
exception = exception2;
|
|
}
|
|
|
|
ConnectScreen.LOGGER.error("Couldn't connect to server", (Throwable)exception2);
|
|
String s = inetsocketaddress == null
|
|
? exception.getMessage()
|
|
: exception.getMessage()
|
|
.replaceAll(inetsocketaddress.getHostName() + ":" + inetsocketaddress.getPort(), "")
|
|
.replaceAll(inetsocketaddress.toString(), "");
|
|
p_251955_.execute(
|
|
() -> p_251955_.setScreen(
|
|
new DisconnectedScreen(
|
|
ConnectScreen.this.parent, ConnectScreen.this.connectFailedTitle, Component.translatable("disconnect.genericReason", s)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
private static ServerPackManager.PackPromptStatus convertPackStatus(ServerData.ServerPackStatus p_310302_) {
|
|
return switch (p_310302_) {
|
|
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 p_95718_) {
|
|
this.status = p_95718_;
|
|
}
|
|
|
|
@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, p_289624_ -> {
|
|
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 render(GuiGraphics p_283201_, int p_95701_, int p_95702_, float p_95703_) {
|
|
super.render(p_283201_, p_95701_, p_95702_, p_95703_);
|
|
long i = Util.getMillis();
|
|
if (i - this.lastNarration > 2000L) {
|
|
this.lastNarration = i;
|
|
this.minecraft.getNarrator().sayNow(Component.translatable("narrator.joining"));
|
|
}
|
|
|
|
p_283201_.drawCenteredString(this.font, this.status, this.width / 2, this.height / 2 - 50, 16777215);
|
|
}
|
|
} |