diff --git a/core/src/main/java/com/xujiayao/discord_mc_chat/client/ClientHandler.java b/core/src/main/java/com/xujiayao/discord_mc_chat/client/ClientHandler.java index efe5c7fd..5b6cc996 100644 --- a/core/src/main/java/com/xujiayao/discord_mc_chat/client/ClientHandler.java +++ b/core/src/main/java/com/xujiayao/discord_mc_chat/client/ClientHandler.java @@ -28,6 +28,7 @@ public class ClientHandler extends SimpleChannelInboundHandler { private final NettyClient client; private final CompletableFuture initialLoginFuture; + private boolean allowReconnect = true; // Default to true for network errors public ClientHandler(NettyClient client, CompletableFuture initialLoginFuture) { this.client = client; @@ -41,12 +42,16 @@ public class ClientHandler extends SimpleChannelInboundHandler { @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.info(I18nManager.getDmccTranslation("client.network.disconnected_generic")); + LOGGER.warn(I18nManager.getDmccTranslation("client.network.disconnected_generic")); - // Trigger reconnection if this was not an intentional stop - if (client.isRunning()) { - LOGGER.info(I18nManager.getDmccTranslation("client.network.reconnecting")); + // Trigger reconnection if this was not an intentional stop AND the server didn't explicitly reject us + if (client.isRunning() && allowReconnect) { + LOGGER.warn(I18nManager.getDmccTranslation("client.network.reconnecting")); client.scheduleReconnect(); + } else { + // If we are not allowed to reconnect, we should probably stop the client fully + // to prevent any background threads from lingering or confusing state. + client.stop(); } } @@ -65,6 +70,11 @@ public class ClientHandler extends SimpleChannelInboundHandler { } } else if (packet instanceof DisconnectPacket p) { + // If we receive a DisconnectPacket, it means the server explicitly rejected us. + // In most cases (whitelist, auth fail, version mismatch), retrying immediately won't help. + // So we disable reconnection. + allowReconnect = false; + String reason = I18nManager.getDmccTranslation(p.key, p.args); LOGGER.error(I18nManager.getDmccTranslation("client.network.disconnected_reason", reason)); diff --git a/core/src/main/java/com/xujiayao/discord_mc_chat/client/NettyClient.java b/core/src/main/java/com/xujiayao/discord_mc_chat/client/NettyClient.java index b2549a1f..3df13998 100644 --- a/core/src/main/java/com/xujiayao/discord_mc_chat/client/NettyClient.java +++ b/core/src/main/java/com/xujiayao/discord_mc_chat/client/NettyClient.java @@ -105,7 +105,7 @@ public class NettyClient { b.connect(host, port).addListener((ChannelFuture future) -> { if (future.isSuccess()) { // Connection established - reconnectDelay.set(2); // Reset delay on success + reconnectDelay.set(1); // Reset delay on success } else { if (isInitialAttempt) { initialLoginFuture.completeExceptionally(future.cause()); diff --git a/core/src/main/java/com/xujiayao/discord_mc_chat/server/ServerHandler.java b/core/src/main/java/com/xujiayao/discord_mc_chat/server/ServerHandler.java index 3101616c..93321ba5 100644 --- a/core/src/main/java/com/xujiayao/discord_mc_chat/server/ServerHandler.java +++ b/core/src/main/java/com/xujiayao/discord_mc_chat/server/ServerHandler.java @@ -44,7 +44,7 @@ public class ServerHandler extends SimpleChannelInboundHandler { @Override public void channelInactive(ChannelHandlerContext ctx) { if (clientName != null) { - LOGGER.info(I18nManager.getDmccTranslation("server.network.client_disconnected_normal", clientName)); + LOGGER.warn(I18nManager.getDmccTranslation("server.network.client_disconnected_normal", clientName)); } } @@ -54,7 +54,7 @@ public class ServerHandler extends SimpleChannelInboundHandler { case HandshakePacket p -> { if (!isWhitelisted(p.serverName)) { String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.not_whitelisted", p.serverName); - LOGGER.warn(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); + LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", p.serverName, reason)); ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.not_whitelisted", p.serverName)); ctx.close(); return; @@ -62,7 +62,7 @@ public class ServerHandler extends SimpleChannelInboundHandler { if (!Constants.VERSION.equals(p.version)) { String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.version_mismatch", p.version, Constants.VERSION); - LOGGER.warn(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); + LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.version_mismatch", p.version, Constants.VERSION)); ctx.close(); return; @@ -82,7 +82,7 @@ public class ServerHandler extends SimpleChannelInboundHandler { // TODO: Add to active clients list } else { String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.auth_failed"); - LOGGER.warn(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); + LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.auth_failed")); ctx.close(); } @@ -94,7 +94,7 @@ public class ServerHandler extends SimpleChannelInboundHandler { // Handle other packets if authenticated if (!authenticated) { String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.not_authenticated"); - LOGGER.warn(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); + LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", clientName, reason)); ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.not_authenticated")); ctx.close(); } @@ -106,7 +106,7 @@ public class ServerHandler extends SimpleChannelInboundHandler { public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent e) { if (e.state() == IdleState.READER_IDLE) { - LOGGER.warn(I18nManager.getDmccTranslation("server.network.client_timeout", clientName != null ? clientName : "unknown")); + LOGGER.error(I18nManager.getDmccTranslation("server.network.client_timeout", clientName != null ? clientName : "unknown")); ctx.close(); } } else {