Skip to content

Commit b91f002

Browse files
[1.5]修复部分BUG
1 parent 2131e82 commit b91f002

3 files changed

Lines changed: 111 additions & 98 deletions

File tree

src/main/java/ict/minesunshineone/simpleTransfer/SimpleTransfer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void onProxyInitialization(ProxyInitializeEvent event) {
5959
configManager = new ConfigManager(logger, dataDirectory);
6060

6161
// 初始化玩家连接管理器
62-
connectionManager = new PlayerConnectionManager(logger, server, configManager, dataDirectory, this);
62+
connectionManager = new PlayerConnectionManager(logger, server, configManager, dataDirectory);
6363

6464
// 初始化延迟监控器
6565
pingMonitor = new PingMonitor(server, configManager, logger);

src/main/java/ict/minesunshineone/simpleTransfer/command/MainCommand.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ private void reloadConfig(Invocation invocation, String[] args) {
525525
invocation.source().sendMessage(Component.text(" "));
526526

527527
boolean reloadConfigFile = reloadType.equals("config") || reloadType.equals("all");
528-
boolean reloadRulesFile = reloadType.equals("rules") || reloadType.equals("all");
528+
boolean reloadRulesFile = reloadType.equals("rules");
529529

530530
// 重新加载配置
531531
if (reloadConfigFile) {
@@ -545,6 +545,14 @@ private void reloadConfig(Invocation invocation, String[] args) {
545545
.append(Component.text(String.valueOf(configManager.getTransferRules().size()), net.kyori.adventure.text.format.TextColor.color(0xFFDD00)))
546546
.append(Component.text(" 条规则)", net.kyori.adventure.text.format.TextColor.color(0xAAFFAA)))
547547
.build());
548+
} else if (reloadConfigFile) {
549+
invocation.source().sendMessage(Component.text()
550+
.append(Component.text(" ➤ ", net.kyori.adventure.text.format.TextColor.color(0x00DDFF)))
551+
.append(Component.text("路由规则已重载 (", net.kyori.adventure.text.format.TextColor.color(0xAAFFAA)))
552+
.append(Component.text(String.valueOf(configManager.getTransferRules().size()), net.kyori.adventure.text.format.TextColor.color(0xFFDD00)))
553+
.append(Component.text(" 条规则)", net.kyori.adventure.text.format.TextColor.color(0xAAFFAA)))
554+
.append(Component.text(" [随配置重载]", NamedTextColor.GRAY))
555+
.build());
548556
}
549557

550558
// 重新加载命令
@@ -878,27 +886,12 @@ private void adminTransferPlayer(Invocation invocation, String[] args) {
878886
return;
879887
}
880888

881-
connectionManager.findPlayerUuidByName(targetInput)
882-
.ifPresentOrElse(uuid -> updateOfflineRouteRecord(source, uuid, targetInput, routeName, serverInfo),
883-
() -> sendAsyncMessage(source, Component.text()
884-
.append(Component.text(" ✘ ", NamedTextColor.RED))
885-
.append(Component.text("未找到玩家 " + targetInput + " 的历史线路记录,请确认名称是否正确或直接使用 UUID", net.kyori.adventure.text.format.TextColor.color(0xFFAAAA)))
886-
.build()));
887889
connectionManager.findPlayerUuidByName(targetInput)
888-
.ifPresentOrElse(uuid -> {
889-
if (connectionManager.isFloodgatePlayer(uuid)) {
890-
sendAsyncMessage(source, Component.text()
891-
.append(Component.text(" ✦ ", NamedTextColor.GOLD))
892-
.append(Component.text("目标玩家通过 Geyser/Floodgate 连接,已跳过 SimpleTransfer 处理", net.kyori.adventure.text.format.TextColor.color(0xFFDD55)))
893-
.build());
894-
return;
895-
}
896-
897-
updateOfflineRouteRecord(source, uuid, targetInput, routeName, serverInfo);
898-
}, () -> sendAsyncMessage(source, Component.text()
899-
.append(Component.text(" ✘ ", NamedTextColor.RED))
900-
.append(Component.text("未找到玩家 " + targetInput + " 的历史线路记录,请确认名称是否正确或直接使用 UUID", net.kyori.adventure.text.format.TextColor.color(0xFFAAAA)))
901-
.build()));
890+
.ifPresentOrElse(uuid -> updateOfflineRouteRecord(source, uuid, targetInput, routeName, serverInfo),
891+
() -> sendAsyncMessage(source, Component.text()
892+
.append(Component.text(" ✘ ", NamedTextColor.RED))
893+
.append(Component.text("未找到玩家 " + targetInput + " 的历史线路记录,请确认名称是否正确或直接使用 UUID", net.kyori.adventure.text.format.TextColor.color(0xFFAAAA)))
894+
.build()));
902895
}
903896

904897
private void updateOfflineRouteRecord(CommandSource source, UUID targetUuid, String targetName,

src/main/java/ict/minesunshineone/simpleTransfer/connection/PlayerConnectionManager.java

Lines changed: 96 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public class PlayerConnectionManager {
3131
private final Logger logger;
3232
private final ProxyServer server;
3333
private final ConfigManager configManager;
34-
private final Object plugin;
3534
private final DatabaseManager databaseManager;
3635
private final GeoIPManager geoIPManager;
3736

@@ -95,11 +94,10 @@ public class PlayerConnectionManager {
9594
});
9695

9796
public PlayerConnectionManager(Logger logger, ProxyServer server, ConfigManager configManager,
98-
Path dataPath, Object plugin) {
97+
Path dataPath) {
9998
this.logger = logger;
10099
this.server = server;
101100
this.configManager = configManager;
102-
this.plugin = plugin;
103101

104102
// 初始化数据库管理器
105103
this.databaseManager = new DatabaseManager(logger, dataPath, configManager);
@@ -184,105 +182,125 @@ public void initializePlayer(Player player) {
184182
// 默认启用延迟监控
185183
pingMonitorEnabled.putIfAbsent(uuid, true);
186184

187-
// 获取IP信息(异步,仅在第一次连接时检测)
188-
if (!ipInfoCache.containsKey(uuid)) {
189-
detectIPInfo(player);
190-
}
191-
192185
// 如果玩家没有历史线路记录,尝试从数据库加载
193-
if (!lastRoutes.containsKey(uuid)) {
186+
boolean hasExistingRoute = lastRoutes.containsKey(uuid);
187+
if (!hasExistingRoute) {
194188
String savedRoute = loadPlayerRoute(uuid);
195189
if (savedRoute != null) {
196190
lastRoutes.put(uuid, savedRoute);
191+
hasExistingRoute = true;
197192
logDebug("玩家 {} 从数据库加载线路记录: {}", player.getUsername(), savedRoute);
198193

199194
CompletableFuture.supplyAsync(() -> databaseManager.saveRoute(uuid, savedRoute, player.getUsername()), databaseExecutor)
200195
.exceptionally(e -> {
201196
logger.error("更新玩家 {} 的用户名记录时出错", player.getUsername(), e);
202197
return false;
203198
});
204-
} else {
205-
// 数据库也没有记录,检测玩家地理位置后设置默认线路
206-
setDefaultRouteForNewPlayer(player);
207199
}
208200
}
201+
202+
// 获取IP信息(异步,仅在第一次连接时检测)
203+
if (!ipInfoCache.containsKey(uuid)) {
204+
detectIPInfo(player, hasExistingRoute);
205+
} else {
206+
applyRulesForPlayer(player, hasExistingRoute);
207+
}
209208
}
210209

211210
/**
212-
* 为新玩家设置默认线路(根据配置文件设置)
211+
* 根据规则为玩家分配或覆写线路
212+
* @param player 当前玩家
213+
* @param hasHistory 是否已经存在历史线路(true 表示允许覆盖已有线路)
213214
*/
214-
private void setDefaultRouteForNewPlayer(Player player) {
215+
private void applyRulesForPlayer(Player player, boolean hasHistory) {
216+
if (!configManager.isRulesEnabled()) {
217+
return;
218+
}
219+
215220
UUID uuid = player.getUniqueId();
216-
217-
// 异步检测完成后设置默认线路
218-
server.getScheduler().buildTask(plugin, () -> {
219-
IPInfo info = ipInfoCache.get(uuid);
220-
221-
if (info == null) {
222-
logDebug("玩家 {} IP 信息未就绪,跳过规则匹配", player.getUsername());
223-
return;
224-
}
225-
226-
// 检查是否有历史记录
227-
boolean hasHistory = databaseManager.getRoute(uuid) != null;
228-
229-
// 获取虚拟主机信息
230-
String hostname = player.getVirtualHost()
221+
IPInfo info = ipInfoCache.get(uuid);
222+
223+
if (info == null) {
224+
logDebug("玩家 {} IP 信息未就绪,暂不应用路由规则", player.getUsername());
225+
return;
226+
}
227+
228+
String hostname = player.getVirtualHost()
231229
.map(address -> address.getHostString())
232230
.orElse("unknown");
233-
234-
// 构建玩家上下文
235-
TransferRule.PlayerContext context = new TransferRule.PlayerContext(
236-
info.country, // country: 国家
237-
info.province, // province: 省份
238-
info.isp, // isp: 运营商
239-
hasHistory, // has_history: 是否有历史记录
240-
uuid, // uuid: 玩家 UUID
241-
hostname // hostname: 虚拟主机名
242-
);
243-
244-
// 尝试匹配规则
245-
List<TransferRule> rules = configManager.getTransferRules();
246-
for (TransferRule rule : rules) {
247-
if (rule.matches(context)) {
248-
String targetRoute = rule.executeAction();
249-
250-
if (targetRoute != null) {
251-
// 检查目标线路是否存在
252-
if (configManager.getTransferServers().containsKey(targetRoute)) {
253-
// 检查是否最近连接失败过
254-
if (isServerRecentlyFailed(uuid, targetRoute)) {
255-
logger.warn("玩家 {} 匹配规则 [{}] 但目标线路 {} 最近连接失败,跳过此规则",
256-
player.getUsername(), rule.getName(), targetRoute);
257-
continue; // 尝试下一个规则
258-
}
259-
260-
lastRoutes.put(uuid, targetRoute);
261-
logDebug("玩家 {} 匹配规则 [{}],分配 {} 线路",
262-
player.getUsername(), rule.getName(), targetRoute.toUpperCase());
263-
return; // 匹配到规则后立即返回
264-
} else {
265-
logger.warn("规则 [{}] 指定的线路 {} 不存在,玩家 {} 跳过此规则",
266-
rule.getName(), targetRoute, player.getUsername());
267-
}
268-
} else {
269-
logDebug("玩家 {} 匹配规则 [{}],跳过自动分配",
270-
player.getUsername(), rule.getName());
271-
return; // skip 动作也会停止后续规则匹配
272-
}
273-
}
231+
232+
TransferRule.PlayerContext context = new TransferRule.PlayerContext(
233+
info.country,
234+
info.province,
235+
info.isp,
236+
hasHistory,
237+
uuid,
238+
hostname
239+
);
240+
241+
List<TransferRule> rules = configManager.getTransferRules();
242+
if (rules.isEmpty()) {
243+
return;
244+
}
245+
246+
for (TransferRule rule : rules) {
247+
if (!rule.matches(context)) {
248+
continue;
274249
}
275-
276-
// 如果没有规则匹配或所有匹配的服务器都失败过,使用安全服务器
250+
251+
String targetRoute = rule.executeAction();
252+
253+
if (targetRoute == null) {
254+
logDebug("玩家 {} 匹配规则 [{}],执行 skip 动作", player.getUsername(), rule.getName());
255+
return;
256+
}
257+
258+
if (!configManager.getTransferServers().containsKey(targetRoute)) {
259+
logger.warn("规则 [{}] 指定的线路 {} 不存在,玩家 {} 跳过此规则", rule.getName(), targetRoute, player.getUsername());
260+
continue;
261+
}
262+
263+
if (isServerRecentlyFailed(uuid, targetRoute)) {
264+
logger.warn("玩家 {} 匹配规则 [{}] 但目标线路 {} 最近连接失败,跳过此规则", player.getUsername(), rule.getName(), targetRoute);
265+
continue;
266+
}
267+
268+
String previousRoute = lastRoutes.get(uuid);
269+
if (previousRoute != null && previousRoute.equalsIgnoreCase(targetRoute)) {
270+
logDebug("玩家 {} 匹配规则 [{}],已在线路 {},无需调整", player.getUsername(), rule.getName(), targetRoute.toUpperCase());
271+
return;
272+
}
273+
274+
lastRoutes.put(uuid, targetRoute);
275+
276+
if (hasHistory && previousRoute != null) {
277+
logger.info("玩家 {} 匹配规则 [{}],线路从 {} 切换为 {}", player.getUsername(), rule.getName(), previousRoute.toUpperCase(), targetRoute.toUpperCase());
278+
} else {
279+
logDebug("玩家 {} 匹配规则 [{}],分配 {} 线路", player.getUsername(), rule.getName(), targetRoute.toUpperCase());
280+
}
281+
282+
CompletableFuture.supplyAsync(() -> databaseManager.saveRoute(uuid, targetRoute, player.getUsername()), databaseExecutor)
283+
.thenAccept(saved -> {
284+
if (!saved) {
285+
logger.warn("保存玩家 {} 的线路 {} 时失败", player.getUsername(), targetRoute);
286+
}
287+
})
288+
.exceptionally(e -> {
289+
logger.error("保存玩家 {} 的线路记录时发生异常", player.getUsername(), e);
290+
return null;
291+
});
292+
return;
293+
}
294+
295+
if (!hasHistory) {
277296
if (configManager.isTransferTimeoutProtectionEnabled()) {
278297
String safeServer = getSafeServer(uuid);
279298
logDebug("玩家 {} 未匹配任何有效规则,使用安全服务器: {}", player.getUsername(), safeServer);
280299
lastRoutes.put(uuid, safeServer);
281300
} else {
282-
// 如果没有规则匹配,不自动分配线路(由玩家手动选择)
283301
logDebug("玩家 {} 未匹配任何规则,不自动分配线路", player.getUsername());
284302
}
285-
}).delay(1, TimeUnit.SECONDS).schedule();
303+
}
286304
}
287305

288306
/**
@@ -462,7 +480,7 @@ public CompletableFuture<Boolean> updateOfflineRoute(UUID targetUuid, String rou
462480
String displayName = targetDisplayName != null ? targetDisplayName : targetUuid.toString();
463481
String operatorName = operatorDisplayName != null ? operatorDisplayName : "未知操作源";
464482

465-
logger.info("管理员 {} 将玩家 {} ({}) 的线路记录更新为 {}", operatorName, displayName, targetUuid, routeName);
483+
logDebug("管理员 {} 将玩家 {} ({}) 的线路记录更新为 {}", operatorName, displayName, targetUuid, routeName);
466484

467485
return CompletableFuture.supplyAsync(() -> databaseManager.saveRoute(targetUuid, routeName, targetDisplayName), databaseExecutor)
468486
.thenApply(saved -> {
@@ -936,7 +954,7 @@ private void sendRouteRecommendations(Player player, IPInfo ipInfo, String curre
936954
/**
937955
* 检测IP信息
938956
*/
939-
private void detectIPInfo(Player player) {
957+
private void detectIPInfo(Player player, boolean hasExistingRoute) {
940958
UUID uuid = player.getUniqueId();
941959

942960
try {
@@ -979,6 +997,8 @@ private void detectIPInfo(Player player) {
979997

980998
logDebug("IP地理位置 {} → {} - {} [{}]",
981999
player.getUsername(), location.toString(), info.isp, ip);
1000+
1001+
applyRulesForPlayer(player, hasExistingRoute);
9821002

9831003
} catch (Exception e) {
9841004
logger.error("IP检测失败 {}: {}", player.getUsername(), e.getMessage());

0 commit comments

Comments
 (0)