parent
accdf5e4d6
commit
84bb216bb9
|
|
@ -56,6 +56,9 @@ public class RobotManager {
|
|||
//跟踪已经恢复leftover_robot的机器人
|
||||
private final Set<Integer> leftoverRobotRecovered = ConcurrentHashMap.newKeySet();
|
||||
|
||||
//房间级别的锁,用于细粒度的同步控制
|
||||
private final Map<String, Object> roomLocks = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public RobotManager() {
|
||||
this.robotDisconnect = new RobotDisconnect(this);
|
||||
|
|
@ -164,9 +167,6 @@ public class RobotManager {
|
|||
gRobotMap.put("pid", String.valueOf(gameId));
|
||||
jedis2.hmset("{grobot}:" + robot.getRobotId(), gRobotMap);
|
||||
|
||||
//将登录后的机器人添加到已连接列表中 等待连接服务器
|
||||
connectedRobots.put(robot.getRobotId(), robot);
|
||||
|
||||
//更新数据库状态为已使用
|
||||
String sql = String.format("UPDATE `account` SET start = %d WHERE id = %d", 1, robot.getRobotId());
|
||||
DataBase.use().executeUpdate(sql);
|
||||
|
|
@ -175,6 +175,8 @@ public class RobotManager {
|
|||
//连接对应游戏服务器
|
||||
RobotManagerInterface handler = getGameHandler(gameId);
|
||||
handler.connectRobot(robot);
|
||||
//将登录后的机器人添加到已连接列表中 等待连接服务器
|
||||
connectedRobots.put(robot.getRobotId(), robot);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("机器人登录时发生错误", e);
|
||||
|
|
@ -253,7 +255,7 @@ public class RobotManager {
|
|||
/**
|
||||
* 断开多余的机器人连接
|
||||
*/
|
||||
public void disconnectExcessRobots(int wanfaId, int requiredCount) {
|
||||
public void disconnectExcessRobots(int wanfaId) {
|
||||
List<RobotInfo> allWanfaRobots = new ArrayList<>();
|
||||
for (RobotInfo robot : connectedRobots.values()) {
|
||||
if (robot.getWanfaId() == wanfaId) {
|
||||
|
|
@ -261,38 +263,23 @@ public class RobotManager {
|
|||
}
|
||||
}
|
||||
|
||||
//该玩法已连接的机器人
|
||||
int currentlyConnected = 0;
|
||||
for (RobotInfo robot : allWanfaRobots) {
|
||||
if (robot.isConnected()) {
|
||||
currentlyConnected++;
|
||||
}
|
||||
}
|
||||
|
||||
//需要断开的机器人
|
||||
int toDisconnect = Math.max(0, currentlyConnected - requiredCount);
|
||||
|
||||
if (toDisconnect > 0) {
|
||||
//断开该玩法下未使用的机器人
|
||||
int disconnectedCount = 0;
|
||||
for (int i = 0; i < allWanfaRobots.size() && disconnectedCount < toDisconnect; i++) {
|
||||
RobotInfo robot = allWanfaRobots.get(i);
|
||||
//不在使用断开连接
|
||||
if (!robot.isUsing() && robot.isConnected()) {
|
||||
for (RobotInfo robot : allWanfaRobots) {
|
||||
synchronized(robot) {
|
||||
if (!robot.isUsing() && robot.isConnected()) {
|
||||
RobotManagerInterface handler = getGameHandler(robot.getWanfaId());
|
||||
if (handler != null) {
|
||||
handler.disconnectRobot(robot);
|
||||
log.debug("断开机器人 {} TCP连接,玩法ID: {}", robot.getRobotId(), wanfaId);
|
||||
log.debug("断开未使用机器人 {} TCP连接,玩法ID: {}", robot.getRobotId(), wanfaId);
|
||||
}
|
||||
disconnectedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disconnectedCount > 0) {
|
||||
log.debug("玩法 {} 成功断开 {} 个机器人的TCP连接,目标连接数: {}", wanfaId, disconnectedCount, requiredCount);
|
||||
}
|
||||
log.debug("玩法 {} 成功断开 {} 个未使用机器人的TCP连接", wanfaId, disconnectedCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -307,36 +294,46 @@ public class RobotManager {
|
|||
}
|
||||
}
|
||||
|
||||
//该玩法已连接的机器人
|
||||
int currentConnected = 0;
|
||||
//空闲机器人
|
||||
int availableCount = 0;
|
||||
for (RobotInfo robot : allWanfaRobots) {
|
||||
if (robot.isConnected()) {
|
||||
currentConnected++;
|
||||
if (robot.isConnected() && !robot.isUsing()) {
|
||||
availableCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//当前连接数小于所需数量 则连接更多机器人
|
||||
if (currentConnected < requiredCount) {
|
||||
int reconnectedCount = 0;
|
||||
//可用机器人数量少于需求 连接更多机器人
|
||||
if (availableCount < requiredCount) {
|
||||
int needToConnect = requiredCount - availableCount;
|
||||
int connectedCount = 0;
|
||||
|
||||
for (RobotInfo robot : allWanfaRobots) {
|
||||
if (!robot.isConnected() && !robot.isUsing() && reconnectedCount < (requiredCount - currentConnected)) {
|
||||
if (connectedCount >= needToConnect) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!robot.isConnected() && !robot.isUsing()) {
|
||||
RobotManagerInterface handler = getGameHandler(robot.getWanfaId());
|
||||
if (handler != null) {
|
||||
if (shouldConnectRobot(robot)) {
|
||||
synchronized(robot) {
|
||||
if (!robot.isConnected() && !robot.isUsing()) {
|
||||
handler.connectRobot(robot);
|
||||
log.debug("重新连接玩法 {} 的机器人: {}", wanfaId, robot.getRobotId());
|
||||
log.debug("连接玩法 {} 的空闲机器人: {}", wanfaId, robot.getRobotId());
|
||||
connectedCount++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("玩法 {} 的leftover_robot为0,跳过连接机器人: {}", wanfaId, robot.getRobotId());
|
||||
}
|
||||
reconnectedCount++;
|
||||
log.debug("玩法 {} 当前不允许连接机器人: {}", wanfaId, robot.getRobotId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (connectedCount > 0) {
|
||||
log.debug("玩法 {} 新连接了 {} 个机器人以满足需求", wanfaId, connectedCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -386,7 +383,7 @@ public class RobotManager {
|
|||
//获取指定玩法的所有可用机器人
|
||||
List<RobotInfo> availableRobots = new ArrayList<>();
|
||||
for (RobotInfo robot : connectedRobots.values()) {
|
||||
if (robot.getWanfaId() == wanfaId && robot.isOnline() && robot.isConnected() && !robot.isUsing()) {
|
||||
if (robot.getWanfaId() == wanfaId && robot.isOnline() && !robot.isUsing()) {
|
||||
availableRobots.add(robot);
|
||||
}
|
||||
}
|
||||
|
|
@ -399,17 +396,20 @@ public class RobotManager {
|
|||
|
||||
RobotInfo selectedRobot = availableRobots.get(currentIndex);
|
||||
|
||||
synchronized (selectedRobot) {
|
||||
if (!selectedRobot.isUsing()) {
|
||||
selectedRobot.setLastActiveTime(System.currentTimeMillis());
|
||||
|
||||
selectedRobot.setUsing(true);
|
||||
int nextIndex = (currentIndex + 1) % availableRobots.size();
|
||||
wanfaRobotIndex.put(wanfaId, nextIndex);
|
||||
return selectedRobot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//如果没有连接的可用机器人,检查是否有未连接的机器人并尝试连接
|
||||
List<RobotInfo> allWanfaRobots = new ArrayList<>();
|
||||
for (RobotInfo robot : connectedRobots.values()) {
|
||||
if (robot.getWanfaId() == wanfaId && robot.isOnline() && robot.isConnected()) {
|
||||
if (robot.getWanfaId() == wanfaId && robot.isOnline()) {
|
||||
allWanfaRobots.add(robot);
|
||||
}
|
||||
}
|
||||
|
|
@ -422,13 +422,27 @@ public class RobotManager {
|
|||
|
||||
RobotInfo selectedRobot = allWanfaRobots.get(currentIndex);
|
||||
|
||||
selectedRobot.setLastActiveTime(System.currentTimeMillis());
|
||||
//机器人未连接 尝试重新连接
|
||||
if (!selectedRobot.isConnected()) {
|
||||
selectedRobot.setUsing(false);
|
||||
RobotManagerInterface handler = getGameHandler(selectedRobot.getWanfaId());
|
||||
if (handler != null) {
|
||||
handler.connectRobot(selectedRobot);
|
||||
}
|
||||
}
|
||||
|
||||
selectedRobot.setUsing(true);
|
||||
if (!selectedRobot.isUsing()) {
|
||||
//使用同步块确保原子操作
|
||||
synchronized (selectedRobot) {
|
||||
if (!selectedRobot.isUsing()) {
|
||||
selectedRobot.setLastActiveTime(System.currentTimeMillis());
|
||||
int nextIndex = (currentIndex + 1) % allWanfaRobots.size();
|
||||
wanfaRobotIndex.put(wanfaId, nextIndex);
|
||||
return selectedRobot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
@ -538,4 +552,11 @@ public class RobotManager {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取房间级别的锁
|
||||
*/
|
||||
public Object getRoomLock(String roomId) {
|
||||
return roomLocks.computeIfAbsent(roomId, k -> new Object());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.group.robot;
|
||||
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.group.robot.info.RoomInfo;
|
||||
|
||||
/**
|
||||
* 机器人处理器接口 - 只负责连接管理和协议转发
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ public class MaJiangRobotHandler implements RobotManagerInterface {
|
|||
try {
|
||||
//连接处理器进行连接
|
||||
robotConnectionHandler.connectRobot(robot);
|
||||
|
||||
//设置机器人连接状态
|
||||
robot.setConnected(true);
|
||||
}catch (Exception e) {
|
||||
log.error("麻将机器人 {} 连接游戏服务器时发生异常", robot.getRobotId(), e);
|
||||
robot.setConnected(false);
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ package com.group.robot.handler;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
|
@ -35,58 +34,15 @@ public class RobotConnectionHandler {
|
|||
//机器人ID到客户端连接的映射
|
||||
private final Map<Integer, TaurusClient> robotClients = new ConcurrentHashMap<>();
|
||||
|
||||
//机器人ID到账户信息的映射
|
||||
private final Map<Integer, RobotAccountInfo> robotAccounts = new ConcurrentHashMap<>();
|
||||
|
||||
//机器人ID到连接ID的映射,用于标识每个机器人连接的唯一性
|
||||
//机器人ID到连接ID的映射 用于标识每个机器人连接的唯一性
|
||||
private final Map<Integer, String> robotConnectionIds = new ConcurrentHashMap<>();
|
||||
|
||||
//机器人连接锁,防止重复连接
|
||||
private final Map<Integer, Object> robotConnectionLocks = new ConcurrentHashMap<>();
|
||||
|
||||
//机器人管理器引用
|
||||
private final RobotManager robotManager;
|
||||
|
||||
//心跳和重连
|
||||
private final Map<Integer, ScheduledFuture<?>> heartbeatTasks = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, String> robotServerAddresses = new ConcurrentHashMap<>();
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
|
||||
|
||||
/**
|
||||
* 机器人账户信息
|
||||
*/
|
||||
public static class RobotAccountInfo {
|
||||
private int robotId;
|
||||
private String account;
|
||||
private String password;
|
||||
private String session;
|
||||
private String token;
|
||||
private int groupId;
|
||||
private String roomId;
|
||||
private int gameId;
|
||||
|
||||
public RobotAccountInfo(int robotId, String account, String password, int groupId) {
|
||||
this.robotId = robotId;
|
||||
this.account = account;
|
||||
this.password = password;
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public int getRobotId() { return robotId; }
|
||||
public void setRobotId(int robotId) { this.robotId = robotId; }
|
||||
public String getAccount() { return account; }
|
||||
public void setAccount(String account) { this.account = account; }
|
||||
public String getPassword() { return password; }
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
public String getSession() { return session; }
|
||||
public void setSession(String session) { this.session = session; }
|
||||
public String getToken() { return token; }
|
||||
public void setToken(String token) { this.token = token; }
|
||||
public int getGroupId() { return groupId; }
|
||||
public void setGroupId(int groupId) { this.groupId = groupId; }
|
||||
public String getRoomId() { return roomId; }
|
||||
public void setRoomId(String roomId) { this.roomId = roomId; }
|
||||
public int getGameId() { return gameId; }
|
||||
public void setGameId(int gameId) { this.gameId = gameId; }
|
||||
}
|
||||
|
||||
private RobotConnectionHandler() {
|
||||
this.robotManager = RobotManager.getRobotManager();
|
||||
}
|
||||
|
|
@ -111,6 +67,17 @@ public class RobotConnectionHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
//机器人锁 防止重复连接
|
||||
Object lock = robotConnectionLocks.computeIfAbsent(robot.getRobotId(), k -> new Object());
|
||||
synchronized (lock) {
|
||||
//再次检查是否已经存在有效连接
|
||||
TaurusClient existingClient = robotClients.get(robot.getRobotId());
|
||||
if (existingClient != null && existingClient.isConnected()) {
|
||||
log.debug("机器人 {} 已存在有效连接,跳过重复连接", robot.getRobotId());
|
||||
robot.setConnected(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//异步执行连接逻辑
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
|
|
@ -125,6 +92,12 @@ public class RobotConnectionHandler {
|
|||
TaurusClient client = new TaurusClient(serverAddress, "game", TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.connect();
|
||||
|
||||
//连接成功后发送初始化协议
|
||||
sendInitializationProtocol(client, robot);
|
||||
|
||||
//设置事件监听器
|
||||
setupInitializationEventListeners(client, robot);
|
||||
|
||||
//生成唯一的connecId
|
||||
String connecId = generateConnectionId(robot.getRobotId());
|
||||
|
||||
|
|
@ -136,29 +109,27 @@ public class RobotConnectionHandler {
|
|||
|
||||
//保存客户端连接
|
||||
robotClients.put(robot.getRobotId(), client);
|
||||
robotServerAddresses.put(robot.getRobotId(), serverAddress);
|
||||
//保存connecId
|
||||
robotConnectionIds.put(robot.getRobotId(), connecId);
|
||||
|
||||
//设置事件监听器
|
||||
setupInitializationEventListeners(client, robot);
|
||||
|
||||
//连接成功后发送初始化协议
|
||||
sendInitializationProtocol(client, robot);
|
||||
|
||||
//设置机器人连接状态
|
||||
robot.setConnected(true);
|
||||
log.info("机器人 {} 成功连接到游戏服务器, ConnectionId: {}", robot.getRobotId(), connecId);
|
||||
System.out.println("connectRobot机器人尝试连接游戏服务器, client状态 :" + client.isConnected() + "机器人状态 :" + robot.isConnected());
|
||||
|
||||
//启动心跳
|
||||
startHeartTask(robot.getRobotId(), client, robot.getWanfaId());
|
||||
} catch (Exception e) {
|
||||
log.error("连接机器人到游戏服务器时发生异常: " + robot.getRobotId(), e);
|
||||
System.out.println("连接机器人到游戏服务器时发生异常: " + robot.getRobotId());
|
||||
robotClients.remove(robot.getRobotId());
|
||||
robotConnectionIds.remove(robot.getRobotId());
|
||||
robot.setConnected(false);
|
||||
disconnectRobot(robot.getRobotId());
|
||||
} finally {
|
||||
if (!robotClients.containsKey(robot.getRobotId())) {
|
||||
robotConnectionLocks.remove(robot.getRobotId());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一的连接ID
|
||||
|
|
@ -210,77 +181,6 @@ public class RobotConnectionHandler {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动心跳任务
|
||||
*/
|
||||
private void startHeartTask(int robotId, TaurusClient client, int wanfaId) {
|
||||
stopHeartTask(robotId);
|
||||
|
||||
ScheduledFuture<?> heartbeatTask = scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
if (client != null && client.isConnected()) {
|
||||
//发送心跳包
|
||||
ITObject heartbeatParam = new TObject();
|
||||
heartbeatParam.putString("type", "heartbeat");
|
||||
heartbeatParam.putInt("robot_id", robotId);
|
||||
heartbeatParam.putInt("wanfa_id", wanfaId);
|
||||
heartbeatParam.putString("connecId", robotConnectionIds.get(robotId));
|
||||
heartbeatParam.putLong("timestamp", System.currentTimeMillis());
|
||||
|
||||
client.send("ping", heartbeatParam, response -> {
|
||||
if (response != null) {
|
||||
log.debug("机器人 {} 心跳响应成功", robotId);
|
||||
} else {
|
||||
log.warn("机器人 {} 心跳响应失败", robotId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.warn("机器人 {} 连接已断开,无法发送心跳", robotId);
|
||||
//连接断开 尝试重连
|
||||
RobotInfo robot = robotManager.getConnectedRobot(robotId);
|
||||
if (robot != null) {
|
||||
scheduleReconnection(robot);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送心跳时发生异常,机器人: " + robotId, e);
|
||||
}
|
||||
}, 30, 30, TimeUnit.SECONDS);//30秒发送一次心跳
|
||||
|
||||
heartbeatTasks.put(robotId, heartbeatTask);
|
||||
log.info("已启动机器人 {} 的心跳任务", robotId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止心跳任务
|
||||
*/
|
||||
private void stopHeartTask(int robotId) {
|
||||
ScheduledFuture<?> task = heartbeatTasks.remove(robotId);
|
||||
if (task != null && !task.isCancelled()) {
|
||||
robotConnectionIds.remove(robotId);
|
||||
task.cancel(false);
|
||||
log.info("已停止机器人 {} 的心跳任务", robotId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划重连任务
|
||||
*/
|
||||
private void scheduleReconnection(RobotInfo robot) {
|
||||
scheduler.schedule(() -> {
|
||||
try {
|
||||
log.info("开始重连机器人: {}", robot.getRobotId());
|
||||
//清理可能存在的旧连接
|
||||
robot.setConnected(false);
|
||||
disconnectRobot(robot.getRobotId());
|
||||
//重新连接
|
||||
connectRobot(robot);
|
||||
} catch (Exception e) {
|
||||
log.error("重连机器人失败: {}", robot.getRobotId(), e);
|
||||
}
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据游戏ID获取服务器地址
|
||||
*/
|
||||
|
|
@ -295,7 +195,7 @@ public class RobotConnectionHandler {
|
|||
return "8.138.242.190:6841";
|
||||
default:
|
||||
log.warn("未知的玩法ID: {}, 使用默认服务器地址", wanfaId);
|
||||
return "192.168.0.32:6311"; //默认地址
|
||||
return "127.0.0.1:6311"; //默认地址
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -305,21 +205,25 @@ public class RobotConnectionHandler {
|
|||
public void disconnectRobot(int robotId) {
|
||||
try {
|
||||
log.info("清理机器人 {} 的连接资源", robotId);
|
||||
stopHeartTask(robotId);
|
||||
Object lock = robotConnectionLocks.computeIfAbsent(robotId, k -> new Object());
|
||||
synchronized (lock) {
|
||||
//移除机器人TCP客户端连接
|
||||
TaurusClient client = robotClients.remove(robotId);
|
||||
if (client != null) {
|
||||
client.killConnection();
|
||||
log.debug("已清理机器人 {} 的客户端连接", robotId);
|
||||
}
|
||||
//移除机器人信息
|
||||
RobotAccountInfo robotAccountInfo = robotAccounts.remove(robotId);
|
||||
if (robotAccountInfo != null && robotManager != null) {
|
||||
//调用RobotManager的统一断开服务
|
||||
robotManager.safeDisconnectRobot(robotId,
|
||||
robotAccountInfo.getGroupId(),
|
||||
robotAccountInfo.getGameId(),
|
||||
robotAccountInfo.getRoomId());
|
||||
//移除连接ID
|
||||
robotConnectionIds.remove(robotId);
|
||||
|
||||
//清理锁对象
|
||||
robotConnectionLocks.remove(robotId);
|
||||
}
|
||||
|
||||
//从RobotManager中获取机器人信息并断开连接
|
||||
RobotInfo robot = robotManager.getConnectedRobot(robotId);
|
||||
if (robot != null) {
|
||||
robotManager.safeDisconnectRobot(robotId, robot.getGroupId(), robot.getWanfaId(), robot.getRoomId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("断开机器人连接时发生异常: " + robotId, e);
|
||||
|
|
@ -342,7 +246,8 @@ public class RobotConnectionHandler {
|
|||
//发送离开房间协议
|
||||
ITObject param = new TObject();
|
||||
param.putString("robotId", String.valueOf(robot.getRobotId()));
|
||||
param.putString("connecId", robotConnectionIds.get(robot.getRobotId())); // 添加connecId
|
||||
param.putString("connecId", robotConnectionIds.get(robot.getRobotId()));
|
||||
System.out.println("readyTimeRobotExit 2005 client: "+ robotConnectionIds.get(robot.getRobotId()));
|
||||
client.send("2005", param, response -> {
|
||||
log.debug("机器人 {} 发送离开房间请求", robot.getRobotId());
|
||||
});
|
||||
|
|
@ -407,20 +312,24 @@ public class RobotConnectionHandler {
|
|||
/**
|
||||
* 发送加入房间消息给指定机器人
|
||||
*/
|
||||
public void sendJoinRoomMessage(RobotInfo robot) {
|
||||
public void sendJoinRoomMessageAsync(RobotInfo robot, Consumer<Boolean> callback) {
|
||||
TaurusClient client = robotClients.get(robot.getRobotId());
|
||||
|
||||
if (client == null) {
|
||||
log.warn("机器人 {} 没有有效的TCP连接,无法发送加入房间消息", robot.getRobotId());
|
||||
callback.accept(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ITObject readyParam = new TObject();
|
||||
readyParam.putInt("groupId", robot.getGroupId());
|
||||
readyParam.putString("roomId", robot.getRoomId());
|
||||
|
||||
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
readyParam.putString("robotId", String.valueOf(robot.getRobotId()));
|
||||
readyParam.putString("connecId", robotConnectionIds.get(robot.getRobotId()));
|
||||
System.out.println("sendJoinRoomMessageAsync 2002 client: "+ robotConnectionIds.get(robot.getRobotId()));
|
||||
client.send("2002", readyParam, response -> {
|
||||
log.debug("机器人 {} 发送加入房间请求响应: {}", robot.getRobotId(), response);
|
||||
boolean success = response != null && response.returnCode == 0;
|
||||
callback.accept(success);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -486,13 +395,95 @@ public class RobotConnectionHandler {
|
|||
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
readyParam.putString("robotId", String.valueOf(robot.getRobotId()));
|
||||
readyParam.putString("connecId", robotConnectionIds.get(robot.getRobotId()));
|
||||
|
||||
System.out.println("sendReadyMessage 2003 client: "+ robotConnectionIds.get(robot.getRobotId()));
|
||||
client.send("2003", readyParam, response -> {
|
||||
boolean success = response != null && response.returnCode == 0;
|
||||
callback.accept(success);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步发送加入房间消息给指定机器人,返回CompletableFuture
|
||||
*/
|
||||
public CompletableFuture<Boolean> sendJoinRoomMessageAsyncCompletable(RobotInfo robot) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
|
||||
TaurusClient client = robotClients.get(robot.getRobotId());
|
||||
if (client == null) {
|
||||
future.complete(false);
|
||||
return future;
|
||||
}
|
||||
|
||||
ITObject readyParam = new TObject();
|
||||
readyParam.putInt("groupId", robot.getGroupId());
|
||||
readyParam.putString("roomId", robot.getRoomId());
|
||||
|
||||
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
readyParam.putString("robotId", String.valueOf(robot.getRobotId()));
|
||||
readyParam.putString("connecId", robotConnectionIds.get(robot.getRobotId()));
|
||||
System.out.println("sendJoinRoomMessageAsync 2002 client: " + robotConnectionIds.get(robot.getRobotId()));
|
||||
|
||||
// 设置超时机制
|
||||
Timer timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!future.isDone()) {
|
||||
future.completeExceptionally(new RuntimeException("Join room timeout"));
|
||||
}
|
||||
}
|
||||
}, 10000); // 10秒超时
|
||||
|
||||
client.send("2002", readyParam, response -> {
|
||||
boolean success = response != null && response.returnCode == 0;
|
||||
if (!future.isDone()) {
|
||||
future.complete(success);
|
||||
}
|
||||
timer.cancel();
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步发送准备消息给指定机器人,返回CompletableFuture
|
||||
*/
|
||||
public CompletableFuture<Boolean> sendReadyMessageAsyncCompletable(RobotInfo robot) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
|
||||
TaurusClient client = robotClients.get(robot.getRobotId());
|
||||
if (client == null) {
|
||||
future.complete(false);
|
||||
return future;
|
||||
}
|
||||
|
||||
ITObject readyParam = new TObject();
|
||||
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
readyParam.putString("robotId", String.valueOf(robot.getRobotId()));
|
||||
readyParam.putString("connecId", robotConnectionIds.get(robot.getRobotId()));
|
||||
|
||||
// 设置超时机制
|
||||
Timer timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!future.isDone()) {
|
||||
future.completeExceptionally(new RuntimeException("Ready message timeout"));
|
||||
}
|
||||
}
|
||||
}, 10000); // 10秒超时
|
||||
|
||||
client.send("2003", readyParam, response -> {
|
||||
boolean success = response != null && response.returnCode == 0;
|
||||
if (!future.isDone()) {
|
||||
future.complete(success);
|
||||
}
|
||||
timer.cancel();
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调接口
|
||||
*/
|
||||
|
|
@ -511,7 +502,8 @@ public class RobotConnectionHandler {
|
|||
*/
|
||||
public void sendCreateRoom(RobotInfo robot, int groupId, int wanfaId) {
|
||||
TaurusClient client = robotClients.get(robot.getRobotId());
|
||||
if (client == null ) {
|
||||
//todo !client.isConnected()
|
||||
if (client == null || !client.isConnected()) {
|
||||
connectRobot(robot);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import com.group.robot.RobotManager;
|
||||
import com.group.robot.handler.RobotConnectionHandler;
|
||||
|
|
@ -79,7 +76,7 @@ public class RoomWanfaMatcher {
|
|||
log.info("开始为群组 {} 玩法ID {} 启动房间轮询", groupId, wanfaId);
|
||||
|
||||
//10秒轮询一次
|
||||
scheduler.scheduleWithFixedDelay(this::pollRooms, 0, 10, TimeUnit.SECONDS);
|
||||
scheduler.scheduleWithFixedDelay(this::pollRooms, 0, 20, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,18 +160,23 @@ public class RoomWanfaMatcher {
|
|||
|
||||
//房间没人 加入房间
|
||||
if (playersStr.equals("[]")) {
|
||||
//房间是否正在被加入
|
||||
Object roomSpecificLock = robotManager.getRoomLock(roomId);
|
||||
synchronized (roomSpecificLock) {
|
||||
if (!processingRooms.contains(roomId)) {
|
||||
processingRooms.add(roomId);
|
||||
robotJoinRoom(robot, true);
|
||||
robotJoinRoomInternal(robot, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//房间有人 不是机器人则加入房间
|
||||
Integer robotInRoom = playerIsRobotRedis(playersStr);
|
||||
if (robotInRoom == null) {
|
||||
Object roomSpecificLock = robotManager.getRoomLock(roomId);
|
||||
synchronized (roomSpecificLock) {
|
||||
if (!processingRooms.contains(roomId)) {
|
||||
processingRooms.add(roomId);
|
||||
robotJoinRoom(robot, false);
|
||||
robotJoinRoomInternal(robot, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -188,70 +190,92 @@ public class RoomWanfaMatcher {
|
|||
}
|
||||
|
||||
/**
|
||||
* 机器人加入房间
|
||||
* 内部机器人加入房间方法,不包含同步逻辑
|
||||
* @param isRobot 是否是机器人创建房间
|
||||
* @param robot 机器人实例
|
||||
* */
|
||||
private void robotJoinRoom(RobotInfo robot, boolean isRobot) {
|
||||
synchronized (joinRoomLock) {
|
||||
RobotInfo robotInfo = robot;
|
||||
private void robotJoinRoomInternal(RobotInfo robot, boolean isRobot) {
|
||||
String roomId = robot != null ? robot.getRoomId() : null;
|
||||
RobotInfo robotInfo = robot;
|
||||
int groupId = robot.getGroupId();
|
||||
|
||||
try {
|
||||
if (robotInfo.getRobotId() == -1) {
|
||||
robotInfo = robotManager.getLoggedInRobotForWanfa(wanfaId);
|
||||
robotInfo.setGroupId(groupId);
|
||||
robotInfo.setRoomId(roomId);
|
||||
}
|
||||
|
||||
//加入房间
|
||||
try {
|
||||
GroupRoomBusiness.joinRoom(robotInfo.getGroupId(), robotInfo.getRoomId(), robotInfo.getSession(), null);
|
||||
Thread.sleep(5000);
|
||||
robotConnectionHandler.sendJoinRoomMessage(robotInfo);
|
||||
Thread.sleep(1000);
|
||||
}catch (Exception e) {
|
||||
log.error("加入房间失败", e);
|
||||
processingRooms.remove(roomId);
|
||||
System.out.println("robotJoinRoom机器人加入房间 机器人状态 :" + robot.isConnecting());
|
||||
if (robotInfo == null) {
|
||||
return;
|
||||
}
|
||||
robotInfo.setGroupId(groupId);
|
||||
robotInfo.setRoomId(roomId);
|
||||
|
||||
//准备
|
||||
//验证机器人连接状态
|
||||
if (robotInfo.isUsing()) {
|
||||
robotManager.releaseRobot(robotInfo.getRobotId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用CompletableFuture替代嵌套回调,提高可读性和可控性
|
||||
RobotInfo finalRobotInfo = robotInfo;
|
||||
robotConnectionHandler.sendReadyMessageAsync(robotInfo, readySuccess -> {
|
||||
|
||||
// 创建一个完整的加入房间流程
|
||||
CompletableFuture<Boolean> joinFuture = robotConnectionHandler.sendJoinRoomMessageAsyncCompletable(finalRobotInfo);
|
||||
|
||||
joinFuture.thenCompose(joinSuccess -> {
|
||||
if (joinSuccess) {
|
||||
System.out.println("robotJoinRoomInternal机器人加入了房间 机器人状态 :" + robot.isConnecting());
|
||||
// 准备阶段
|
||||
return robotConnectionHandler.sendReadyMessageAsyncCompletable(finalRobotInfo);
|
||||
} else {
|
||||
System.out.println("robotJoinRoomInternal机器人加入了房间 失败 :" + robot.isConnecting());
|
||||
// 加入失败,释放机器人
|
||||
robotManager.releaseRobot(finalRobotInfo.getRobotId());
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}).thenAccept(readySuccess -> {
|
||||
if (readySuccess) {
|
||||
System.out.println("robotJoinRoomInternal机器人准备 房间 机器人状态 :" + robot.isConnecting());
|
||||
roomToRobotMap.put(roomId, finalRobotInfo.getRobotId());
|
||||
updateRobotStatusRedis(finalRobotInfo);
|
||||
if (isRobot) {
|
||||
//6秒没有玩家加入 则退出房间
|
||||
robotConnectionHandler.readyTimeRobotExit(finalRobotInfo, joinRoomLock);
|
||||
robotConnectionHandler.readyTimeRobotExit(finalRobotInfo, robotManager.getRoomLock(roomId));
|
||||
}
|
||||
} else {
|
||||
System.out.println("机器人准备失败");
|
||||
}
|
||||
if (roomId != null) {
|
||||
processingRooms.remove(roomId);
|
||||
System.out.println("robotJoinRoomInternal机器人准备 房间 失败 :" + robot.isConnecting());
|
||||
// 准备失败时释放机器人
|
||||
robotManager.releaseRobot(finalRobotInfo.getRobotId());
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("机器人加入房间流程异常", throwable);
|
||||
robotManager.releaseRobot(finalRobotInfo.getRobotId());
|
||||
return null;
|
||||
});
|
||||
/*boolean readySuccess = robotConnectionHandler.sendReadyMessageSync(robotInfo);
|
||||
if (readySuccess) {
|
||||
//记录机器人和房间的关联
|
||||
roomToRobotMap.put(roomId, robotInfo.getRobotId());
|
||||
|
||||
updateRobotStatusRedis(robotInfo);
|
||||
|
||||
if (isRobot) {
|
||||
//6秒没有玩家加入 则退出房间
|
||||
robotConnectionHandler.readyTimeRobotExit(robotInfo, joinRoomLock);
|
||||
}
|
||||
} else {
|
||||
//robotConnectionHandler.disconnectRobot(robotInfo.getRobotId());
|
||||
}*/
|
||||
} catch (Exception e) {
|
||||
if (robotInfo != null) {
|
||||
//robotConnectionHandler.disconnectRobot(robotInfo.getRobotId());
|
||||
//释放机器人
|
||||
robotManager.releaseRobot(robotInfo.getRobotId());
|
||||
}
|
||||
} finally {
|
||||
// 从处理队列中移除房间 - 这个操作是必要的,无论是在哪种情况下
|
||||
processingRooms.remove(roomId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 机器人加入房间 - 保持原有的公共接口
|
||||
* @param isRobot 是否是机器人创建房间
|
||||
* @param robot 机器人实例
|
||||
* */
|
||||
private void robotJoinRoom(RobotInfo robot, boolean isRobot) {
|
||||
String roomId = robot != null ? robot.getRoomId() : null;
|
||||
// 使用房间级别的细粒度锁,而不是全局锁
|
||||
Object roomSpecificLock = robotManager.getRoomLock(roomId);
|
||||
|
||||
synchronized (roomSpecificLock) {
|
||||
robotJoinRoomInternal(robot, isRobot);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -321,15 +345,16 @@ public class RoomWanfaMatcher {
|
|||
private void manageRobotConnections(int currentLeftoverRobot) {
|
||||
if (lastLeftoverRobot != currentLeftoverRobot) {
|
||||
if (currentLeftoverRobot <= 0 && lastLeftoverRobot > 0) {
|
||||
//leftover_robot变为0 断开该玩法与robot_mj_cs的连接
|
||||
robotManager.disconnectExcessRobots(wanfaId, 0);
|
||||
//leftover_robot变为0 断开该玩法下未使用的机器人连接
|
||||
robotManager.disconnectExcessRobots(wanfaId);
|
||||
lastLeftoverRobot = 0;
|
||||
} else if (currentLeftoverRobot > 0 && lastLeftoverRobot <= 0) {
|
||||
//leftover_robot变为正数 重新连接机器人到robot_mj_cs
|
||||
//leftover_robot变为正数 检查是否有可用的空闲机器人 没有则连接新的
|
||||
robotManager.connectRequiredRobots(wanfaId, currentLeftoverRobot);
|
||||
}
|
||||
lastLeftoverRobot = currentLeftoverRobot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止轮询
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<gameSetting>
|
||||
<host>127.0.0.1</host>
|
||||
<intranet>127.0.0.1</intranet>
|
||||
<host>192.168.0.32</host>
|
||||
<intranet>192.168.0.32</intranet>
|
||||
<port>8701</port>
|
||||
<serverId>7701</serverId>
|
||||
<gameId>10</gameId>
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@
|
|||
</poolConfig>
|
||||
|
||||
<infos>
|
||||
<info name="group1_db0" host="8.148.219.235" password="cssq@2020" port="6379" database="0" timeout="5000"/>
|
||||
<info name="group1_db1" host="8.148.219.235" password="cssq@2020" port="6379" database="1" timeout="5000"/>
|
||||
<info name="group1_db2" host="8.148.219.235" password="cssq@2020" port="6379" database="2" timeout="5000"/>
|
||||
<info name="group1_db5" host="8.148.219.235" password="cssq@2020" port="6379" database="5" timeout="5000"/>
|
||||
<info name="group1_db8" host="8.148.219.235" password="cssq@2020" port="6379" database="8" timeout="5000"/>
|
||||
<info name="group1_db9" host="8.148.219.235" password="cssq@2020" port="6379" database="9" timeout="5000"/>
|
||||
<info name="group1_db10" host="8.148.219.235" password="cssq@2020" port="6379" database="10" timeout="5000"/>
|
||||
<info name="group1_db11" host="8.148.219.235" password="cssq@2020" port="6379" database="11" timeout="5000"/>
|
||||
<info name="tmp_group1_db9" host="8.148.219.235" password="654sads" port="6479" database="9" timeout="5000"/>
|
||||
<info name="group1_db0" host="8.134.76.43" password="cssq@2020" port="6379" database="0" timeout="5000"/>
|
||||
<info name="group1_db1" host="8.134.76.43" password="cssq@2020" port="6379" database="1" timeout="5000"/>
|
||||
<info name="group1_db2" host="8.134.76.43" password="cssq@2020" port="6379" database="2" timeout="5000"/>
|
||||
<info name="group1_db5" host="8.134.76.43" password="cssq@2020" port="6379" database="5" timeout="5000"/>
|
||||
<info name="group1_db8" host="8.134.76.43" password="cssq@2020" port="6379" database="8" timeout="5000"/>
|
||||
<info name="group1_db9" host="8.134.76.43" password="cssq@2020" port="6379" database="9" timeout="5000"/>
|
||||
<info name="group1_db10" host="8.134.76.43" password="cssq@2020" port="6379" database="10" timeout="5000"/>
|
||||
<info name="group1_db11" host="8.134.76.43" password="cssq@2020" port="6379" database="11" timeout="5000"/>
|
||||
<info name="tmp_group1_db9" host="8.134.76.43" password="654sads" port="6479" database="9" timeout="5000"/>
|
||||
</infos>
|
||||
<!--<infos>
|
||||
<info name="group1_db0" host="127.0.0.1" port="6379" database="0" timeout="5000"/>
|
||||
|
|
|
|||
|
|
@ -98,33 +98,36 @@ public class Config {
|
|||
|
||||
public static final String GAME_EVT_TING = "836";
|
||||
|
||||
// 初始化连接协议
|
||||
public static final String CREATE_ROOM_ROBOT = "create_room_for_robot";
|
||||
public static final String INIT_CONNECTION = "init_connection";
|
||||
|
||||
// 创建房间机器人协议
|
||||
public static final String CREATE_ROOM_ROBOT = "create_room_for_robot";
|
||||
|
||||
// 加入房间协议
|
||||
/**
|
||||
* 加入房间 - robot_mgr to robot_mj_cs 的内部协议号
|
||||
*/
|
||||
public static final String JOIN_ROOM = "2002";
|
||||
|
||||
// 加入房间CS协议
|
||||
public static final String JOIN_ROOM_CS = "1002";
|
||||
|
||||
// 游戏准备协议
|
||||
/**
|
||||
* 发送准备 - robot_mgr to robot_mj_cs 的内部协议号
|
||||
*/
|
||||
public static final String GAME_READY = "2003";
|
||||
|
||||
// 游戏准备CS协议
|
||||
/**
|
||||
* 退出房间 - robot_mgr to robot_mj_cs 的内部协议号
|
||||
*/
|
||||
public static final String EXIT_ROOM = "2005";
|
||||
|
||||
/**
|
||||
* 发送准备 - robot_mj_cs to game_mj_cs 的协议号
|
||||
*/
|
||||
public static final String GAME_READY_CS = "1003";
|
||||
|
||||
// 退出房间协议
|
||||
public static final String EXIT_ROOM = "2004";
|
||||
/**
|
||||
* 加入房间 - robot_mgr to game_mj_cs 的内部协议号
|
||||
*/
|
||||
public static final String JOIN_ROOM_CS = "1002";
|
||||
|
||||
// 退出房间CS协议
|
||||
public static final String EXIT_ROOM_CS = "1004";
|
||||
|
||||
// 其他可能的游戏相关协议
|
||||
public static final String GAME_CHAT = "1006";
|
||||
|
||||
// 心跳协议
|
||||
public static final String HEARTBEAT = "9000";
|
||||
/**
|
||||
* 退出房间 - robot_mgr to game_mj_cs 的内部协议号
|
||||
*/
|
||||
public static final String EXIT_ROOM_CS = "1005";
|
||||
}
|
||||
|
|
@ -5,18 +5,19 @@ import com.robot.GameInterceptor;
|
|||
import com.robot.MainServer;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.entity.TObject;
|
||||
import com.taurus.core.events.Event;
|
||||
import com.taurus.core.events.IEventListener;
|
||||
import com.taurus.core.routes.ActionKey;
|
||||
import com.taurus.core.util.ICallback;
|
||||
import com.taurus.core.util.StringUtil;
|
||||
import com.taurus.permanent.data.Session;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import robot.mj.handler.HuNanChangSha;
|
||||
import taurus.client.Message;
|
||||
import taurus.client.MessageResponse;
|
||||
import taurus.client.TaurusClient;
|
||||
import taurus.client.business.GroupRoomBusiness;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* 长沙麻将游戏控制器 - 处理游戏协议
|
||||
|
|
@ -113,40 +114,56 @@ public class EXGameController extends GameController {
|
|||
@ActionKey(value = Config.JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
|
||||
public void joinRoom(Session session, ITObject params, int gid) {
|
||||
try {
|
||||
System.out.println("收到加入房间请求,Session: {}, GID: {}, 参数: {}");
|
||||
|
||||
String connecId = params.getString("connecId");
|
||||
TaurusClient client = null;// getCsMjGameServerConnection(connecId);
|
||||
client = new TaurusClient("8.134.76.43" + ":" + "6311", "game", TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.connect();
|
||||
TaurusClient client = getCsMjGameServerConnection(connecId);
|
||||
System.out.println("接收来自robot_mgr的加入房间协议 connecId: = "+connecId);
|
||||
System.out.println("接收来自robot_mgr的加入房间协议 client: = "+client);
|
||||
if (client == null) {
|
||||
// 返回失败响应而不是直接返回
|
||||
ITObject errorResponse = TObject.newInstance();
|
||||
errorResponse.putString("status", "failed");
|
||||
errorResponse.putString("message", "无法获取游戏服务器连接");
|
||||
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
return;
|
||||
}
|
||||
|
||||
//设置session和token
|
||||
String sessionToken = params.getString("session");
|
||||
String robotSession = null;
|
||||
if (sessionToken != null && sessionToken.contains(",")) {
|
||||
String[] sessionParts = sessionToken.split(",");
|
||||
if (sessionParts.length >= 2) {
|
||||
String actualSessionFromParams = sessionParts[0];
|
||||
robotSession = sessionParts[0];
|
||||
String token = sessionParts[1];
|
||||
connectionManager.setSessionAndToken(actualSessionFromParams, token);
|
||||
connectionManager.setSessionAndToken(robotSession, token);
|
||||
}
|
||||
}
|
||||
|
||||
//发送加入房间请求
|
||||
Integer groupId = params.getInt("groupId");
|
||||
String roomId = params.getString("roomId");
|
||||
|
||||
// 在当前线程中同步执行阻塞操作
|
||||
GroupRoomBusiness.joinRoom(groupId, roomId, robotSession, null);
|
||||
|
||||
Thread.sleep(5000); // 等待100毫秒后再次检查
|
||||
|
||||
|
||||
// 发送加入房间请求到game_mj_cs
|
||||
client.send(Config.JOIN_ROOM_CS, params, response -> {
|
||||
System.out.println("csmj OnEvent " + response.returnCode);
|
||||
log.info("加入房间请求发送结果: returnCode={}", response.returnCode);
|
||||
});
|
||||
client.addEventListener(TaurusClient.NetClientEvent.OnEvent, new IEventListener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
System.out.println("csmj OnEvent 能监听:jefe " );
|
||||
}
|
||||
System.out.println("joinRoom: " + response);
|
||||
});
|
||||
|
||||
// 发送成功响应
|
||||
ITObject paramsReq = TObject.newInstance();
|
||||
paramsReq.putString("status", "success");
|
||||
MainServer.instance.sendResponse(gid, 0, paramsReq, session);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理加入房间请求时发生错误", e);
|
||||
ITObject errorResponse = TObject.newInstance();
|
||||
errorResponse.putString("status", "error");
|
||||
errorResponse.putString("message", "处理加入房间请求时发生错误: " + e.getMessage());
|
||||
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,20 +175,34 @@ public class EXGameController extends GameController {
|
|||
try {
|
||||
String connecId = params.getString("connecId");
|
||||
TaurusClient client = getCsMjGameServerConnection(connecId);
|
||||
System.out.println("session: " + session);
|
||||
System.out.println("client: " + client);
|
||||
System.out.println("接收来自robot_mgr的机器人准备协议 connecId: = "+connecId);
|
||||
System.out.println("接收来自robot_mgr的机器人准备协议 client: = "+client);
|
||||
if (client == null) {
|
||||
ITObject errorResponse = TObject.newInstance();
|
||||
errorResponse.putString("status", "failed");
|
||||
errorResponse.putString("message", "无法获取游戏服务器连接");
|
||||
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
return;
|
||||
}
|
||||
|
||||
params.del("connecId");
|
||||
client.send(Config.GAME_READY_CS, params, null);
|
||||
Thread.sleep(1000); // 等待100毫秒后再次检查
|
||||
// 发送准备请求到game_mj_cs
|
||||
client.send(Config.GAME_READY_CS, params, response -> {
|
||||
System.out.println("robotReadyRoom: " + response);
|
||||
});
|
||||
|
||||
// 发送成功响应
|
||||
ITObject paramsReq = TObject.newInstance();
|
||||
paramsReq.putString("status", "success");
|
||||
MainServer.instance.sendResponse(gid, 0, paramsReq, session);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理机器人准备请求时发生错误", e);
|
||||
ITObject errorResponse = TObject.newInstance();
|
||||
errorResponse.putString("status", "error");
|
||||
errorResponse.putString("message", "服务器内部错误: " + e.getMessage());
|
||||
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,18 +214,21 @@ public class EXGameController extends GameController {
|
|||
public void exitRoom(Session session, ITObject params, int gid) {
|
||||
try {
|
||||
String connecId = params.getString("connecId");
|
||||
TaurusClient client = getCsMjGameServerConnection(connecId);
|
||||
log.info("处理退出房间请求,connecId: {}", connecId);
|
||||
|
||||
TaurusClient client = getCsMjGameServerConnection(connecId);
|
||||
if (client == null) {
|
||||
log.error("无法获取到游戏服务器连接,connecId: {}", connecId);
|
||||
return;
|
||||
}
|
||||
|
||||
//发送退出房间请求
|
||||
client.send(Config.EXIT_ROOM_CS, params, response -> {
|
||||
log.info("退出房间请求发送结果: returnCode={} for connecId={}", response.returnCode, connecId);
|
||||
});
|
||||
|
||||
//断开与游戏服务器的连接
|
||||
//connectionManager.disconnectFromGameServer(connecId);
|
||||
connectionManager.disconnectFromGameServer(connecId);
|
||||
} catch (Exception e) {
|
||||
log.error("处理退出房间请求时发生错误", e);
|
||||
String connecId = params.getString("connecId");
|
||||
|
|
@ -204,21 +238,17 @@ public class EXGameController extends GameController {
|
|||
|
||||
/**
|
||||
* 根据机器人ID和连接ID获取长沙麻将游戏服务器连接
|
||||
* 基于robotId和connectionId的组合复用连接
|
||||
*/
|
||||
public static TaurusClient getCsMjGameServerConnection(String connecId) {
|
||||
TaurusClient taurusClient = connectionManager.getGameServerConnection(connecId);
|
||||
TaurusClient taurusClient = connectionManager.getGameClient(connecId);
|
||||
System.out.println("根据机器人ID和连接ID获取长沙麻将游戏服务器连接 client: = "+taurusClient);
|
||||
if (taurusClient != null) {
|
||||
log.debug("成功获取游戏服务器连接,connecId: {}", connecId);
|
||||
return taurusClient;
|
||||
}
|
||||
|
||||
boolean connected = connectionManager.connectToGameServer(connecId);
|
||||
if (connected) {
|
||||
taurusClient = connectionManager.getGameServerConnection(connecId);
|
||||
if (taurusClient != null) {
|
||||
taurusClient = connectionManager.connectToGameServer(connecId);
|
||||
return taurusClient;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,16 +28,6 @@ import robot.mj.handler.HuNanChangSha;
|
|||
public class EXMainServer extends MainServer{
|
||||
private static final Logger log = LoggerFactory.getLogger(EXMainServer.class);
|
||||
|
||||
//机器人连接管理器
|
||||
private static RobotConnectionManager robotConnectionManager;
|
||||
|
||||
//长沙麻将AI处理器
|
||||
private static HuNanChangSha huNanChangSha;
|
||||
|
||||
//心跳和重连
|
||||
private final Map<String, ScheduledFuture<?>> serverHeartbeatTasks = new ConcurrentHashMap<>();
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
|
@ -67,9 +57,6 @@ public class EXMainServer extends MainServer{
|
|||
* 初始化组件
|
||||
*/
|
||||
private void initializeComponents() {
|
||||
robotConnectionManager = new RobotConnectionManager();
|
||||
//长沙麻将AI处理器
|
||||
huNanChangSha = new HuNanChangSha();
|
||||
|
||||
log.info("长沙麻将机器人服务器组件初始化完成");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import taurus.client.Message;
|
|||
import taurus.client.TaurusClient;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import robot.mj.handler.HuNanChangSha;
|
||||
import taurus.client.business.GroupRoomBusiness;
|
||||
import taurus.util.ChangShaSuanFaTest;
|
||||
import taurus.util.TinHuChi;
|
||||
|
||||
|
|
@ -21,8 +20,6 @@ import java.sql.SQLException;
|
|||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
/**
|
||||
* 机器人连接管理器 - 管理与游戏服务器的连接
|
||||
*/
|
||||
|
|
@ -33,10 +30,12 @@ public class RobotConnectionManager {
|
|||
//存储全局的长沙麻将AI处理器
|
||||
private HuNanChangSha huNanChangSha;
|
||||
|
||||
private final String host="8.134.76.43";
|
||||
private final String host="192.168.0.32";
|
||||
private final int port=6311;
|
||||
|
||||
private TaurusClient client = null;
|
||||
// 连接状态管理
|
||||
private Map<String, Long> lastActivityTime = new ConcurrentHashMap<>();
|
||||
private Map<String, Boolean> connectionRegistered = new ConcurrentHashMap<>();
|
||||
|
||||
private Map<Integer, List<Integer>> playerOutcardsMap = new HashMap<>();
|
||||
|
||||
|
|
@ -59,8 +58,12 @@ public class RobotConnectionManager {
|
|||
public RobotConnectionManager() {
|
||||
gameClients = new HashMap<>();
|
||||
huNanChangSha = new HuNanChangSha();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有session列表
|
||||
*/
|
||||
|
|
@ -79,13 +82,18 @@ public class RobotConnectionManager {
|
|||
/**
|
||||
* 连接到长沙麻将游戏服务器
|
||||
*/
|
||||
public boolean connectToGameServer(String connecId) {
|
||||
public TaurusClient connectToGameServer(String connecId) {
|
||||
try {
|
||||
//检查是否已经连接
|
||||
if (gameClients.containsKey(connecId)) {
|
||||
TaurusClient existingClient = gameClients.get(connecId);
|
||||
if (existingClient.isConnected()) {
|
||||
return true;
|
||||
//检查是否已注册
|
||||
if (!connectionRegistered.getOrDefault(connecId, false)) {
|
||||
//如果连接存在但未注册 尝试重新注册
|
||||
reRegisterConnection(connecId, existingClient);
|
||||
}
|
||||
return existingClient;
|
||||
} else {
|
||||
//连接断开 移除旧的客户端
|
||||
disconnectFromGameServer(connecId);
|
||||
|
|
@ -93,22 +101,9 @@ public class RobotConnectionManager {
|
|||
}
|
||||
|
||||
//创建Taurus客户端
|
||||
client = new TaurusClient(host + ":" + port, "game", TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.connect();
|
||||
TaurusClient client = new TaurusClient(host + ":" + port, "game", TaurusClient.ConnectionProtocol.Tcp);
|
||||
|
||||
|
||||
|
||||
System.out.println("csmj OnEvent " + client.getSession());
|
||||
/// GroupRoomBusiness.joinRoom(383709, "room:592473", "{user}:101555", null);
|
||||
//Thread.sleep(5000);
|
||||
System.out.println("csmj OnEvent2 " + client.getSession());
|
||||
|
||||
|
||||
|
||||
|
||||
System.out.println("client.getSession()1111" +client.getSession());
|
||||
System.out.println("client.getId()1111" +client.getId());
|
||||
//添加事件监听器处理网络消息和连接断开
|
||||
//添加事件监听器处理网络消息和连接断开 - 必须在连接之前添加监听器
|
||||
client.addEventListener(TaurusClient.NetClientEvent.OnEvent, new IEventListener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
|
|
@ -117,7 +112,6 @@ public class RobotConnectionManager {
|
|||
//获取 msg
|
||||
Message message = (Message) event.getParameter("msg");
|
||||
if (message == null) {
|
||||
System.out.println("在OnEvent中收到空消息");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -126,8 +120,8 @@ public class RobotConnectionManager {
|
|||
String command = message.command;
|
||||
System.out.println("csmj OnEvent msg: " + command);
|
||||
|
||||
// 添加更详细的日志
|
||||
System.out.println("收到协议命令: " + command + " params: " + param);
|
||||
//更新最后活动时间
|
||||
lastActivityTime.put(connecId, System.currentTimeMillis());
|
||||
|
||||
//根据玩法ID处理不同的回调
|
||||
if (StringUtil.isNotEmpty(command)) {
|
||||
|
|
@ -143,43 +137,72 @@ public class RobotConnectionManager {
|
|||
public void handleEvent(Event event) {
|
||||
System.out.println("Connect");
|
||||
System.out.println("csmj Connect connecId: " + connecId);
|
||||
|
||||
//连接成功后立即尝试注册连接
|
||||
registerConnection(connecId, client);
|
||||
}
|
||||
});
|
||||
|
||||
// 添加连接断开监听器
|
||||
/* client.addEventListener(TaurusClient.NetClientEvent.Disconnect, new IEventListener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
System.out.println("Connection disconnected for connecId: " + connecId);
|
||||
connectionRegistered.put(connecId, false);
|
||||
}
|
||||
});*/
|
||||
|
||||
ITObject readyParam = new TObject();
|
||||
readyParam.putString("session","{user}:101555,c739ec6c3e93e9655e507397f78d857f");
|
||||
readyParam.putString("pos", "10,10");
|
||||
//readyParam.putString("connecId", "1");
|
||||
//pos
|
||||
client.send(Config.JOIN_ROOM_CS, readyParam, response -> {
|
||||
System.out.println("csmj OnEvent " + response.returnCode);
|
||||
log.info("加入房间请求发送结果: returnCode={}", response.returnCode);
|
||||
});
|
||||
client.connect();
|
||||
//连接成功后立即尝试注册连接
|
||||
//registerConnection(connecId, client);
|
||||
|
||||
readyParam.del("connecId");
|
||||
sleep(5000);
|
||||
client.send(Config.GAME_READY_CS, readyParam, null);
|
||||
|
||||
|
||||
System.out.println(client);
|
||||
System.out.println("client.getSession()2222" +client.getSession());
|
||||
System.out.println("client.getId()2222" +client.getId());
|
||||
gameClients.put(connecId, client);
|
||||
System.out.println("gameClients" + gameClients.get(connecId));
|
||||
|
||||
return true;
|
||||
return client;
|
||||
} catch (Exception e) {
|
||||
log.error("连接到游戏服务器时发生异常", e);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册连接到游戏服务器
|
||||
*/
|
||||
private void registerConnection(String connecId, TaurusClient client) {
|
||||
ITObject authParam = new TObject();
|
||||
authParam.putString("type", "robot_auth");
|
||||
authParam.putString("connecId", connecId);
|
||||
authParam.putInt("playerId", 0); // 机器人ID占位符
|
||||
|
||||
client.send("1000", authParam, response -> {
|
||||
System.out.println("Robot authentication sent for connecId: " + connecId + ", response: " + response.returnCode);
|
||||
|
||||
if (response.returnCode == 0) {
|
||||
connectionRegistered.put(connecId, true);
|
||||
System.out.println("Successfully registered connection for connecId: " + connecId);
|
||||
} else {
|
||||
System.out.println("Failed to register connection for connecId: " + connecId);
|
||||
connectionRegistered.put(connecId, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新注册连接
|
||||
*/
|
||||
private void reRegisterConnection(String connecId, TaurusClient client) {
|
||||
System.out.println("Re-registering connection for connecId: " + connecId);
|
||||
registerConnection(connecId, client);
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开与游戏服务器的连接
|
||||
*/
|
||||
public void disconnectFromGameServer(String compositeKey) {
|
||||
TaurusClient client = gameClients.remove(compositeKey);
|
||||
connectionRegistered.remove(compositeKey);
|
||||
lastActivityTime.remove(compositeKey);
|
||||
|
||||
if (client != null && client.isConnected()) {
|
||||
try {
|
||||
client.killConnection();
|
||||
|
|
@ -189,26 +212,11 @@ public class RobotConnectionManager {
|
|||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RobotConnectionManager rb=new RobotConnectionManager();
|
||||
boolean i = rb.connectToGameServer("1");
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据connecId获取游戏服务器连接
|
||||
*/
|
||||
public TaurusClient getGameServerConnection(String connecId) {
|
||||
TaurusClient client = gameClients.get(connecId);
|
||||
|
||||
if (client == null) {
|
||||
System.out.println("Attempting to reconnect: " + connecId);
|
||||
// 尝试重新连接
|
||||
connectToGameServer(connecId);
|
||||
client = gameClients.get(connecId);
|
||||
}
|
||||
|
||||
return client;
|
||||
public TaurusClient getGameClient(String connecId) {
|
||||
return gameClients.get(connecId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -315,24 +323,20 @@ public class RobotConnectionManager {
|
|||
HuNanChangSha.drawCard(command, message);
|
||||
break;
|
||||
case "819": //摸牌
|
||||
System.out.println("Handling 819 - Draw card");
|
||||
huNanChangSha.getCard(command, message);
|
||||
break;
|
||||
case "813": //出牌提示
|
||||
System.out.println("Handling 813 - Discard card tip received!");
|
||||
huNanChangSha.outCard(client,playerOutcardsMap,playerchisMap,playerpengsMap,playermingsMap,playerzisMap);
|
||||
break;
|
||||
case "814": //操作提示(吃碰杠胡)
|
||||
System.out.println("Handling 814 - Action tips (Chi, Peng, Gang, Hu)");
|
||||
huNanChangSha.actionCard(param, client);
|
||||
break;
|
||||
case "2009": //其他操作 - 房间检查和踢人逻辑
|
||||
System.out.println("Handling 2009 - Other operations");
|
||||
try {
|
||||
Jedis jedis22 = Redis.use().getJedis();
|
||||
// 使用JiQiRens的sleepTime方法
|
||||
try {
|
||||
sleep(3000);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
@ -479,16 +483,13 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
case "815": //服务器通知客户端有玩家执行了操作
|
||||
System.out.println("Handling 815 - Server notifies client of player action");
|
||||
//[TCP->815] data:{"playerid":101555,"card":104,"opcard":[105,103],"from_seat":2,"type":1,"opengang":false}
|
||||
huNanChangSha.shanchuchuguopai(param);
|
||||
break;
|
||||
case "820": //换牌提示
|
||||
System.out.println("Handling 820 - Change card tips");
|
||||
HuNanChangSha.changePlayer(command, message);
|
||||
break;
|
||||
case "825":
|
||||
System.out.println("Handling 825");
|
||||
ITObject params25 = TObject.newInstance();
|
||||
params25.putInt("qi", 0);
|
||||
params25.putInt("id", 1);
|
||||
|
|
@ -498,7 +499,6 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
case "822":
|
||||
System.out.println("Handling 822");
|
||||
ITObject params22 = TObject.newInstance();
|
||||
//params.putInt("qi", 0);
|
||||
params22.putInt("id", 1);
|
||||
|
|
@ -510,7 +510,6 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
case "2008": //解散房间时候恢复机器人账号可以使用
|
||||
System.out.println("Handling 2008 - Restore robot accounts when room is dismissed");
|
||||
// Jedis jedis11s = Redis.use("group1_db11").getJedis();
|
||||
// String key = "g{" + groupId + "}:play:" + pid;
|
||||
//
|
||||
|
|
@ -542,7 +541,6 @@ public class RobotConnectionManager {
|
|||
}
|
||||
break;
|
||||
case "838": //补杠事件
|
||||
System.out.println("Handling 838 - Bu Gang event");
|
||||
int card838 = param.getInt("card");
|
||||
ITObject params838 = new TObject();
|
||||
params838.putInt("card", card838);
|
||||
|
|
@ -552,7 +550,6 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
case "816": //抢杠胡
|
||||
System.out.println("Handling 816 - Qiang Gang Hu");
|
||||
int card816 = param.getInt("card");
|
||||
ITObject params816 = new TObject();
|
||||
params816.putInt("type", 21); //胡牌类型
|
||||
|
|
@ -563,7 +560,6 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
case "821": //吃牌
|
||||
System.out.println("Handling 821 - Chi Pai");
|
||||
int card821 = param.getInt("card");
|
||||
ITObject params821 = new TObject();
|
||||
params821.putInt("type", 21); //吃牌类型
|
||||
|
|
@ -574,14 +570,12 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
case "823": //杠后补牌
|
||||
System.out.println("Handling 823 - Gang after draw card");
|
||||
//处理杠后补牌逻辑
|
||||
int card823 = param.getInt("card");
|
||||
huNanChangSha.getChangShaCardInhand().add(card823);
|
||||
log.info("杠后补牌: " + card823 + ", 当前手牌: " + huNanChangSha.getChangShaCardInhand());
|
||||
break;
|
||||
case "835": //听牌相关
|
||||
System.out.println("Handling 835 - Ting Pai related");
|
||||
ITObject params835 = new TObject();
|
||||
params835.putInt("qi", 0);
|
||||
params835.putInt("id", 1);
|
||||
|
|
@ -591,9 +585,11 @@ public class RobotConnectionManager {
|
|||
});
|
||||
break;
|
||||
default:
|
||||
System.out.println("Received unknown protocol command: " + command + ", params: " + param);
|
||||
System.out.println("收到未知协议命令: " + command + ", 参数: " + param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue