From 3e74b5cc43ae57f1da8cb47854791aacaa73014c Mon Sep 17 00:00:00 2001 From: zhouwei <849588297@qq.com> Date: Thu, 26 Feb 2026 12:03:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/robot/mj/EXGameController.java | 93 ++++++++++++++++--- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/robots/majiang/robot_mj_cs/src/main/java/robot/mj/EXGameController.java b/robots/majiang/robot_mj_cs/src/main/java/robot/mj/EXGameController.java index 4b5e6af..3db100d 100644 --- a/robots/majiang/robot_mj_cs/src/main/java/robot/mj/EXGameController.java +++ b/robots/majiang/robot_mj_cs/src/main/java/robot/mj/EXGameController.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; /** @@ -225,14 +226,31 @@ public class EXGameController extends GameController { String roomId = params.getString("roomid"); int groupId = params.getInt("groupid"); - //防止玩家操作同一房间 导致其他机器人加入 - List robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId)); - if (!robotUsers.isEmpty()) { - synchronized (robotUsers) { - RobotUser robotUser = robotUsers.get(0); - if (robotId != Integer.parseInt(robotUser.getRobotId())) { - System.err.println("房间{"+ roomId +"}中已有机器人{"+robotUser.getRobotId()+"},当前机器人{"+robotId+"}不执行加入逻辑"); - return; + //检查Redis中该房间是否真的包含当前机器人 + if (!checkRobotInRoomRedis(roomId, String.valueOf(robotId))) { + //Redis中不存在该机器人 清理本地可能的错误映射 + List robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId)); + if (!robotUsers.isEmpty()) { + synchronized (robotUsers) { + RobotUser robotUser = robotUsers.get(0); + System.err.println("房间{"+ roomId +"}中Redis未找到机器人{"+robotId+"},但本地映射存在{"+robotUser.getRobotId()+"},清理本地映射"); + robotRoomMapping.remove(robotUser.getConnecId()); + robotRoomMapping.remove(robotUser.getRobotId()); + } + } + } else { + //Redis中存在该机器人 检查是否是不同机器人的冲突 + List robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId)); + if (!robotUsers.isEmpty()) { + synchronized (robotUsers) { + RobotUser robotUser = robotUsers.get(0); + int existingRobotId = Integer.parseInt(robotUser.getRobotId()); + + if (robotId != existingRobotId) { + //不同机器人的冲突 + System.err.println("房间{"+ roomId +"}中Redis已存在机器人{"+existingRobotId+"},当前机器人{"+robotId+"}不执行加入逻辑"); + return; + } } } } @@ -287,7 +305,7 @@ public class EXGameController extends GameController { System.err.println("重启后已进入房间准备成功: " + "room:" + robotUser.getCurrentRoomId() + "robot:" + robotUser.getRobotId()); } catch (Exception e) { - throw new RuntimeException(e); + log.error("重启服务断线重连时发生错误", e); } finally { jedis0.close(); jedis2.close(); @@ -325,15 +343,33 @@ public class EXGameController extends GameController { robotUser.setClient(client); robotUser.setConnecId(connecId); } - robotRoomMapping.put(robotUser.getConnecId(), robotUser); + + //先不放入映射 等确认加入成功后再放入 + //robotRoomMapping.put(robotUser.getConnecId(), robotUser); robotRoomMapping.remove(robotUser.getRobotId()); Thread.sleep(2000); params.putString("session", "{user}:" + robotId + "," + robotSession); //发送加入房间请求到game_mj_cs client.send(Config.JOIN_ROOM_CS, params, response -> { + //成功响应后才建立映射关系 + robotRoomMapping.put(robotUser.getConnecId(), robotUser); robotConnectionManager.reconnectToGameServer(response, robotUser, client); }); + + //添加超时检查机制 + CompletableFuture.runAsync(() -> { + try { + Thread.sleep(10000); + //10秒后还没有建立映射关系 加入可能失败 + if (robotRoomMapping.get(robotUser.getConnecId()) == null) { + System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时,清理临时状态"); + robotConnectionManager.disconnectFromGameServer(connecId); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); System.err.println("已进入房间成功: " + robotUser.getConnecId()); Thread.sleep(1000); if (client.isConnected()) { @@ -348,7 +384,7 @@ public class EXGameController extends GameController { robotUser.setIntoRoomTime(robotConnectionManager.getTime()); System.err.println("已进入房间准备成功: " + robotUser.getConnecId()); } catch (Exception e) { - throw new RuntimeException(e); + log.error("加入房间时发生错误", e); } finally { jedis0.close(); jedis2.close(); @@ -394,6 +430,41 @@ public class EXGameController extends GameController { public static void removeRobotRoomInfo(String robotId) { robotRoomMapping.remove(robotId); } + + /** + * 检查Redis中房间是否包含指定机器人 + * @param roomId 房间ID + * @param robotId 机器人ID + * @return 是否包含该机器人 + */ + private boolean checkRobotInRoomRedis(String roomId, String robotId) { + Jedis jedis = Redis.use().getJedis(); + try { + //查询该房间的玩家信息 + String playersStr = jedis.hget("room:" + roomId, "players"); + if (playersStr == null || playersStr.equals("[]")) { + return false; + } + + String players = playersStr.substring(1, playersStr.length() - 1); + String[] playerIds = players.split(","); + + //检查是否包含该机器人 + int targetRobotId = Integer.parseInt(robotId); + for (String playerIdStr : playerIds) { + int playerId = Integer.parseInt(playerIdStr.trim()); + if (playerId == targetRobotId) { + return true; + } + } + return false; + } catch (Exception e) { + log.error("检查Redis房间玩家信息时发生错误,roomId: {}, robotId: {}", roomId, robotId, e); + return false; + } finally { + jedis.close(); + } + } /** * 根据机器人ID和连接ID获取长沙麻将游戏服务器连接