机器人连接

master
zhouwei 2026-01-27 17:28:01 +08:00
parent dda674af58
commit 18a90dd89d
12 changed files with 6033 additions and 152 deletions

View File

@ -40,6 +40,9 @@ public class RobotManager {
//使用数量计数器 跟踪每种玩法的机器人使用数量
private final Map<Integer, Integer> count = new ConcurrentHashMap<>();
//玩法对应的机器人轮询索引
private final Map<Integer, Integer> wanfaRobotIndex = new ConcurrentHashMap<>();
//玩法房间轮询器
private final Map<Integer, RoomWanfaMatcher> wanfaRoomPollers = new ConcurrentHashMap<>();
@ -49,6 +52,9 @@ public class RobotManager {
//机器人断开连接处理
private final RobotDisconnect robotDisconnect;
//跟踪已经恢复leftover_robot的机器人
private final Set<Integer> leftoverRobotRecovered = ConcurrentHashMap.newKeySet();
public RobotManager() {
@ -240,6 +246,85 @@ public class RobotManager {
}
}
/**
*
*/
public void disconnectExcessRobots(int wanfaId, int requiredCount) {
List<RobotInfo> allWanfaRobots = new ArrayList<>();
for (RobotInfo robot : connectedRobots.values()) {
if (robot.getWanfaId() == wanfaId) {
allWanfaRobots.add(robot);
}
}
//该玩法已连接的机器人
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()) {
RobotManagerInterface handler = getGameHandler(robot.getWanfaId());
if (handler != null) {
handler.disconnectRobot(robot);
log.debug("仅断开机器人 {} TCP连接保持注册状态", robot.getRobotId());
}
disconnectedCount++;
}
}
if (disconnectedCount > 0) {
log.debug("玩法 {} 成功断开 {} 个机器人的TCP连接目标连接数: {}", wanfaId, disconnectedCount, requiredCount);
}
}
}
/**
*
*/
public void connectRequiredRobots(int wanfaId, int requiredCount) {
List<RobotInfo> allWanfaRobots = new ArrayList<>();
for (RobotInfo robot : connectedRobots.values()) {
if (robot.getWanfaId() == wanfaId) {
allWanfaRobots.add(robot);
}
}
//该玩法已连接的机器人
int currentConnected = 0;
for (RobotInfo robot : allWanfaRobots) {
if (robot.isConnected()) {
currentConnected++;
}
}
//当前连接数小于所需数量 则连接更多机器人
if (currentConnected < requiredCount) {
int reconnectedCount = 0;
for (RobotInfo robot : allWanfaRobots) {
if (!robot.isConnected() && !robot.isUsing() && reconnectedCount < (requiredCount - currentConnected)) {
RobotManagerInterface handler = getGameHandler(robot.getWanfaId());
if (handler != null) {
handler.connectRobot(robot);
log.debug("重新连接玩法 {} 的机器人: {}", wanfaId, robot.getRobotId());
reconnectedCount++;
}
}
}
}
}
/**
*
*/
@ -283,13 +368,53 @@ public class RobotManager {
*
*/
public RobotInfo getLoggedInRobotForWanfa(int wanfaId) {
//获取指定玩法的所有可用机器人
List<RobotInfo> availableRobots = new ArrayList<>();
for (RobotInfo robot : connectedRobots.values()) {
if (robot.getWanfaId() == wanfaId && robot.isOnline() && robot.isConnected()) {
//更新最后活跃时间
robot.setLastActiveTime(System.currentTimeMillis());
return robot;
if (robot.getWanfaId() == wanfaId && robot.isOnline() && robot.isConnected() && !robot.isUsing()) {
availableRobots.add(robot);
}
}
if (!availableRobots.isEmpty()) {
int currentIndex = wanfaRobotIndex.getOrDefault(wanfaId, 0);
if (currentIndex >= availableRobots.size()) {
currentIndex = 0;
}
RobotInfo selectedRobot = availableRobots.get(currentIndex);
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()) {
allWanfaRobots.add(robot);
}
}
if (!allWanfaRobots.isEmpty()) {
int currentIndex = wanfaRobotIndex.getOrDefault(wanfaId, 0);
if (currentIndex >= allWanfaRobots.size()) {
currentIndex = 0;
}
RobotInfo selectedRobot = allWanfaRobots.get(currentIndex);
selectedRobot.setLastActiveTime(System.currentTimeMillis());
selectedRobot.setUsing(true);
int nextIndex = (currentIndex + 1) % allWanfaRobots.size();
wanfaRobotIndex.put(wanfaId, nextIndex);
return selectedRobot;
}
return null;
}
@ -319,12 +444,28 @@ public class RobotManager {
}
/**
*
* leftover_robot
*/
public void removeConnectedRobot(int robotId) {
connectedRobots.remove(robotId);
public void markLeftoverRobotRecovered(int robotId) {
leftoverRobotRecovered.add(robotId);
log.debug("机器人 {} 的leftover_robot已标记为已恢复", robotId);
}
/**
* leftover_robot
*/
public boolean isLeftoverRobotRecovered(int robotId) {
return leftoverRobotRecovered.contains(robotId);
}
/**
* leftover_robot
*/
public void leftoverRobotRemoved(int robotId) {
leftoverRobotRecovered.remove(robotId);
log.debug("机器人 {} 从leftover_robot恢复集合中移除", robotId);
}
/**
*
*/
@ -332,11 +473,29 @@ public class RobotManager {
if (robotDisconnect != null) {
robotDisconnect.disconnectRobot(robotId, groupId, gameId, roomId);
} else {
//如果RobotDisconnect还未初始化 使用原来的方式
RobotInfo robot = connectedRobots.get(robotId);
if (robot != null) {
disconnectRobot(robot);
}
}
}
/**
*
*/
public void roomProcessingFinish(String roomId) {
for (RoomWanfaMatcher matcher : wanfaRoomPollers.values()) {
matcher.roomProcessingFinish(roomId);
}
}
/**
* 使使
*/
public void releaseRobot(int robotId) {
RobotInfo robot = connectedRobots.get(robotId);
if (robot != null) {
robot.setUsing(false);
}
}
}

View File

@ -33,7 +33,7 @@ public class RobotDisconnect {
*
* @param robotId ID
* @param groupId ID
* @param gameId IDID
* @param gameId ID
* @param roomId ID
*/
public void disconnectRobot(int robotId, int groupId, int gameId, String roomId) {
@ -48,7 +48,7 @@ public class RobotDisconnect {
}
disconnectingRobots.add(robotId);
}
try {
try (Jedis jedis2 = Redis.use("group1_db2").getJedis()){
log.info("开始断开机器人 {} 的连接(群组={}, 玩法={}, 房间={}",robotId, groupId, gameId, roomId);
//从连接列表中移除机器人信息
@ -62,9 +62,11 @@ public class RobotDisconnect {
log.debug("游戏处理器已断开机器人 {} 连接", robotId);
}
//从连接列表中移除
robotManager.removeConnectedRobot(robotId);
log.debug("从连接列表中移除机器人 {}", robotId);
//释放机器人
robot.setUsing(false);
//恢复集合leftover_robot 再次分配leftover_robot计数
robotManager.leftoverRobotRemoved(robotId);
log.debug("机器人 {} 已被释放,可以重新分配", robotId);
}
//减少机器人使用数
@ -75,9 +77,14 @@ public class RobotDisconnect {
//更新Redis中的leftover_robot数量
if (groupId > 0 && gameId > 0) {
updateRedisLeftoverRobot(groupId, gameId, robotId);
if (!robotManager.isLeftoverRobotRecovered(robotId)) {
updateRedisLeftoverRobot(groupId, gameId, robotId);
}
}
//更新Redis2中的机器人start状态为0
updateRedis2StartStatus(robotId, 0);
//更新机器人状态为可用
updateDatabaseStatus(robotId);
log.info("机器人 {} 断开连接流程完成", robotId);
@ -115,4 +122,17 @@ public class RobotDisconnect {
}
}
/**
* Redis2start
*/
private void updateRedis2StartStatus(int robotId, int startValue) {
try (Jedis jedis2 = Redis.use("group1_db2").getJedis()) {
String gRobotKey = "{grobot}:" + robotId;
jedis2.hset(gRobotKey, "start", String.valueOf(startValue));
log.debug("Redis2已更新机器人 {} 的start状态为 {}", robotId, startValue);
} catch (Exception e) {
log.error("更新机器人 {} Redis2 start状态失败", robotId, e);
}
}
}

View File

@ -10,6 +10,7 @@ import com.group.robot.RobotManager;
import com.group.robot.info.RoomInfo;
import com.group.robot.matcher.RoomWanfaMatcher;
import com.taurus.core.entity.TObject;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.util.ICallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -20,6 +21,7 @@ import taurus.client.Message;
import com.taurus.core.entity.ITObject;
import com.taurus.core.events.Event;
import com.taurus.core.events.IEventListener;
import redis.clients.jedis.Jedis;
/**
* -
@ -203,29 +205,36 @@ public class RobotConnectionHandler {
}
}
/**
* 6 退
* @param robot
*/
public void readyTimeRobotExit(RobotInfo robot) {
public void readyTimeRobotExit(RobotInfo robot, Object joinRoomLock) {
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(6000);
log.info("机器人 {} 准备时间超过6秒且房间人数不足退出房间", robot.getRobotId());
TaurusClient client = robotClients.get(robot.getRobotId());
if (client != null && client.isConnected()) {
if (client != null) {
//发送离开房间协议
ITObject param = new TObject();
client.send("1005", param, response -> {
client.send("2005", param, response -> {
log.debug("机器人 {} 发送离开房间请求", robot.getRobotId());
});
} else {
log.warn("机器人 {} 连接不存在或未激活,跳过离开房间操作", robot.getRobotId());
}
//延迟后断开连接
Thread.sleep(1000);
disconnectRobot(robot.getRobotId());
//机器人退出空房间 增加leftover_robot数量
if (joinRoomLock != null) {
synchronized (joinRoomLock) {
increaseLeftoverRobot(robot);
}
} else {
increaseLeftoverRobot(robot);
}
} catch (InterruptedException e) {
log.debug("超时检查线程被中断: {}", robot.getRobotId());
Thread.currentThread().interrupt();
@ -233,6 +242,24 @@ public class RobotConnectionHandler {
});
}
/**
* leftover_robot 退
*/
private void increaseLeftoverRobot(RobotInfo robot) {
try (Jedis jedis11 = Redis.use("group1_db11").getJedis();Jedis jedis2 = Redis.use("group1_db2").getJedis()) {
String playKey = "g{" + robot.getGroupId() + "}:play:" + robot.getWanfaId();
jedis11.hincrBy(playKey, "leftover_robot", 1);
jedis2.hset("{grobot}:" + robot.getRobotId(), "start", "0");
robotManager.markLeftoverRobotRecovered(robot.getRobotId());
robotManager.roomProcessingFinish(robot.getRoomId());
log.debug("机器人 {} 退出空房间增加leftover_robot群组={}, 玩法={}", robot.getRobotId(), robot.getGroupId(), robot.getWanfaId());
} catch (Exception e) {
log.error("增加Redis leftover_robot时异常群组={}, 玩法={}", robot.getGroupId(), robot.getWanfaId(), e);
}
}
/**
*
*/
@ -253,20 +280,36 @@ public class RobotConnectionHandler {
});
}
public void sendJoinRoomMessage(RobotInfo robot) {
TaurusClient client = robotClients.get(robot.getRobotId());
if (client == null) {
log.warn("机器人 {} 没有有效的TCP连接无法发送加入房间消息", robot.getRobotId());
return;
}
ITObject readyParam = new TObject();
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
client.send("2002", readyParam, response -> {
log.debug("机器人 {} 发送加入房间请求响应: {}", robot.getRobotId(), response);
});
}
/**
*
*/
public void sendReadyMessage(RobotInfo robot) {
TaurusClient client = robotClients.get(robot.getRobotId());
if (client == null || !client.isConnected()) {
if (client == null) {
log.warn("机器人 {} 没有有效的TCP连接无法发送准备消息", robot.getRobotId());
return;
}
ITObject readyParam = new TObject();
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
client.send("1003", readyParam, response -> {
client.send("2003", readyParam, response -> {
log.debug("机器人 {} 发送准备请求响应: {}", robot.getRobotId(), response);
});
}
@ -275,7 +318,7 @@ public class RobotConnectionHandler {
*
*/
public interface RoomCreatedCallback {
void onRoomCreated(RobotInfo robot, int groupId, String roomId, int wanfaId);
void onRoomCreated(RobotInfo robot);
}
private RoomCreatedCallback roomCreatedCallback;
@ -288,7 +331,6 @@ public class RobotConnectionHandler {
*
*/
public void sendCreateRoom(RobotInfo robot, int groupId, int wanfaId) {
CompletableFuture<RoomInfo> future = new CompletableFuture<>();
TaurusClient client = robotClients.get(robot.getRobotId());
if (!client.isConnected()) {
log.warn("机器人 {} 的TCP连接未激活无法发送创建房间请求", robot.getRobotId());
@ -307,27 +349,13 @@ public class RobotConnectionHandler {
String roomId = responseData.getString("roomKey");
log.info("机器人 {} 成功创建房间 {}", robot.getRobotId(), roomId);
if (roomCreatedCallback != null) {
roomCreatedCallback.onRoomCreated(robot, groupId, roomId, wanfaId);
robot.setRoomId(roomId);
robot.setGroupId(groupId);
robot.setWanfaId(wanfaId);
roomCreatedCallback.onRoomCreated(robot);
}
}
});
/*client.send(Protocol.CREATE_ROOM_FOR_ROBOT, param, new ICallback<MessageResponse>() {
@Override
public void action(MessageResponse response) {
if (response.returnCode == 0) {
//解析响应数据
ITObject responseData = response.messageData.param;
RoomInfo roomInfo = new RoomInfo();
//RoomWanfaMatcher.robotJoinRoom(groupId, responseData.getString("roomKey"), wanfaId, true);
future.complete(roomInfo);
log.info("robot_mj_cs创建房间成功: " + roomInfo.getRoomId());
} else {
future.completeExceptionally(new RuntimeException("创建房间失败,错误码: " + response.returnCode));
}
}
});*/
}
}

View File

@ -12,11 +12,14 @@ public class RobotInfo {
private boolean isOnline; //是否在线
private boolean isConnected; //是否已连接到游戏服务器
private boolean isConnecting; //是否正在连接
private boolean isUsing; //是否正在被使用
private String roomId; //当前所在房间ID
private int groupId; //当前群组ID
private int wanfaId; //当前玩法ID
private long lastActiveTime; //最后活跃时间
private String session;
private String token;
public RobotInfo() {
this.lastActiveTime = System.currentTimeMillis();
@ -86,6 +89,15 @@ public class RobotInfo {
isConnecting = connecting;
}
public boolean isUsing() {
return isUsing;
}
public void setUsing(boolean using) {
isUsing = using;
}
public String getRoomId() {
return roomId;
}
@ -126,6 +138,13 @@ public class RobotInfo {
this.token = token;
}
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
@Override
public String toString() {

View File

@ -2,8 +2,9 @@ package com.group.robot.matcher;
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;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -34,6 +35,18 @@ public class RoomWanfaMatcher {
private volatile boolean isRunning = false;
//机器人连接处理器
private final RobotConnectionHandler robotConnectionHandler;
//记录上一次leftover_robot数量
private volatile int lastLeftoverRobot = -1;
//机器人加入房间锁
private final Object joinRoomLock = new Object();
//正在处理的房间
private final Set<String> processingRooms = ConcurrentHashMap.newKeySet();
//房间ID到机器人ID
private final Map<String, Integer> roomToRobotMap = new ConcurrentHashMap<>();
public RoomWanfaMatcher(RobotManager robotManager, int groupId, int wanfaId) {
this.robotManager = robotManager;
@ -44,6 +57,9 @@ public class RoomWanfaMatcher {
//设置房间创建回调
this.robotConnectionHandler.setRoomCreatedCallback(this::onRoomCreated);
//初始化轮询时会触发连接管理
this.lastLeftoverRobot = -1;
}
/**
@ -97,6 +113,9 @@ public class RoomWanfaMatcher {
String playKey = "g{" + groupId + "}:play:" + this.wanfaId;
int leftoverRobot = Integer.parseInt(jedis11.hget(playKey, "leftover_robot"));
//根据leftover_robot数量管理机器人连接状态
manageRobotConnections(leftoverRobot);
if (leftoverRobot > 0) {
//满人房间
int fullRooms = 0;
@ -143,15 +162,27 @@ public class RoomWanfaMatcher {
//处理未开始的陪打房间
if (status == 0) {
String playersStr = jedis0.hget(roomId, "players");
RobotInfo robot = new RobotInfo();
robot.setWanfaId(this.wanfaId);
robot.setGroupId(group);
robot.setRoomId(roomId);
robot.setRobotId(-1);
//房间没人 加入房间
if (playersStr.equals("[]")) {
robotJoinRoom(group, roomId, this.wanfaId, true);
//房间是否正在被加入
if (!processingRooms.contains(roomId)) {
processingRooms.add(roomId);
robotJoinRoom(robot, true);
}
} else {
//房间有人 不是机器人则加入房间
Integer robotInRoom = playerIsRobotRedis(playersStr);
if (robotInRoom == null) {
robotJoinRoom(group, roomId, this.wanfaId, false);
if (!processingRooms.contains(roomId)) {
processingRooms.add(roomId);
robotJoinRoom(robot, false);
}
}
}
}
@ -159,39 +190,56 @@ public class RoomWanfaMatcher {
}
}
}
} catch (Throwable t) { // 捕获所有Throwable包括Error
} catch (Throwable t) {
log.error("轮询玩法ID {} 的房间时发生严重错误", wanfaId, t);
}
}
/**
*
* @param isRobot
* @param robot
* */
private void robotJoinRoom(int group, String roomId, int wanfaId, boolean isRobot) {
//检查调度器是否可用
if (!scheduler.isShutdown()) {
CompletableFuture.runAsync(() -> {
RobotInfo robot = null;
try {
robot = robotManager.getLoggedInRobotForWanfa(wanfaId);
//加入房间
GroupRoomBusiness.joinRoom(group, roomId, robot.getSession(), null);
//准备
Thread.sleep(1000);
robotConnectionHandler.sendReadyMessage(robot);
if (isRobot) {
//6秒没有玩家加入 则退出房间
robotConnectionHandler.readyTimeRobotExit(robot);
}
} catch (Exception e) {
if (robot != null) {
robotConnectionHandler.disconnectRobot(robot.getRobotId());
}
log.error("机器人加入房间时发生错误: groupId={}, roomId={}, wanfaId={}, isRobot={}", group, roomId, wanfaId, isRobot, e);
private void robotJoinRoom(RobotInfo robot, boolean isRobot) {
synchronized (joinRoomLock) {
RobotInfo robotInfo = robot;
String roomId = robot != null ? robot.getRoomId() : null;
int groupId = robot.getGroupId();
try {
if (robotInfo.getRobotId() == -1) {
robotInfo = robotManager.getLoggedInRobotForWanfa(wanfaId);
robotInfo.setGroupId(groupId);
robotInfo.setRoomId(roomId);
}
});
//加入房间
GroupRoomBusiness.joinRoom(robotInfo.getGroupId(), robotInfo.getRoomId(), robotInfo.getSession(), null);
Thread.sleep(5000);
robotConnectionHandler.sendJoinRoomMessage(robotInfo);
//准备
Thread.sleep(1000);
robotConnectionHandler.sendReadyMessage(robotInfo);
//记录机器人和房间的关联
roomToRobotMap.put(roomId, robotInfo.getRobotId());
if (isRobot) {
updateRobotStatusRedis(robotInfo, isRobot);
//6秒没有玩家加入 则退出房间
robotConnectionHandler.readyTimeRobotExit(robotInfo, joinRoomLock);
} else {
updateRobotStatusRedis(robotInfo, isRobot);
}
} catch (Exception e) {
if (robotInfo != null) {
robotConnectionHandler.disconnectRobot(robotInfo.getRobotId());
}
} finally {
if (roomId != null) {
processingRooms.remove(roomId);
}
}
}
}
@ -199,25 +247,28 @@ public class RoomWanfaMatcher {
* TCP
*/
private void createRobotWanfaRoomTCP(int groupId, int wanfaId) {
try {
RobotInfo robot = robotManager.getLoggedInRobotForWanfa(wanfaId);
if (robot == null) {
log.warn("未能获取到玩法ID {} 的已登录机器人", wanfaId);
return;
synchronized (joinRoomLock) {
try {
RobotInfo robot = robotManager.getLoggedInRobotForWanfa(wanfaId);
//使用机器人连接处理器发送创建房间请求
robotConnectionHandler.sendCreateRoom(robot, groupId, wanfaId);
} catch (Exception e) {
log.error("创建玩法ID {} 的房间时发生错误", wanfaId, e);
}
//使用机器人连接处理器发送创建房间请求
robotConnectionHandler.sendCreateRoom(robot, groupId, wanfaId);
} catch (Exception e) {
log.error("创建玩法ID {} 的房间时发生错误", wanfaId, e);
}
}
/**
*
*/
private void onRoomCreated(RobotInfo robot, int groupId, String roomId, int wanfaId) {
//加入新创建的房间
robotJoinRoom(groupId, roomId, wanfaId, true);
private void onRoomCreated(RobotInfo robot) {
try {
robotJoinRoom(robot, true);
} catch (Exception e) {
if (robot != null) {
robotConnectionHandler.disconnectRobot(robot.getRobotId());
}
}
}
/**
@ -251,6 +302,22 @@ public class RoomWanfaMatcher {
public boolean isRunning() {
return isRunning;
}
/**
* leftover_robot
*/
private void manageRobotConnections(int currentLeftoverRobot) {
if (lastLeftoverRobot != currentLeftoverRobot) {
if (currentLeftoverRobot <= 0 && lastLeftoverRobot > 0) {
//leftover_robot变为0 断开该玩法未连接的机器人
robotManager.disconnectExcessRobots(wanfaId, 0);
} else if (currentLeftoverRobot > 0 && lastLeftoverRobot <= 0) {
//leftover_robot变为正数 重新连接机器人
robotManager.connectRequiredRobots(wanfaId, currentLeftoverRobot);
}
lastLeftoverRobot = currentLeftoverRobot;
}
}
/**
*
@ -272,4 +339,36 @@ public class RoomWanfaMatcher {
}
log.info("玩法ID {} 的房间轮询已停止", wanfaId);
}
/**
*
*/
private void updateRobotStatusRedis(RobotInfo robot, boolean isRobot) {
try (Jedis jedis11 = Redis.use("group1_db11").getJedis(); Jedis jedis2 = Redis.use("group1_db2").getJedis()) {
String playKey = "g{" + robot.getGroupId() + "}:play:" + robot.getWanfaId();
if (!isRobot) {
jedis11.hincrBy(playKey, "leftover_robot", -1);
String gRobotKey = "{grobot}:" + robot.getRobotId();
jedis2.hset(gRobotKey, "start", "1");
log.debug("机器人 {} 加入非机器人房间减少leftover_robot并更新redis2状态群组={}, 玩法={}", robot.getRobotId(), robot.getGroupId(), robot.getWanfaId());
}
} catch (Exception e) {
log.error("更新机器人状态时异常,机器人={}, 群组={}, 玩法={}", robot.getRobotId(), robot.getGroupId(), robot.getWanfaId(), e);
}
}
/**
* processingRooms
*/
public void roomProcessingFinish(String roomId) {
processingRooms.remove(roomId);
Integer robotId = roomToRobotMap.remove(roomId);
if (robotId != null) {
robotManager.releaseRobot(robotId);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
<!-- Enable disable Nagle algorithm on sockets, true == disable -->
<tcpNoDelay>true</tcpNoDelay>
<!-- 会话超时时间(单位秒)-->
<sessionTimeout>15</sessionTimeout>
<sessionTimeout>300</sessionTimeout>
<!-- Bind socket addresses -->
<socketAddresses>

View File

@ -24,7 +24,7 @@
<!-- Enable disable Nagle algorithm on sockets, true == disable -->
<tcpNoDelay>true</tcpNoDelay>
<!-- 会话超时时间(单位秒)-->
<sessionTimeout>15</sessionTimeout>
<sessionTimeout>300</sessionTimeout>
<!-- Bind socket addresses -->
<socketAddresses>

View File

@ -100,4 +100,34 @@ public class Config {
public static final String CREATE_ROOM_ROBOT = "create_room_for_robot";
public static final String INIT_CONNECTION = "init_connection";
/**
* - robot_mgr to robot_mj_cs
*/
public static final String JOIN_ROOM = "2002";
/**
* - robot_mgr to robot_mj_cs
*/
public static final String GAME_READY = "2003";
/**
* 退 - 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";
/**
* - robot_mgr to game_mj_cs
*/
public static final String JOIN_ROOM_CS = "1002";
/**
* 退 - robot_mgr to game_mj_cs
*/
public static final String EXIT_ROOM_CS = "1005";
}

View File

@ -6,9 +6,13 @@ import com.robot.MainServer;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.routes.ActionKey;
import com.taurus.core.util.ICallback;
import com.taurus.permanent.data.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import robot.mj.handler.HuNanChangShaHandler;
import taurus.client.MessageResponse;
import taurus.client.TaurusClient;
/**
* -
@ -84,6 +88,7 @@ public class EXGameController extends GameController {
response.putString("roomKey", roomInfo.getRoomId());
response.putInt("groupId", roomInfo.getGroupId());
response.putInt("wanfaId", roomInfo.getWanfaId());
response.putInt("robotId", robotId);
response.putString("server_ip", roomInfo.getServerIp());
response.putInt("server_port", roomInfo.getServerPort());
@ -106,4 +111,120 @@ public class EXGameController extends GameController {
}
}
/**
* robot_mgr
*/
@ActionKey(value = Config.JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
public void joinRoom(Session session, ITObject params, int gid) {
try {
log.info("收到robot_mgr的机器人准备请求Session: {}, GID: {}, 参数: {}", session, gid, params);
//在收到加入房间请求 建立到长沙麻将游戏服务器的连接
TaurusClient client = GameServerConnector.getCsMjGameServerConnection();
if (client == null) {
log.error("无法连接到长沙麻将游戏服务器");
ITObject errorResponse = TObject.newInstance();
errorResponse.putInt("error", 1);
errorResponse.putString("message", "无法连接到游戏服务器");
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
return;
}
//发送准备请求
client.send(Config.JOIN_ROOM_CS, params, response -> {
System.out.println("进入房间成功: " + response.returnCode);
});
} catch (Exception e) {
e.printStackTrace();
ITObject errorResponse = TObject.newInstance();
errorResponse.putInt("error", 1);
errorResponse.putString("message", "服务器内部错误: " + e.getMessage());
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
}
}
/**
* robot_mgr
*/
@ActionKey(value = Config.GAME_READY, validate = GameInterceptor.NOT_PLAYER)
public void robotReadyRoom(Session session, ITObject params, int gid) {
try {
log.info("收到robot_mgr的机器人准备请求Session: {}, GID: {}, 参数: {}", session, gid, params);
//在收到准备请求 建立到长沙麻将游戏服务器的连接
TaurusClient client = GameServerConnector.getCsMjGameServerConnection();
if (client == null) {
log.error("无法连接到长沙麻将游戏服务器");
ITObject errorResponse = TObject.newInstance();
errorResponse.putInt("error", 1);
errorResponse.putString("message", "无法连接到游戏服务器");
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
return;
}
//发送准备请求
client.send(Config.GAME_READY_CS, params, new ICallback<MessageResponse>() {
@Override
public void action(MessageResponse readyResponse) {
log.info("机器人准备请求发送结果: returnCode={}", readyResponse.returnCode);
if (readyResponse.returnCode == 0) {
log.info("机器人准备成功");
ITObject successResponse = TObject.newInstance();
successResponse.putString("status", "success");
successResponse.putString("message", "机器人准备成功");
MainServer.instance.sendResponse(gid, 0, successResponse, session);
} else {
log.error("机器人准备失败,返回码: {}", readyResponse.returnCode);
ITObject errorResponse = TObject.newInstance();
errorResponse.putInt("error", 1);
errorResponse.putString("message", "机器人准备失败");
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
}
}
});
} catch (Exception e) {
e.printStackTrace();
log.error("处理机器人准备请求时发生错误", e);
ITObject errorResponse = TObject.newInstance();
errorResponse.putInt("error", 1);
errorResponse.putString("message", "服务器内部错误: " + e.getMessage());
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
}
}
/**
* robot_mgr退
*/
@ActionKey(value = Config.EXIT_ROOM, validate = GameInterceptor.NOT_PLAYER)
public void exitRoom(Session session, ITObject params, int gid) {
try {
log.info("收到robot_mgr的机器人准备请求Session: {}, GID: {}, 参数: {}", session, gid, params);
TaurusClient client = GameServerConnector.getCsMjGameServerConnection();
client.send(Config.EXIT_ROOM_CS, params, response -> {
System.out.println("退出房间成功: " + response.returnCode);
});
} catch (Exception e) {
e.printStackTrace();
ITObject errorResponse = TObject.newInstance();
errorResponse.putInt("error", 1);
errorResponse.putString("message", "服务器内部错误: " + e.getMessage());
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
}
}
}

View File

@ -0,0 +1,114 @@
package robot.mj;
import com.taurus.core.util.ICallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import taurus.client.TaurusClient;
import taurus.client.Message;
import taurus.client.SocketCode;
import taurus.client.MessageResponse;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.events.Event;
import com.taurus.core.events.IEventListener;
/**
* -
*/
public class GameServerConnector {
private static final Logger log = LoggerFactory.getLogger(GameServerConnector.class);
//长沙麻将服务器地址
private static final String CS_MJ_SERVER_ADDRESS = "8.134.76.43:6311";
//长沙麻将服务器连接
private static volatile TaurusClient csMjConnection;
/**
*
*/
public static TaurusClient getCsMjGameServerConnection() {
if (csMjConnection != null && csMjConnection.isConnected()) {
return csMjConnection;
}
synchronized (GameServerConnector.class) {
if (csMjConnection != null) {
return csMjConnection;
}
csMjConnection = createConnection(CS_MJ_SERVER_ADDRESS, "长沙麻将");
if (csMjConnection != null) {
log.info("成功创建到长沙麻将游戏服务器的连接: {}", CS_MJ_SERVER_ADDRESS);
} else {
log.error("无法连接到长沙麻将游戏服务器: {}", CS_MJ_SERVER_ADDRESS);
return null;
}
}
return csMjConnection;
}
/**
*
*/
private static TaurusClient createConnection(String serverAddress, String gameName) {
try {
log.info("正在连接到{}服务器: {}", gameName, serverAddress);
TaurusClient client = new TaurusClient(serverAddress, "game", TaurusClient.ConnectionProtocol.Tcp);
//添加连接事件监听器
client.addEventListener(TaurusClient.NetClientEvent.Connect, new IEventListener() {
@Override
public void handleEvent(Event event) {
SocketCode code = (SocketCode) event.getParameter("code");
if (code == SocketCode.Connect) {
log.info("成功连接到{}服务器: {}", gameName, serverAddress);
} else {
log.warn("连接到{}服务器失败: {},错误码: {}", gameName, serverAddress, code);
}
}
});
//添加消息接收事件监听器
client.addEventListener(TaurusClient.NetClientEvent.OnEvent, new IEventListener() {
@Override
public void handleEvent(Event event) {
Message message = (Message) event.getParameter("msg");
if (message != null) {
log.debug("从{}服务器收到消息: 命令={},参数={}", gameName, message.command, message.param);
}
}
});
client.connect();
Thread.sleep(100);
return client;
} catch (Exception e) {
log.error("连接到{}服务器时发生错误: {}", gameName, serverAddress, e);
return null;
}
}
/**
*
*/
public static void sendProtocolToCsMj(String protocol, ITObject params, ICallback<MessageResponse> responseCallback) {
TaurusClient connection = getCsMjGameServerConnection();
if (connection != null) {
connection.send(protocol, params, responseCallback);
} else {
log.error("无法发送协议到长沙麻将游戏服务器,连接不可用");
// 在回调中返回错误
if (responseCallback != null) {
MessageResponse errorResponse = new MessageResponse();
errorResponse.returnCode = 1;
errorResponse.messageData = new taurus.client.Message();
errorResponse.messageData.param = new com.taurus.core.entity.TObject();
responseCallback.action(errorResponse);
}
}
}
}

View File

@ -91,6 +91,7 @@ public class RoomCreator {
roomMap.put("payer", String.valueOf(robotId)); //支付者ID
roomMap.put("rewardType", "0"); //奖励类型
roomMap.put("rewardValueType", "0"); //奖励值类型
roomMap.put("seats", "[1]"); //房间状态
roomMap.put("status", "0"); //房间状态
roomMap.put("times", "4"); //局数
roomMap.put("xipai_rewardType", "3"); //洗牌奖励类型
@ -165,10 +166,6 @@ public class RoomCreator {
switch (wanfaId) {
case 10: //长沙麻将
return 6311;
case 22: //湖南红中
return 6421;
case 66: //跑得快
return 6841;
default:
return 6311;
}