新增Minecraft版本验证,优化握手和断开连接逻辑

This commit is contained in:
Xujiayao 2026-01-23 13:14:49 +08:00
parent 616a8a704c
commit 164aff814b
7 changed files with 51 additions and 10 deletions

View file

@ -9,6 +9,7 @@ import com.xujiayao.discord_mc_chat.network.packets.KeepAlivePacket;
import com.xujiayao.discord_mc_chat.network.packets.LoginSuccessPacket;
import com.xujiayao.discord_mc_chat.network.packets.Packet;
import com.xujiayao.discord_mc_chat.utils.CryptUtils;
import com.xujiayao.discord_mc_chat.utils.EnvironmentUtils;
import com.xujiayao.discord_mc_chat.utils.i18n.I18nManager;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@ -37,7 +38,7 @@ public class ClientHandler extends SimpleChannelInboundHandler<Packet> {
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(new HandshakePacket(client.getServerName(), Constants.VERSION));
ctx.writeAndFlush(new HandshakePacket(client.getServerName(), Constants.VERSION, EnvironmentUtils.getMinecraftVersion()));
}
@Override

View file

@ -7,10 +7,12 @@ package com.xujiayao.discord_mc_chat.network.packets;
*/
public class HandshakePacket extends Packet {
public String serverName;
public String version;
public String dmccVersion;
public String minecraftVersion;
public HandshakePacket(String serverName, String version) {
public HandshakePacket(String serverName, String dmccVersion, String minecraftVersion) {
this.serverName = serverName;
this.version = version;
this.dmccVersion = dmccVersion;
this.minecraftVersion = minecraftVersion;
}
}

View file

@ -96,10 +96,18 @@ public class ServerHandler extends SimpleChannelInboundHandler<Packet> {
}
}
if (!Constants.VERSION.equals(p.version)) {
String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.version_mismatch", p.version, Constants.VERSION);
LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", clientName, reason));
ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.version_mismatch", p.version, Constants.VERSION));
if (!Constants.VERSION.equals(p.dmccVersion)) {
String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.version_mismatch", "DMCC", p.dmccVersion, Constants.VERSION);
LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", p.serverName, reason));
ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.version_mismatch", "DMCC", p.dmccVersion, Constants.VERSION));
ctx.close();
return;
}
if (!getMinecraftVersion(p.serverName).equals(p.minecraftVersion)) {
String reason = I18nManager.getDmccTranslation("server.network.disconnect_reasons.version_mismatch", "Minecraft", p.minecraftVersion, getMinecraftVersion(p.serverName));
LOGGER.error(I18nManager.getDmccTranslation("server.network.reject", p.serverName, reason));
ctx.writeAndFlush(new DisconnectPacket("server.network.disconnect_reasons.version_mismatch", "Minecraft", p.minecraftVersion, getMinecraftVersion(p.serverName)));
ctx.close();
return;
}
@ -157,4 +165,16 @@ public class ServerHandler extends SimpleChannelInboundHandler<Packet> {
}
return false;
}
private String getMinecraftVersion(String serverName) {
JsonNode serversNode = ConfigManager.getConfigNode("multi_server.servers");
if (serversNode.isArray()) {
for (JsonNode node : serversNode) {
if (serverName.equals(node.path("name").asText())) {
return node.path("minecraft_version").asText();
}
}
}
return "";
}
}

View file

@ -29,6 +29,23 @@ public class EnvironmentUtils {
return false;
}
/**
* Gets the Minecraft version using reflection.
* Should only be called if running in a Minecraft environment.
*
* @return The Minecraft version as a string.
*/
public static String getMinecraftVersion() {
try {
// SharedConstants.getCurrentVersion().name()
Class<?> sharedConstantsClass = Class.forName("net.minecraft.SharedConstants");
Object worldVersionObject = sharedConstantsClass.getMethod("getCurrentVersion").invoke(null);
return (String) worldVersionObject.getClass().getMethod("name").invoke(worldVersionObject);
} catch (Exception e) {
throw new RuntimeException("Failed to get Minecraft version", e);
}
}
/**
* Gets the DMCC version from the template "mode.yml" file in resources.
*

View file

@ -23,6 +23,7 @@ multi_server:
servers:
# This list acts as a whitelist. Only clients with a server name defined here are allowed to connect.
- name: "SMP"
minecraft_version: "1.21.10"
avatar_url: ""
color: "yellow"
start_command: "./SMP/start.bat" # command or url

View file

@ -76,7 +76,7 @@ server:
disconnect_reasons:
single_server_mode: "DMCC Server is in single_server mode, rejecting any additional client connections."
not_whitelisted: "Name \"{}\" is not whitelisted."
version_mismatch: "Version mismatch. Client: {}, Server: {}"
version_mismatch: "{} version mismatch. Client: {}, Server: {}"
auth_failed: "Authentication failed. Please check your shared secret."
exception_caught: "Netty caught an exception."

View file

@ -76,7 +76,7 @@ server:
disconnect_reasons:
single_server_mode: "DMCC 服务端处于 single_server 模式,拒绝任何额外客户端连接。"
not_whitelisted: "名称 \"{}\" 不在白名单中。"
version_mismatch: "版本不匹配。客户端:{},服务端:{}"
version_mismatch: "{} 版本不匹配。客户端:{},服务端:{}"
auth_failed: "验证失败。请检查你的共享密钥。"
exception_caught: "Netty 捕获到一个异常。"