修改机器人登录连接需求
parent
9717f80bfb
commit
552620e486
|
|
@ -2,14 +2,14 @@ package com.group;
|
|||
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.data.cache.AccountCache;
|
||||
import com.data.cache.GroupCache;
|
||||
import com.group.robot.RobotManager;
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.taurus.core.entity.ITArray;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.plugin.database.DataBase;
|
||||
|
|
@ -19,11 +19,9 @@ import com.taurus.core.routes.Routes;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import taurus.client.NetManager;
|
||||
|
||||
|
||||
|
||||
public class MainServer extends Extension {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainServer.class);
|
||||
private ScheduledThreadPoolExecutor timeScheduler;
|
||||
|
|
@ -32,8 +30,8 @@ public class MainServer extends Extension {
|
|||
private static final String FORCE_VER_KEY = "force_ver";
|
||||
|
||||
//机器人管理器
|
||||
private RobotManager robotManager;
|
||||
|
||||
private RobotManager robotManager = new RobotManager();
|
||||
|
||||
public static Map<String,String> lua_map = new HashMap<>();
|
||||
public MainServer() {
|
||||
super();
|
||||
|
|
@ -65,17 +63,26 @@ public class MainServer extends Extension {
|
|||
public void onStart() {
|
||||
System.out.println("开始创建机器人连接...");
|
||||
|
||||
|
||||
|
||||
//初始化机器人管理器
|
||||
robotManager = new RobotManager();
|
||||
|
||||
//0 加载机器人到redis 2
|
||||
loadGroupRobot();
|
||||
|
||||
// 1. 先启动独立的事件处理线程(只启动一次)
|
||||
//1.先启动独立的事件处理线程(只启动一次)
|
||||
startNetEventThread();
|
||||
|
||||
//2.加载机器人到redis 2
|
||||
loadGroupRobot();
|
||||
|
||||
//关闭时重置机器人状态
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::resetRobotStatus));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置机器人状态为未使用
|
||||
*/
|
||||
private void resetRobotStatus() {
|
||||
try {
|
||||
String sql = "UPDATE account SET start = 0 WHERE jiqiren = 9998";
|
||||
DataBase.use().executeUpdate(sql);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 独立的事件处理线程
|
||||
|
|
@ -100,67 +107,60 @@ public class MainServer extends Extension {
|
|||
* 把机器人加载到redis2
|
||||
*/
|
||||
private void loadGroupRobot(){
|
||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||
String sql = "SELECT id,acc,nick,portrait,password FROM `account` WHERE jiqiren=9998 and start = 0";
|
||||
ITArray robotIds = null;
|
||||
try {
|
||||
String sql = String.format("SELECT id,acc,nick,portrait,password FROM `account` WHERE jiqiren=9998 and start = 0");
|
||||
ITArray robotIds = DataBase.use().executeQueryByTArray(sql);
|
||||
HashMap<String, String> robotMap = new HashMap<>();
|
||||
|
||||
//遍历机器人,
|
||||
for(int i = 0; i < robotIds.size(); ++i) {
|
||||
// //把机器人按group 分类好 存放到redis2
|
||||
|
||||
ITObject robot = robotIds.getTObject(i);
|
||||
Integer robotId = robot.getInt("id");
|
||||
String robotAcc = robot.getString("acc");
|
||||
String robotNick = robot.getString("nick");
|
||||
String robotPortrait = robot.getString("portrait");
|
||||
String robotPassword = robot.getString("password");
|
||||
|
||||
robotMap.put("acc", robotAcc);
|
||||
robotMap.put("nick", robotNick);
|
||||
robotMap.put("portrait", robotPortrait);
|
||||
robotMap.put("password", robotPassword);
|
||||
jedis2.hmset("{robot}:" + robotId , robotMap);
|
||||
|
||||
// String sqls = String.format("UPDATE `account` SET start = %d WHERE id = %d", 1, robotId);
|
||||
// DataBase.use().executeUpdate(sqls);
|
||||
}
|
||||
|
||||
|
||||
Map<String,String> gRobotMap = new HashMap<>();
|
||||
gRobotMap.put("start", "0");
|
||||
gRobotMap.put("pid", "66");
|
||||
jedis2.hmset("{grobot}:"+101666, gRobotMap);
|
||||
|
||||
|
||||
|
||||
} catch (SQLException e) {
|
||||
robotIds = DataBase.use().executeQueryByTArray(sql);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}finally {
|
||||
jedis2.close();
|
||||
}
|
||||
|
||||
Map<Integer, Integer> gameRobotConfig = new HashMap<>();
|
||||
gameRobotConfig.put(10, 5);
|
||||
gameRobotConfig.put(22, 3);
|
||||
int robotIndex = 0;
|
||||
|
||||
//长沙麻将机器人
|
||||
List<RobotInfo> csRobots = new ArrayList<>();
|
||||
for (int i = 0; i < gameRobotConfig.get(10) && robotIndex < robotIds.size(); i++, robotIndex++) {
|
||||
ITObject robot = robotIds.getTObject(robotIndex);
|
||||
RobotInfo robotInfo = createRobotInfo(robot, 10);
|
||||
csRobots.add(robotInfo);
|
||||
}
|
||||
|
||||
//红中麻将机器人
|
||||
List<RobotInfo> hzRobots = new ArrayList<>();
|
||||
for (int i = 0; i < gameRobotConfig.get(22) && robotIndex < robotIds.size(); i++, robotIndex++) {
|
||||
ITObject robot = robotIds.getTObject(robotIndex);
|
||||
RobotInfo robotInfo = createRobotInfo(robot, 22);
|
||||
hzRobots.add(robotInfo);
|
||||
}
|
||||
|
||||
log.info("机器人分配完成:长沙麻将{}个,红中麻将{}个", csRobots.size(), hzRobots.size());
|
||||
|
||||
//登录分配的机器人
|
||||
//初始化机器人管理器
|
||||
robotManager.loginRobots(csRobots, 10);
|
||||
robotManager.loginRobots(hzRobots, 22);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建机器人信息对象
|
||||
*/
|
||||
private RobotInfo createRobotInfo(ITObject robotObj, int wanfaId) {
|
||||
RobotInfo robot = new RobotInfo();
|
||||
robot.setRobotId(robotObj.getInt("id"));
|
||||
robot.setAccount(robotObj.getString("acc"));
|
||||
robot.setNickName(robotObj.getString("nick"));
|
||||
robot.setPortrait(robotObj.getString("portrait"));
|
||||
robot.setPassword(robotObj.getString("password"));
|
||||
robot.setWanfaId(wanfaId);
|
||||
return robot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configRoute(Routes me) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
if(timeScheduler!=null) {
|
||||
timeScheduler.shutdownNow();
|
||||
|
||||
//关闭机器人管理器
|
||||
if (robotManager != null) {
|
||||
robotManager.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -3,26 +3,22 @@ package com.group.robot;
|
|||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import com.group.robot.connect.RedisRoomListener;
|
||||
import com.group.robot.connect.RobotDisconnect;
|
||||
import com.group.robot.handler.*;
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.group.robot.info.RoomInfo;
|
||||
import com.group.robot.matcher.RoomWanfaMatcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import com.taurus.core.plugin.redis.Redis;
|
||||
import com.taurus.core.plugin.database.DataBase;
|
||||
import com.taurus.core.entity.ITArray;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.group.robot.handler.CSMJRobotHandler;
|
||||
import com.group.robot.handler.HZMJRobotHandler;
|
||||
import com.group.robot.handler.PokerRobotHandler;
|
||||
import com.group.robot.handler.ZZMJRobotHandler;
|
||||
import com.group.robot.matcher.majiang.CSMJRoomMatcher;
|
||||
import com.group.robot.matcher.majiang.HZMJRoomMatcher;
|
||||
import com.group.robot.matcher.poker.PokerRoomMatcher;
|
||||
import com.group.robot.matcher.majiang.ZZMJRoomMatcher;
|
||||
import com.group.robot.matcher.GameRoomMatcherInterface;
|
||||
import taurus.client.business.AccountBusiness;
|
||||
|
||||
/**
|
||||
* 机器人管理器 - 管理游戏机器人、游戏房间、监听
|
||||
|
|
@ -42,12 +38,12 @@ public class RobotManager {
|
|||
//游戏特定的房间匹配器
|
||||
private final Map<Integer, GameRoomMatcherInterface> gameRoomMatchers = new ConcurrentHashMap<>();
|
||||
|
||||
//Redis房间监听器
|
||||
private RedisRoomListener redisRoomListener;
|
||||
|
||||
//使用数量计数器 跟踪每种玩法的机器人使用数量
|
||||
private final Map<Integer, Integer> count = new ConcurrentHashMap<>();
|
||||
|
||||
//玩法房间轮询器
|
||||
private final Map<Integer, RoomWanfaMatcher> wanfaRoomPollers = new ConcurrentHashMap<>();
|
||||
|
||||
//定时任务调度器
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
|
||||
|
||||
|
|
@ -61,9 +57,6 @@ public class RobotManager {
|
|||
|
||||
//1、启动 ==》2、登录,3、是否快捷登录 4、分配做什么工作(a:长麻,b:红中,c:跑得快)5、干活,6、销毁回收
|
||||
|
||||
|
||||
|
||||
|
||||
//初始化游戏处理器
|
||||
initializeGameHandlers();
|
||||
//1、设定每个玩法多少机器人
|
||||
|
|
@ -72,10 +65,7 @@ public class RobotManager {
|
|||
//初始化游戏房间匹配器
|
||||
initializeGameRoomMatchers();
|
||||
|
||||
//初始化Redis房间监听器
|
||||
initializeRedisListener();
|
||||
|
||||
//定时清理任务
|
||||
//定时任务
|
||||
startCleanupTask();
|
||||
}
|
||||
|
||||
|
|
@ -94,32 +84,6 @@ public class RobotManager {
|
|||
log.info("已初始化 {} 个游戏处理器", gameHandlers.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加游戏处理器
|
||||
*/
|
||||
public void addGameHandler(int gameId, RobotManagerInterface handler) {
|
||||
gameHandlers.put(gameId, handler);
|
||||
log.info("添加游戏处理器: gameId={}, handler={}", gameId, handler.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取游戏处理器
|
||||
*/
|
||||
public RobotManagerInterface getGameHandler(int gameId) {
|
||||
return gameHandlers.get(gameId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Redis房间监听器
|
||||
*/
|
||||
private void initializeRedisListener() {
|
||||
redisRoomListener = new RedisRoomListener(this);
|
||||
//启动Redis实时监听
|
||||
redisRoomListener.startListening();
|
||||
|
||||
log.info("房间监控已启动 - 实时监听模式,支持 {} 种游戏类型", gameHandlers.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化游戏房间匹配器
|
||||
*/
|
||||
|
|
@ -145,115 +109,146 @@ public class RobotManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* 定时清理任务
|
||||
* 登录单个机器人
|
||||
*/
|
||||
private void startCleanupTask() {
|
||||
//每30秒检查一次不活跃的机器人连接
|
||||
scheduler.scheduleAtFixedRate(this::cleanupInactiveRobots, 30, 30, java.util.concurrent.TimeUnit.SECONDS);
|
||||
public void loginRobots(List<RobotInfo> robots, int gameId) {
|
||||
try (Jedis jedis0 = Redis.use().getJedis(); Jedis jedis2 = Redis.use("group1_db2").getJedis()){
|
||||
for (RobotInfo robot : robots) {
|
||||
AccountBusiness accountBusiness = new AccountBusiness();
|
||||
//检查Redis中是否存在已有token
|
||||
Set<String> tokenKeys = jedis0.keys("{user}:" + robot.getRobotId() + "_token");
|
||||
ITObject loginResult;
|
||||
|
||||
log.info("定时清理任务已启动");
|
||||
if (tokenKeys != null && !tokenKeys.isEmpty()) {
|
||||
log.debug("机器人 {} 存在已有token,直接使用", robot.getRobotId());
|
||||
Set<String> tokenSet = jedis0.smembers("{user}:" + robot.getRobotId() + "_token");
|
||||
List<String> tokenList = new ArrayList<>(tokenSet);
|
||||
|
||||
robot.setSession("{user}:" + robot.getRobotId());
|
||||
if (!tokenList.isEmpty()) {
|
||||
robot.setToken(tokenList.get(0));
|
||||
} else {
|
||||
//如果没有token 则执行正常登录
|
||||
loginResult = accountBusiness.idPasswordLogin(robot.getRobotId(), robot.getPassword());
|
||||
robot.setToken(loginResult.getString("token"));
|
||||
robot.setSession(accountBusiness.getSession());
|
||||
}
|
||||
} else {
|
||||
log.debug("机器人 {} 执行常规登录", robot.getRobotId());
|
||||
//执行正常登录流程
|
||||
loginResult = accountBusiness.idPasswordLogin(robot.getRobotId(), robot.getPassword());
|
||||
robot.setToken(loginResult.getString("token"));
|
||||
robot.setSession(accountBusiness.getSession());
|
||||
}
|
||||
robot.setOnline(true);
|
||||
robot.setWanfaId(gameId);
|
||||
robot.setLastActiveTime(System.currentTimeMillis());
|
||||
|
||||
HashMap<String, String> robotMap = new HashMap<>();
|
||||
robotMap.put("acc", robot.getAccount());
|
||||
robotMap.put("nick", robot.getNickName());
|
||||
robotMap.put("portrait", robot.getPortrait());
|
||||
robotMap.put("password", robot.getPassword());
|
||||
jedis2.hmset("{robot}:" + robot.getRobotId(), robotMap);
|
||||
|
||||
//todo 将机器人信息存储到grobot键中,用于按group分类
|
||||
Map<String, String> gRobotMap = new HashMap<>();
|
||||
gRobotMap.put("start", "0");
|
||||
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);
|
||||
log.info("机器人{}登录成功,分配到玩法{}", robot.getRobotId(), gameId);
|
||||
|
||||
//连接对应游戏服务器
|
||||
RobotManagerInterface handler = getGameHandler(gameId);
|
||||
handler.connectRobot(robot);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("机器人登录时发生错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理不活跃的机器人连接
|
||||
* 添加游戏处理器
|
||||
*/
|
||||
private void cleanupInactiveRobots() {
|
||||
log.debug("开始清理不活跃的机器人连接...");
|
||||
public void addGameHandler(int gameId, RobotManagerInterface handler) {
|
||||
gameHandlers.put(gameId, handler);
|
||||
log.info("添加游戏处理器: gameId={}, handler={}", gameId, handler.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
//已连接的机器人
|
||||
for (RobotInfo robot : new ArrayList<>(connectedRobots.values())) {
|
||||
//检查机器人是否仍然连接到房间
|
||||
try {
|
||||
//检查房间状态
|
||||
try (Jedis jedis0 = Redis.use().getJedis()){
|
||||
String roomKey = robot.getCurrentRoomId();
|
||||
if (roomKey != null) {
|
||||
//检查房间是否存在或是否已结束
|
||||
String status = jedis0.hget(roomKey, "status");
|
||||
if (status != null) {
|
||||
int roomStatus = Integer.parseInt(status);
|
||||
//如果房间已结束或已删除 断开机器人连接
|
||||
if (roomStatus == 2 || roomStatus == 3) {
|
||||
log.info("房间 {} 已结束,断开机器人 {} 连接", roomKey, robot.getRobotId());
|
||||
disconnectRobot(robot);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取游戏处理器
|
||||
*/
|
||||
public RobotManagerInterface getGameHandler(int gameId) {
|
||||
return gameHandlers.get(gameId);
|
||||
}
|
||||
|
||||
//检查房间玩家列表 确认机器人是否仍在房间中
|
||||
String players = jedis0.hget(roomKey, "players");
|
||||
if (players != null && !players.equals("[]")) {
|
||||
String playersStr = players.substring(1, players.length() - 1);
|
||||
String[] playerIds = playersStr.split(",");
|
||||
boolean robotInRoom = false;
|
||||
/**
|
||||
* 定时任务
|
||||
*/
|
||||
private void startCleanupTask() {
|
||||
//每15秒检查一次玩法配置
|
||||
scheduler.scheduleAtFixedRate(this::manageWanfaPollers, 15, 15, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
for (String playerIdStr : playerIds) {
|
||||
int playerId = Integer.parseInt(playerIdStr.trim());
|
||||
if (playerId == robot.getRobotId()) {
|
||||
robotInRoom = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//如果机器人不在房间玩家列表中 断开连接
|
||||
if (!robotInRoom) {
|
||||
log.info("机器人 {} 不在房间 {} 断开连接", robot.getRobotId(), roomKey);
|
||||
disconnectRobot(robot);
|
||||
/**
|
||||
* 管理玩法轮询器
|
||||
*/
|
||||
private void manageWanfaPollers() {
|
||||
try (Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
|
||||
Set<String> playKeys = jedis11.keys("g{*}:play:*");
|
||||
|
||||
for (String playKey : playKeys) {
|
||||
try {
|
||||
String[] parts = playKey.split(":");
|
||||
if (parts.length >= 3) {
|
||||
String groupStr = parts[0];
|
||||
int groupId = Integer.parseInt(groupStr.substring(2, groupStr.length() - 1));
|
||||
int wanfaId = Integer.parseInt(parts[parts.length - 1]);
|
||||
|
||||
//检查是否配置了机器人
|
||||
int shangxianRobot = Integer.parseInt(jedis11.hget(playKey, "shangxian_robot"));
|
||||
int leftoverRobot = Integer.parseInt(jedis11.hget(playKey, "leftover_robot"));
|
||||
|
||||
if (shangxianRobot != 0 && leftoverRobot > 0) {
|
||||
RoomWanfaMatcher poller = getWanfaRoomPoller(groupId, wanfaId);
|
||||
if (!poller.isRunning()) {
|
||||
poller.startPolling();
|
||||
log.info("为玩法ID {} 启动房间轮询器", wanfaId);
|
||||
}
|
||||
} else {
|
||||
//如果房间玩家列表为空 但机器人连接到此房间 断开连接
|
||||
if (roomKey.equals(robot.getCurrentRoomId())) {
|
||||
log.info("房间 {} 玩家列表为空,断开机器人 {} 连接", roomKey, robot.getRobotId());
|
||||
disconnectRobot(robot);
|
||||
//如果没有配置机器人 停止轮询器
|
||||
RoomWanfaMatcher poller = wanfaRoomPollers.get(wanfaId);
|
||||
if (poller != null) {
|
||||
poller.stopPolling();
|
||||
log.info("为玩法ID {} 停止房间轮询器", wanfaId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
log.debug("无法解析玩法ID: {}", playKey);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("检查机器人 {} 连接状态时发生错误", robot.getRobotId(), e);
|
||||
}
|
||||
}
|
||||
log.debug("清理不活跃的机器人连接完成,当前连接机器人数量: {}", connectedRobots.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接机器人到指定房间
|
||||
*/
|
||||
public void connectRobotToRoom(RobotInfo robot, RoomInfo room) {
|
||||
RobotManagerInterface handler = getGameHandler(room.getWanfaId());
|
||||
if (handler == null) {
|
||||
log.warn("未找到处理玩法ID {} 的处理器", room.getWanfaId());
|
||||
return;
|
||||
}
|
||||
|
||||
//增加对应玩法的机器人使用计数
|
||||
increaseRobotUsageCount(room.getGroupId(), room.getWanfaId());
|
||||
log.info("机器人 {} 加入房间前,减少leftover_robot数量,群组={}, 玩法ID={}", robot.getRobotId(), room.getGroupId(), room.getWanfaId());
|
||||
|
||||
try {
|
||||
//通过处理器连接机器人
|
||||
handler.connectRobot(robot, room);
|
||||
connectedRobots.put(robot.getRobotId(), robot);
|
||||
} catch (Exception e) {
|
||||
log.error("连接机器人到房间时发生异常", e);
|
||||
robot.setConnected(false);
|
||||
//异常时回滚计数
|
||||
rollbackRobotCounts(room.getGroupId(), room.getWanfaId());
|
||||
log.error("管理玩法轮询器时发生错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 回滚机器人相关计数
|
||||
* 获取玩法房间轮询器
|
||||
*/
|
||||
private void rollbackRobotCounts(int groupId, int wanfaId) {
|
||||
//减少的机器人使用计数回滚
|
||||
decreaseRobotCount(wanfaId);
|
||||
//增加leftover_robot数量
|
||||
try (Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
|
||||
String playKey = "g{" + groupId + "}:play:" + wanfaId;
|
||||
jedis11.hincrBy(playKey, "leftover_robot", 1);
|
||||
log.info("回滚机器人计数,群组={}, 玩法ID={}", groupId, wanfaId);
|
||||
} catch (Exception e) {
|
||||
log.error("回滚leftover_robot计数时发生异常", e);
|
||||
}
|
||||
public RoomWanfaMatcher getWanfaRoomPoller(int groupId, int wanfaId) {
|
||||
return wanfaRoomPollers.computeIfAbsent(wanfaId, k -> {
|
||||
RoomWanfaMatcher poller = new RoomWanfaMatcher(this, groupId, wanfaId);
|
||||
log.info("创建玩法ID {} 的房间轮询器", wanfaId);
|
||||
return poller;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -261,9 +256,9 @@ public class RobotManager {
|
|||
*/
|
||||
public void disconnectRobot(RobotInfo robot) {
|
||||
int robotId = robot.getRobotId();
|
||||
int groupId = getGroupIdFromRoomId(robot.getCurrentRoomId());
|
||||
int gameId = robot.getCurrentWanfaId();
|
||||
String roomId = robot.getCurrentRoomId();
|
||||
int groupId = getGroupIdFromRoomId(robot.getRoomId());
|
||||
int gameId = robot.getWanfaId();
|
||||
String roomId = robot.getRoomId();
|
||||
|
||||
//断开机器人服务
|
||||
safeDisconnectRobot(robotId, groupId, gameId, roomId);
|
||||
|
|
@ -285,92 +280,17 @@ public class RobotManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* 获取可用机器人列表
|
||||
* 获取已登录的指定玩法的机器人
|
||||
*/
|
||||
public List<RobotInfo> getAvailableRobots(int count) {
|
||||
List<RobotInfo> availableRobots = new ArrayList<>();
|
||||
|
||||
try {
|
||||
//获取可用机器人信息
|
||||
String sql = String.format("SELECT id,acc,nick,portrait,password FROM `account` WHERE jiqiren=9998 and start = 0 LIMIT %d", count);
|
||||
ITArray robotArray = DataBase.use().executeQueryByTArray(sql);
|
||||
|
||||
for (int i = 0; i < robotArray.size() && i < count; i++) {
|
||||
ITObject robotObj = robotArray.getTObject(i);
|
||||
|
||||
RobotInfo robot = new RobotInfo();
|
||||
robot.setRobotId(robotObj.getInt("id"));
|
||||
robot.setAccount(robotObj.getString("acc"));
|
||||
robot.setNickName(robotObj.getString("nick"));
|
||||
robot.setPortrait(robotObj.getString("portrait"));
|
||||
robot.setPassword(robotObj.getString("password"));
|
||||
robot.setOnline(false);
|
||||
robot.setConnected(false);
|
||||
|
||||
availableRobots.add(robot);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取可用机器人列表时发生错误", e);
|
||||
} finally {
|
||||
//更新机器人状态为已使用
|
||||
if (!availableRobots.isEmpty()) {
|
||||
for (RobotInfo robot : availableRobots) {
|
||||
try {
|
||||
String sql = String.format("UPDATE `account` SET start = %d WHERE id = %d", 1, robot.getRobotId());
|
||||
DataBase.use().executeUpdate(sql);
|
||||
log.debug("机器人 {} 状态已更新为已使用", robot.getRobotId());
|
||||
} catch (Exception e) {
|
||||
log.error("更新机器人 {} 状态失败", robot.getRobotId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return availableRobots;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定玩法类型的房间匹配器
|
||||
*/
|
||||
public GameRoomMatcherInterface getGameRoomMatcher(int wanfaId) {
|
||||
return gameRoomMatchers.get(wanfaId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭机器人管理器
|
||||
*/
|
||||
public void shutdown() {
|
||||
//停止Redis监听
|
||||
if (redisRoomListener != null) {
|
||||
redisRoomListener.stopListening();
|
||||
}
|
||||
|
||||
//断开所有机器人连接
|
||||
public RobotInfo getLoggedInRobotForWanfa(int wanfaId) {
|
||||
for (RobotInfo robot : connectedRobots.values()) {
|
||||
disconnectRobot(robot);
|
||||
}
|
||||
|
||||
//恢复所有机器人状态为可用
|
||||
try {
|
||||
String sql = "UPDATE `account` SET start = 0 WHERE jiqiren = 9998";
|
||||
DataBase.use().executeUpdate(sql);
|
||||
log.info("所有机器人状态已重置为可用");
|
||||
} catch (Exception e) {
|
||||
log.error("重置机器人状态时发生错误", e);
|
||||
}
|
||||
|
||||
//关闭定时任务调度器
|
||||
try {
|
||||
scheduler.shutdown();
|
||||
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
if (robot.getWanfaId() == wanfaId && robot.isOnline() && robot.isConnected()) {
|
||||
//更新最后活跃时间
|
||||
robot.setLastActiveTime(System.currentTimeMillis());
|
||||
return robot;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
log.info("机器人管理器已关闭,断开了 {} 个机器人连接", connectedRobots.size());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -380,21 +300,6 @@ public class RobotManager {
|
|||
return robotManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加指定玩法ID的机器人使用计数
|
||||
*/
|
||||
public void increaseRobotUsageCount(int groupId, int wanfaId) {
|
||||
count.put(wanfaId, count.getOrDefault(wanfaId, 0) + 1);
|
||||
|
||||
try (Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
|
||||
String playKey = "g{" + groupId + "}:play:" + wanfaId;
|
||||
jedis11.hincrBy(playKey, "leftover_robot", -1);
|
||||
} catch (Exception e) {
|
||||
decreaseRobotCount(wanfaId);
|
||||
}
|
||||
log.debug("玩法ID {} 的机器人使用计数增加到: {}", wanfaId, count.get(wanfaId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少指定玩法ID的机器人使用计数
|
||||
*/
|
||||
|
|
@ -406,13 +311,6 @@ public class RobotManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定玩法ID的机器人使用计数
|
||||
*/
|
||||
public int getRobotUsageCount(int wanfaId) {
|
||||
return count.getOrDefault(wanfaId, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已连接的机器人
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import com.group.robot.info.RoomInfo;
|
|||
*/
|
||||
public interface RobotManagerInterface {
|
||||
/**
|
||||
* 连接机器人到房间
|
||||
* 连接机器人到游戏服务器
|
||||
*/
|
||||
void connectRobot(RobotInfo robot, RoomInfo room);
|
||||
void connectRobot(RobotInfo robot);
|
||||
|
||||
/**
|
||||
* 断开机器人连接
|
||||
|
|
|
|||
|
|
@ -1,451 +0,0 @@
|
|||
package com.group.robot.connect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.group.robot.RobotManager;
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.group.robot.info.RoomInfo;
|
||||
import com.taurus.core.entity.ITArray;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.plugin.database.DataBase;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
import com.taurus.core.plugin.redis.Redis;
|
||||
import com.group.robot.matcher.GameRoomMatcherInterface;
|
||||
|
||||
/**
|
||||
* Redis房间监听器 - 实时监听房间的游戏类型 触发对应游戏类型匹配器
|
||||
*/
|
||||
public class RedisRoomListener extends JedisPubSub {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RedisRoomListener.class);
|
||||
private final ExecutorService executorService = Executors.newFixedThreadPool(4);
|
||||
//机器人管理器
|
||||
private final RobotManager robotManager;
|
||||
|
||||
public RedisRoomListener(RobotManager robotManager) {
|
||||
this.robotManager = robotManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始监听房间变化
|
||||
*/
|
||||
public void startListening() {
|
||||
// 启动db0监听线程(房间变化)
|
||||
Thread db0ListenerThread = new Thread(() -> {
|
||||
Jedis jedis0 = Redis.use().getJedis(); // 默认db0
|
||||
try {
|
||||
log.info("开始监听db0的房间键空间变化...");
|
||||
|
||||
//订阅键空间通知 - db0中的房间变化
|
||||
//注意:Redis需要开启键空间通知:config set notify-keyspace-events Ex
|
||||
jedis0.psubscribe(this, "__keyspace@0__:room:*");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("监听db0房间变化时发生错误", e);
|
||||
} finally {
|
||||
if (jedis0 != null) {
|
||||
jedis0.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
db0ListenerThread.setDaemon(true);
|
||||
db0ListenerThread.setName("RedisRoomListener-db0");
|
||||
db0ListenerThread.start();
|
||||
|
||||
//启动db11监听线程(玩法配置变化)
|
||||
Thread db11ListenerThread = new Thread(() -> {
|
||||
Jedis jedis11 = Redis.use("group1_db11").getJedis();
|
||||
try {
|
||||
log.info("开始监听db11的玩法配置变化...");
|
||||
|
||||
//订阅键空间通知 - db11中的玩法配置变化
|
||||
//注意:需要订阅正确的模式
|
||||
jedis11.psubscribe(this, "__keyspace@11__:g{*}:play:*");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("监听db11玩法配置变化时发生错误", e);
|
||||
} finally {
|
||||
if (jedis11 != null) {
|
||||
jedis11.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
db11ListenerThread.setDaemon(true);
|
||||
db11ListenerThread.setName("RedisRoomListener-db11");
|
||||
db11ListenerThread.start();
|
||||
|
||||
log.info("Redis房间监听器已启动,正在监听db0的房间变化和db11的玩法配置变化");
|
||||
|
||||
//等待监听线程启动
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
if (db0ListenerThread.isAlive() && db11ListenerThread.isAlive()) {
|
||||
log.info("两个监听线程都已成功启动");
|
||||
System.out.println("Redis房间监听器已启动,正在监听db0的房间变化和db11的玩法配置变化");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String channel, String message) {
|
||||
log.debug("收到Redis频道消息: channel={}, message={}", channel, message);
|
||||
System.out.println("收到Redis频道消息: channel=" + channel + ", message=" + message);
|
||||
//根据订阅类型处理
|
||||
if (channel.startsWith("__keyspace@0__:room:")) {
|
||||
//处理房间人员进出或状态变化
|
||||
handleRoomEvent(channel, message);
|
||||
} else if (channel.startsWith("g{") && channel.contains("}:play:")) {
|
||||
//群组玩法配置变化事件
|
||||
handleGroupPlayChange(channel, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理房间变化事件
|
||||
*/
|
||||
private void handleRoomEvent(String channel, String message) {
|
||||
executorService.submit(() -> {
|
||||
try (Jedis jedis0 = Redis.use().getJedis(); Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
|
||||
//获取房间ID
|
||||
String roomId = getRedisChannelRoomId(channel);
|
||||
|
||||
int wanfaId = Integer.parseInt(jedis0.hget(roomId, "game"));
|
||||
int groupId = Integer.parseInt(jedis0.hget(roomId, "group"));
|
||||
int status = Integer.parseInt(jedis0.hget(roomId, "status"));
|
||||
int maxPlayers = Integer.parseInt(jedis0.hget(roomId, "maxPlayers"));
|
||||
|
||||
if (maxPlayers != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
//房间已结束或已删除
|
||||
if (status == 2 || status == 3) {
|
||||
String playersStr = jedis0.hget(roomId, "players");
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
//房间结束后 如果房间中有机器人 恢复剩余机器人数量
|
||||
restoreLeftoverRobotOnRoomEnd(roomId, groupId, wanfaId, playersStr, jedis11);
|
||||
|
||||
//房间结束后 立即检查是否需要创建新房间
|
||||
checkCreateRobotRoomTCP(wanfaId, groupId, jedis0, jedis11);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 匹配机器人机制 */
|
||||
//检查玩法配置中的机器人设置
|
||||
String playKey = "g{" + groupId + "}:play:" + wanfaId;
|
||||
int shangxianRobot = Integer.parseInt(jedis11.hget(playKey, "shangxian_robot"));
|
||||
|
||||
//玩法配置了机器人上限
|
||||
if (shangxianRobot > 0) {
|
||||
String playersStr = jedis0.hget(roomId, "players");
|
||||
|
||||
//房间中当前人数
|
||||
int currentPlayers = 0;
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
String playersClean = playersStr.substring(1, playersStr.length() - 1);
|
||||
if (!playersClean.isEmpty()) {
|
||||
String[] playerIds = playersClean.split(",");
|
||||
currentPlayers = playerIds.length;
|
||||
}
|
||||
}
|
||||
|
||||
//检查房间中是否已有机器人
|
||||
boolean hasRobot = hasRobotInRoom(roomId, jedis0);
|
||||
|
||||
//触发对应游戏类型的房间匹配器
|
||||
GameRoomMatcherInterface matcher = robotManager.getGameRoomMatcher(wanfaId);
|
||||
if (matcher != null && !hasRobot && currentPlayers < maxPlayers) {
|
||||
log.info("触发玩法ID {} 的房间匹配", wanfaId);
|
||||
|
||||
//获取玩法配置中的剩余机器人数量
|
||||
int leftoverRobot = Integer.parseInt(jedis11.hget(playKey, "leftover_robot"));
|
||||
if (leftoverRobot > 0) {
|
||||
int currentUsage = robotManager.getRobotUsageCount(wanfaId);
|
||||
//当前机器人使用数量小于上限
|
||||
if (currentUsage < shangxianRobot) {
|
||||
//获取可用机器人
|
||||
List<RobotInfo> availableRobots = robotManager.getAvailableRobots(1);
|
||||
if (!availableRobots.isEmpty()) {
|
||||
RobotInfo robot = availableRobots.get(0);
|
||||
|
||||
//创建房间信息对象
|
||||
RoomInfo roomInfo = new RoomInfo();
|
||||
roomInfo.setRoomId(roomId);
|
||||
roomInfo.setWanfaId(wanfaId);
|
||||
roomInfo.setGroupId(groupId);
|
||||
roomInfo.setCurrentPlayers(currentPlayers);
|
||||
roomInfo.setMaxPlayers(maxPlayers);
|
||||
roomInfo.setGame(String.valueOf(wanfaId));
|
||||
|
||||
//连接机器人到房间
|
||||
robotManager.connectRobotToRoom(robot, roomInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("玩法ID {} 房间已有机器人或房间已满", wanfaId);
|
||||
}
|
||||
} else {
|
||||
log.debug("玩法ID {} 没有配置机器人上限或上限为0 跳过处理", wanfaId);
|
||||
}
|
||||
|
||||
/* 对2人房间进行检查 当房间状态发生变化时 检查是否需要创建新房间 */
|
||||
checkCreateRobotRoomTCP(wanfaId, groupId, jedis0, jedis11);
|
||||
} catch (Exception e) {
|
||||
log.error("处理房间变化事件时发生错误", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理群组玩法配置变化
|
||||
*/
|
||||
private void handleGroupPlayChange(String channel, String message) {
|
||||
executorService.submit(() -> {
|
||||
try (Jedis jedis0 = Redis.use().getJedis(); Jedis jedis11 = Redis.use("group1_db11").getJedis()){
|
||||
log.info("监听到群组玩法配置变化: {}", channel);
|
||||
|
||||
int braceIndex = channel.indexOf('}');
|
||||
if (braceIndex > 1) {
|
||||
String groupIdStr = channel.substring(2, braceIndex);
|
||||
String remaining = channel.substring(braceIndex + 1);
|
||||
|
||||
if (remaining.startsWith(":play:") && remaining.length() > 6) {
|
||||
String wanfaIdStr = remaining.substring(6);
|
||||
int groupId = Integer.parseInt(groupIdStr);
|
||||
int wanfaId = Integer.parseInt(wanfaIdStr);
|
||||
|
||||
//当玩法配置发生变化时 立即检查是否需要创建房间
|
||||
checkCreateRobotRoomTCP(wanfaId, groupId, jedis0, jedis11);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理群组玩法配置变化时发生错误", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取房间ID
|
||||
*/
|
||||
private String getRedisChannelRoomId(String channel) {
|
||||
if (channel.startsWith("__keyspace@0__:room:")) {
|
||||
return "room:" + channel.substring("__keyspace@0__:room:".length());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止监听
|
||||
*/
|
||||
public void stopListening() {
|
||||
try {
|
||||
this.unsubscribe();
|
||||
executorService.shutdown();
|
||||
try {
|
||||
//等待现有任务完成
|
||||
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
executorService.shutdownNow();
|
||||
//再次等待
|
||||
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
log.error("线程池未能正常关闭");
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// 重新中断当前线程
|
||||
executorService.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
log.info("Redis房间监听器已停止");
|
||||
} catch (Exception e) {
|
||||
log.error("停止Redis房间监听器时发生错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查房间中是否已有机器人
|
||||
*/
|
||||
private boolean hasRobotInRoom(String roomId, Jedis jedis0) {
|
||||
String players = jedis0.hget(roomId, "players");
|
||||
Integer playerId = hasRobotInPlayerList(players);
|
||||
return playerId != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查玩家列表中是否包含机器人
|
||||
*/
|
||||
public static Integer hasRobotInPlayerList(String playersStr) {
|
||||
if (playersStr == null || playersStr.equals("[]")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String playersClean = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = playersClean.split(",");
|
||||
|
||||
for (String playerIdStr : playerIds) {
|
||||
try {
|
||||
int playerId = Integer.parseInt(playerIdStr.trim());
|
||||
//检查是否为机器人账户(jiqiren=9998)
|
||||
String checkSql = String.format("SELECT jiqiren FROM `account` WHERE id = %d", playerId);
|
||||
ITArray checkArray = DataBase.use().executeQueryByTArray(checkSql);
|
||||
|
||||
if (checkArray.size() > 0) {
|
||||
ITObject checkObj = checkArray.getTObject(0);
|
||||
int jiqiren = checkObj.getInt("jiqiren");
|
||||
if (jiqiren == 9998) { //是机器人
|
||||
return playerId;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("检查玩家是否为机器人时发生错误: {}", playerIdStr, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否需要为指定玩法和群组创建新房间 通过TCP服务
|
||||
*/
|
||||
private void checkCreateRobotRoomTCP(int wanfaId, int groupId, Jedis jedis0, Jedis jedis11) {
|
||||
try {
|
||||
//获取玩法配置中是否允许机器人创建房间
|
||||
String playKey = "g{" + groupId + "}:play:" + wanfaId;
|
||||
String leftoverRobotValue = jedis11.hget(playKey, "leftover_robot");
|
||||
String shangxianRobotValue = jedis11.hget(playKey, "shangxian_robot");
|
||||
|
||||
if (leftoverRobotValue == null || shangxianRobotValue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int leftoverRobot = Integer.parseInt(leftoverRobotValue);
|
||||
int shangxianRobot = Integer.parseInt(shangxianRobotValue);
|
||||
|
||||
//检查当前玩法的机器人使用数量
|
||||
int currentUsage = robotManager.getRobotUsageCount(wanfaId);
|
||||
if (leftoverRobot > 0 && currentUsage < shangxianRobot) {
|
||||
Set<String> roomIds = jedis0.keys("room:*");
|
||||
//有效房间数量
|
||||
int validRoomCount = 0;
|
||||
|
||||
for (String roomId : roomIds) {
|
||||
String groupValue = jedis0.hget(roomId, "group");
|
||||
String gameValue = jedis0.hget(roomId, "game");
|
||||
|
||||
if (groupValue == null || gameValue == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int roomGroup = Integer.parseInt(groupValue);
|
||||
int roomWanfa = Integer.parseInt(gameValue);
|
||||
|
||||
//检查玩法和群组是否匹配
|
||||
if (roomGroup == groupId && roomWanfa == wanfaId) {
|
||||
int status = Integer.parseInt(jedis0.hget(roomId, "status"));
|
||||
int maxPlayers = Integer.parseInt(jedis0.hget(roomId, "maxPlayers"));
|
||||
|
||||
//只考虑2人房间 未开始或进行中
|
||||
if (maxPlayers == 2 && status < 2) {
|
||||
String playersStr = jedis0.hget(roomId, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String playersClean = playersStr.substring(1, playersStr.length() - 1);
|
||||
int currentPlayers = 0;
|
||||
if (!playersClean.isEmpty()) {
|
||||
String[] playerIds = playersClean.split(",");
|
||||
currentPlayers = playerIds.length;
|
||||
}
|
||||
if (currentPlayers < maxPlayers) {
|
||||
validRoomCount++; //未满员的有效房间
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//如果没有有效房间(空房间或未满员房间)则通过TCP创建新房间
|
||||
if (validRoomCount == 0) {
|
||||
log.info("检测到群组 {} 和玩法ID {} 没有效房间,通过TCP创建房间: 剩余机器人={}, 当前使用={}, 上限={}",groupId, wanfaId, leftoverRobot, currentUsage, shangxianRobot);
|
||||
//通过TCP创建新房间
|
||||
createRoomForWanfaTCP(groupId, wanfaId, jedis11);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("检查是否需要通过TCP创建房间时发生错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过TCP服务为指定群组和玩法创建房间
|
||||
*/
|
||||
private void createRoomForWanfaTCP(int groupId, int wanfaId, Jedis jedis11) {
|
||||
//检查玩法配置中的机器人设置
|
||||
try {
|
||||
String playKey = "g{" + groupId + "}:play:" + wanfaId;
|
||||
String shangxianRobotValue = jedis11.hget(playKey, "shangxian_robot");
|
||||
|
||||
if (shangxianRobotValue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int shangxianRobot = Integer.parseInt(shangxianRobotValue);
|
||||
|
||||
if (shangxianRobot != 0) {
|
||||
int currentUsage = robotManager.getRobotUsageCount(wanfaId);
|
||||
|
||||
if (currentUsage < shangxianRobot) {
|
||||
RobotMgrTcpClient tcpClient = new RobotMgrTcpClient("127.0.0.1", 8701);
|
||||
|
||||
//获取可用机器人
|
||||
List<RobotInfo> availableRobots = robotManager.getAvailableRobots(1);
|
||||
if (!availableRobots.isEmpty()) {
|
||||
RobotInfo robot = availableRobots.get(0);
|
||||
|
||||
//TCP客户端连接到robot_mj_cs
|
||||
int attempts = 0;
|
||||
while (!tcpClient.isConnected() && attempts < 10) {
|
||||
Thread.sleep(100);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
//发送创建房间请求
|
||||
CompletableFuture<RoomInfo> future = tcpClient.sendCreateRoomForRobot(groupId, wanfaId, robot.getRobotId());
|
||||
|
||||
RoomInfo roomInfo = future.get();
|
||||
if (roomInfo != null) {
|
||||
log.info("收到创建房间{}响应:", roomInfo.getRoomId());
|
||||
robotManager.connectRobotToRoom(robot, roomInfo);
|
||||
log.info("成功为玩法ID {} 的房间 {} 添加机器人 {}", wanfaId, roomInfo.getRoomId(), robot.getRobotId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("玩法ID {} 已达到机器人使用上限: 当前={}, 上限={}", wanfaId, currentUsage, shangxianRobot);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("通过TCP为群组 {} 和玩法ID {} 创建房间时发生错误", groupId, wanfaId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 房间结束时恢复leftover_robot数量
|
||||
*/
|
||||
private void restoreLeftoverRobotOnRoomEnd(String roomId, int groupId, int wanfaId, String playersStr, Jedis jedis11) {
|
||||
Integer robotId = hasRobotInPlayerList(playersStr);
|
||||
if (robotId != null) {
|
||||
log.info("房间 {} 结束,检测到机器人 {},调用统一断开服务", roomId, robotId);
|
||||
//调用RobotManager的统一断开服务
|
||||
robotManager.safeDisconnectRobot(robotId, groupId, wanfaId, roomId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ public class RobotDisconnect {
|
|||
|
||||
//处理对应游戏处理器断开连接
|
||||
if (robot != null) {
|
||||
RobotManagerInterface handler = robotManager.getGameHandler(robot.getCurrentWanfaId());
|
||||
RobotManagerInterface handler = robotManager.getGameHandler(robot.getWanfaId());
|
||||
if (handler != null) {
|
||||
handler.disconnectRobot(robot);
|
||||
log.debug("游戏处理器已断开机器人 {} 连接", robotId);
|
||||
|
|
|
|||
|
|
@ -1,240 +0,0 @@
|
|||
package com.group.robot.connect;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.group.Protocol;
|
||||
import com.group.robot.info.RoomInfo;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.entity.TObject;
|
||||
import com.taurus.core.util.ICallback;
|
||||
import com.taurus.core.util.Logger;
|
||||
import taurus.client.MessageResponse;
|
||||
import taurus.client.NetManager;
|
||||
import taurus.client.TaurusClient;
|
||||
|
||||
/**
|
||||
* TCP客户端 - 与robot_mj_cs服务端通信
|
||||
*/
|
||||
public class RobotMgrTcpClient {
|
||||
|
||||
private Logger log = Logger.getLogger(RobotMgrTcpClient.class);
|
||||
private TaurusClient client;
|
||||
private volatile boolean isConnected = false;
|
||||
private volatile boolean isInitialized = false;
|
||||
private volatile boolean isLoginCompleted = false;
|
||||
private Thread eventThread;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param host 服务器主机地址
|
||||
* @param port 服务器端口
|
||||
*/
|
||||
public RobotMgrTcpClient(String host, int port) {
|
||||
try {
|
||||
//创建TCP客户端
|
||||
this.client = new TaurusClient(host + ":" + port, "10", TaurusClient.ConnectionProtocol.Tcp);
|
||||
|
||||
//启动网络事件处理线程
|
||||
startNetEventThread();
|
||||
|
||||
//连接到服务器 异步
|
||||
client.connect();
|
||||
|
||||
int attempts = 0;
|
||||
while (!client.isConnected() && attempts < 100) {
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
attempts++;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("等待连接建立时被中断: " + e.getMessage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//连接成功 发送握手协议
|
||||
if (client.isConnected()) {
|
||||
log.info("TCP连接已建立 发送握手协议");
|
||||
isConnected = true;
|
||||
isInitialized = true;
|
||||
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
//发送初始化协议 完成握手过程 防止服务端超时断开连接
|
||||
sendInitializationProtocol();
|
||||
|
||||
attempts = 0;
|
||||
while (!isLoginCompleted && attempts < 50) {
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
attempts++;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.error("等待握手完成被中断: " + e.getMessage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动网络事件处理线程
|
||||
*/
|
||||
private void startNetEventThread() {
|
||||
eventThread = new Thread(() -> {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
NetManager.processEvents();
|
||||
try {
|
||||
Thread.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
log.error("网络事件处理错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}, "RobotMgrTcpClient-NetEventThread");
|
||||
|
||||
eventThread.setDaemon(true);
|
||||
eventThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送初始化协议到robot_mj_cs服务器
|
||||
*/
|
||||
private void sendInitializationProtocol() {
|
||||
try {
|
||||
log.info("发送初始化协议到robot_mj_cs服务器");
|
||||
|
||||
//构建初始化参数
|
||||
ITObject params = TObject.newInstance();
|
||||
params.putString("type", "manager_connection");
|
||||
params.putString("client", "robot_mgr");
|
||||
|
||||
//发送初始化协议
|
||||
client.send("init_connection", params, new ICallback<MessageResponse>() {
|
||||
@Override
|
||||
public void action(MessageResponse response) {
|
||||
if (response.returnCode == 0) {
|
||||
isLoginCompleted = true;
|
||||
} else {
|
||||
isLoginCompleted = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
isLoginCompleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查连接状态
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return isConnected && isInitialized && isLoginCompleted && client != null && client.isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送创建房间协议到robot_mj_cs
|
||||
* @param groupId 群组ID
|
||||
* @param wanfaId 玩法ID
|
||||
* @return CompletableFuture<RoomInfo> 异步返回房间信息
|
||||
*/
|
||||
public CompletableFuture<RoomInfo> sendCreateRoomForRobot(int groupId, int wanfaId, int robotId) {
|
||||
CompletableFuture<RoomInfo> future = new CompletableFuture<>();
|
||||
|
||||
if (!isConnected()) {
|
||||
future.completeExceptionally(new RuntimeException("未连接到robot_mj_cs服务器"));
|
||||
return future;
|
||||
}
|
||||
|
||||
try {
|
||||
//构建请求参数
|
||||
ITObject params = TObject.newInstance();
|
||||
params.putInt("groupId", groupId);
|
||||
params.putInt("wanfaId", wanfaId);
|
||||
params.putInt("robotId", robotId);
|
||||
|
||||
//发送创建房间请求
|
||||
client.send(Protocol.CREATE_ROOM_FOR_ROBOT, params, new ICallback<MessageResponse>() {
|
||||
@Override
|
||||
public void action(MessageResponse response) {
|
||||
if (response.returnCode == 0 && response.messageData != null &&
|
||||
response.messageData.param != null) {
|
||||
//解析响应数据
|
||||
ITObject responseData = response.messageData.param;
|
||||
RoomInfo roomInfo = new RoomInfo();
|
||||
|
||||
//设置房间信息
|
||||
roomInfo.setRoomId(responseData.getString("roomKey"));
|
||||
roomInfo.setGroupId(responseData.getInt("groupId"));
|
||||
roomInfo.setWanfaId(responseData.getInt("wanfaId"));
|
||||
|
||||
//获取游戏服务器地址和端口
|
||||
if (responseData.containsKey("server_ip")) {
|
||||
roomInfo.setGameServerHost(responseData.getString("server_ip"));
|
||||
}
|
||||
if (responseData.containsKey("server_port")) {
|
||||
roomInfo.setGameServerPort(responseData.getInt("server_port"));
|
||||
}
|
||||
|
||||
future.complete(roomInfo);
|
||||
log.info("robot_mj_cs创建房间成功: " + roomInfo.getRoomId());
|
||||
} else {
|
||||
future.completeExceptionally(new RuntimeException("创建房间失败,错误码: " + response.returnCode));
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
System.err.println("发送创建房间协议时发生错误: " + e.getMessage());
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
//停止网络事件处理线程
|
||||
if (eventThread != null) {
|
||||
eventThread.interrupt();
|
||||
try {
|
||||
eventThread.join(2000);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("等待事件线程结束时被中断", e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
eventThread = null;
|
||||
}
|
||||
//关闭客户端连接
|
||||
if (client != null) {
|
||||
try {
|
||||
client.killConnection();
|
||||
log.debug("已关闭TCP客户端连接");
|
||||
} catch (Exception e) {
|
||||
log.warn("关闭TCP客户端连接时发生异常", e);
|
||||
} finally {
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
//重置状态
|
||||
isConnected = false;
|
||||
isInitialized = false;
|
||||
isLoginCompleted = false;
|
||||
log.info("RobotMgrTcpClient连接已关闭");
|
||||
} catch (Exception e) {
|
||||
log.error("关闭RobotMgrTcpClient时发生异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.group.robot.info.RoomInfo;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -17,17 +16,19 @@ public class MaJiangRobotHandler implements RobotManagerInterface {
|
|||
private final RobotConnectionHandler robotConnectionHandler;
|
||||
|
||||
public MaJiangRobotHandler() {
|
||||
this.robotConnectionHandler = new RobotConnectionHandler();
|
||||
this.robotConnectionHandler = RobotConnectionHandler.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectRobot(RobotInfo robot, RoomInfo room) {
|
||||
public void connectRobot(RobotInfo robot) {
|
||||
try {
|
||||
log.info("麻将机器人 {} 正在连接到房间 {}", robot.getRobotId(), room.getRoomId());
|
||||
//连接处理器进行连接
|
||||
robotConnectionHandler.connectRobot(robot, room);
|
||||
robotConnectionHandler.connectRobot(robot);
|
||||
|
||||
//设置机器人连接状态
|
||||
robot.setConnected(true);
|
||||
}catch (Exception e) {
|
||||
log.error("麻将机器人 {} 连接房间 {} 时发生异常", robot.getRobotId(), room.getRoomId(), e);
|
||||
log.error("麻将机器人 {} 连接游戏服务器时发生异常", robot.getRobotId(), e);
|
||||
robot.setConnected(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,9 +42,7 @@ public class MaJiangRobotHandler implements RobotManagerInterface {
|
|||
robotConnectionHandler.disconnectRobot(robot.getRobotId());
|
||||
|
||||
robot.setConnected(false);
|
||||
robot.setCurrentRoomId(null);
|
||||
robot.setCurrentWanfaId(0);
|
||||
|
||||
|
||||
log.info("麻将机器人 {} 连接已断开", robot.getRobotId());
|
||||
} catch (Exception e) {
|
||||
log.error("断开麻将机器人连接时发生错误: " + robot.getRobotId(), e);
|
||||
|
|
|
|||
|
|
@ -17,24 +17,21 @@ public class PokerRobotHandler implements RobotManagerInterface {
|
|||
private final RobotConnectionHandler connectionHandler;
|
||||
|
||||
public PokerRobotHandler() {
|
||||
this.connectionHandler = new RobotConnectionHandler();
|
||||
this.connectionHandler = RobotConnectionHandler.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectRobot(RobotInfo robot, RoomInfo room) {
|
||||
public void connectRobot(RobotInfo robot) {
|
||||
try {
|
||||
log.info("扑克机器人 {} 正在连接到房间 {}", robot.getRobotId(), room.getRoomId());
|
||||
log.info("扑克机器人 {} 正在连接到房间 {}", robot.getRobotId(), robot.getRoomId());
|
||||
|
||||
//使用连接处理器进行连接
|
||||
connectionHandler.connectRobot(robot, room);
|
||||
connectionHandler.connectRobot(robot);
|
||||
|
||||
// 设置机器人连接状态和房间信息
|
||||
robot.setConnected(true);
|
||||
robot.setCurrentWanfaId(room.getWanfaId());
|
||||
robot.setCurrentRoomId(room.getRoomId());
|
||||
|
||||
log.info("扑克机器人 {} 开始连接到房间 {}, 玩法ID: {}",
|
||||
robot.getRobotId(), room.getRoomId(), room.getWanfaId());
|
||||
|
||||
log.info("扑克机器人 {} 开始连接到房间 {}, 玩法ID: {}", robot.getRobotId(), robot.getRoomId(), robot.getWanfaId());
|
||||
} catch (Exception e) {
|
||||
log.error("扑克机器人连接失败: " + robot.getRobotId(), e);
|
||||
}
|
||||
|
|
@ -49,9 +46,6 @@ public class PokerRobotHandler implements RobotManagerInterface {
|
|||
connectionHandler.disconnectRobot(robot.getRobotId());
|
||||
|
||||
robot.setConnected(false);
|
||||
robot.setCurrentRoomId(null);
|
||||
robot.setCurrentWanfaId(0);
|
||||
|
||||
log.info("扑克机器人 {} 连接已断开", robot.getRobotId());
|
||||
} catch (Exception e) {
|
||||
log.error("断开扑克机器人连接时发生错误: " + robot.getRobotId(), e);
|
||||
|
|
|
|||
|
|
@ -1,37 +1,31 @@
|
|||
package com.group.robot.handler;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.group.robot.connect.RedisRoomListener;
|
||||
import com.group.Protocol;
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.group.robot.RobotManager;
|
||||
import com.group.robot.info.RoomInfo;
|
||||
import com.taurus.core.entity.ITArray;
|
||||
import com.group.robot.matcher.RoomWanfaMatcher;
|
||||
import com.taurus.core.entity.TObject;
|
||||
import com.taurus.core.plugin.database.DataBase;
|
||||
import com.taurus.core.util.ICallback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import taurus.client.MessageResponse;
|
||||
import taurus.client.SocketCode;
|
||||
import taurus.client.TaurusClient;
|
||||
import taurus.client.Message;
|
||||
import taurus.client.business.AccountBusiness;
|
||||
import taurus.client.business.GroupRoomBusiness;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.events.Event;
|
||||
import com.taurus.core.events.IEventListener;
|
||||
import com.taurus.core.plugin.redis.Redis;
|
||||
import com.taurus.core.util.StringUtil;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
/**
|
||||
* 机器人连接处理器 - 将机器人连接到游戏服务器并准备
|
||||
*/
|
||||
public class RobotConnectionHandler {
|
||||
private static volatile RobotConnectionHandler instance;
|
||||
private static final Logger log = LoggerFactory.getLogger(RobotConnectionHandler.class);
|
||||
|
||||
//机器人ID到客户端连接的映射
|
||||
|
|
@ -81,54 +75,44 @@ public class RobotConnectionHandler {
|
|||
public void setGameId(int gameId) { this.gameId = gameId; }
|
||||
}
|
||||
|
||||
public RobotConnectionHandler() {
|
||||
private RobotConnectionHandler() {
|
||||
this.robotManager = RobotManager.getRobotManager();
|
||||
}
|
||||
|
||||
public static RobotConnectionHandler getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (RobotConnectionHandler.class) {
|
||||
if (instance == null) {
|
||||
instance = new RobotConnectionHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接机器人到指定房间并准备
|
||||
* 连接机器人到游戏服务器
|
||||
*/
|
||||
public void connectRobot(RobotInfo robot, RoomInfo room) {
|
||||
public void connectRobot(RobotInfo robot) {
|
||||
//异步执行连接逻辑
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
log.info("开始连接机器人 {} 到房间 {}, 玩法ID: {}", robot.getRobotId(), room.getRoomId(), room.getWanfaId());
|
||||
|
||||
//获取机器人账户信息
|
||||
RobotAccountInfo accountInfo = getRobotAccountInfo(robot.getRobotId(), room.getGroupId());
|
||||
if (accountInfo == null) {
|
||||
log.error("无法获取机器人 {} 的账户信息", robot.getRobotId());
|
||||
return;
|
||||
}
|
||||
|
||||
//根据玩法ID获取服务器地址
|
||||
String serverAddress = getGameServerAddress(room.getWanfaId());
|
||||
//创建TCP客户端连接
|
||||
TaurusClient client = new TaurusClient(serverAddress, "game", TaurusClient.ConnectionProtocol.Tcp);
|
||||
log.info("开始连接机器人 {} 到游戏服务器,玩法ID: {}", robot.getRobotId(), robot.getWanfaId());
|
||||
//TCP客户端连接
|
||||
TaurusClient client = new TaurusClient(getGameServerAddress(robot.getWanfaId()), "game", TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.connect();
|
||||
|
||||
//保存客户端连接
|
||||
robotClients.put(robot.getRobotId(), client);
|
||||
|
||||
//设置事件监听器
|
||||
setupInitializationEventListeners(client, robot, room);
|
||||
setupInitializationEventListeners(client, robot);
|
||||
|
||||
//登录并加入房间
|
||||
Thread.sleep(5000);
|
||||
loginAndJoinRoom(accountInfo, room);
|
||||
|
||||
//登录成功后
|
||||
robotAccounts.put(robot.getRobotId(), accountInfo);
|
||||
|
||||
//发送准备请求
|
||||
Thread.sleep(1000);
|
||||
sendReadyRequest(client, accountInfo.getRobotId());
|
||||
log.info("机器人 {} 成功连接到房间 {}", robot.getRobotId(), room.getRoomId());
|
||||
|
||||
//6秒没有玩家加入 则退出房间
|
||||
readyTimeRobotExit(accountInfo.getRobotId(), room);
|
||||
//连接成功后发送初始化协议
|
||||
sendInitializationProtocol(client, robot);
|
||||
log.info("机器人 {} 成功连接到游戏服务器", robot.getRobotId());
|
||||
} catch (Exception e) {
|
||||
log.error("连接机器人时发生异常: " + robot.getRobotId(), e);
|
||||
log.error("连接机器人到游戏服务器时发生异常: " + robot.getRobotId(), e);
|
||||
//清理已经建立的连接
|
||||
disconnectRobot(robot.getRobotId());
|
||||
}
|
||||
|
|
@ -138,7 +122,7 @@ public class RobotConnectionHandler {
|
|||
/**
|
||||
* 设置初始化阶段的事件监听器
|
||||
*/
|
||||
private void setupInitializationEventListeners(TaurusClient client, RobotInfo robot, RoomInfo room) {
|
||||
private void setupInitializationEventListeners(TaurusClient client, RobotInfo robot) {
|
||||
//添加连接状态监听器
|
||||
client.addEventListener(TaurusClient.NetClientEvent.Connect, new IEventListener() {
|
||||
@Override
|
||||
|
|
@ -175,74 +159,6 @@ public class RobotConnectionHandler {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录并加入房间
|
||||
*/
|
||||
private void loginAndJoinRoom(RobotAccountInfo accountInfo, RoomInfo room) {
|
||||
try {
|
||||
//登录获取session和token
|
||||
AccountBusiness accountBusiness = new AccountBusiness();
|
||||
|
||||
try (Jedis jedis0 = Redis.use().getJedis()){
|
||||
//检查Redis中是否存在已有token
|
||||
Set<String> tokenKeys = jedis0.keys("{user}:" + accountInfo.getRobotId() + "_token");
|
||||
ITObject loginResult;
|
||||
|
||||
if (tokenKeys != null && !tokenKeys.isEmpty()) {
|
||||
log.debug("机器人 {} 存在已有token,直接使用", accountInfo.getRobotId());
|
||||
Set<String> tokenSet = jedis0.smembers("{user}:" + accountInfo.getRobotId() + "_token");
|
||||
List<String> tokenList = new ArrayList<>(tokenSet);
|
||||
|
||||
accountInfo.setSession("{user}:" + accountInfo.getRobotId());
|
||||
if (!tokenList.isEmpty()) {
|
||||
accountInfo.setToken(tokenList.get(0));
|
||||
} else {
|
||||
//如果没有token 则执行正常登录
|
||||
loginResult = accountBusiness.idPasswordLogin(accountInfo.getRobotId(), accountInfo.getPassword());
|
||||
accountInfo.setToken(loginResult.getString("token"));
|
||||
accountInfo.setSession(accountBusiness.getSession());
|
||||
}
|
||||
} else {
|
||||
log.debug("机器人 {} 执行常规登录", accountInfo.getRobotId());
|
||||
//执行正常登录流程
|
||||
loginResult = accountBusiness.idPasswordLogin(accountInfo.getRobotId(), accountInfo.getPassword());
|
||||
accountInfo.setToken(loginResult.getString("token"));
|
||||
accountInfo.setSession(accountBusiness.getSession());
|
||||
}
|
||||
}
|
||||
//加入房间
|
||||
GroupRoomBusiness.joinRoom(accountInfo.getGroupId(), room.getRoomId(), accountInfo.getSession(), null);
|
||||
log.info("机器人 {} 已成功加入房间 {}", accountInfo.getRobotId(), room.getRoomId());
|
||||
} catch (Exception e) {
|
||||
log.error("登录并加入房间时发生异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送准备请求
|
||||
*/
|
||||
private void sendReadyRequest(TaurusClient client, int robotId) {
|
||||
try {
|
||||
//获取机器人的账户信息以获取session和token
|
||||
RobotAccountInfo accountInfo = robotAccounts.get(robotId);
|
||||
if (accountInfo == null) {
|
||||
log.error("机器人 {} 的账户信息不存在,无法发送准备请求", robotId);
|
||||
return;
|
||||
}
|
||||
if (StringUtil.isEmpty(accountInfo.getSession()) || StringUtil.isEmpty(accountInfo.getToken())) {
|
||||
log.error("机器人 {} 的session或token为空,无法发送准备请求", robotId);
|
||||
return;
|
||||
}
|
||||
ITObject readyParam = new TObject();
|
||||
readyParam.putString("session", accountInfo.getSession() + "," + accountInfo.getToken());
|
||||
client.send("1003", readyParam, response -> {
|
||||
log.debug("机器人 {} 发送准备请求响应: {}", robotId, response);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("发送准备请求时发生异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据游戏ID获取服务器地址
|
||||
*/
|
||||
|
|
@ -250,11 +166,9 @@ public class RobotConnectionHandler {
|
|||
//根据玩法ID返回对应的服务器地址
|
||||
switch (wanfaId) {
|
||||
case 10: //长沙麻将
|
||||
return "127.0.0.1:6311";
|
||||
return "127.0.0.1:8701";
|
||||
case 22: //红中麻将
|
||||
return "8.138.242.190:6421";
|
||||
case 108: //转转麻将
|
||||
return "8.138.242.190:6841";
|
||||
case 66: //跑得快
|
||||
return "8.138.242.190:6841";
|
||||
default:
|
||||
|
|
@ -263,53 +177,6 @@ public class RobotConnectionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取机器人信息
|
||||
*/
|
||||
private RobotAccountInfo getRobotAccountInfo(int robotId, int groupId) {
|
||||
try {
|
||||
//获取机器人信息
|
||||
String sql = String.format("SELECT id,acc,nick,portrait,password FROM `account` WHERE id = %d", robotId);
|
||||
ITArray robotArray = DataBase.use().executeQueryByTArray(sql);
|
||||
|
||||
if (robotArray.size() == 0) {
|
||||
//数据库中没有 从Redis获取信息
|
||||
Jedis jedis = Redis.use("group1_db2").getJedis();
|
||||
try {
|
||||
Map<String, String> robotData = jedis.hgetAll("{robot}:" + robotId);
|
||||
if (robotData.isEmpty()) {
|
||||
log.error("未找到机器人ID {} 的信息", robotId);
|
||||
return null;
|
||||
}
|
||||
|
||||
String account = robotData.get("acc");
|
||||
String password = robotData.get("password");
|
||||
|
||||
if (StringUtil.isEmpty(account) || StringUtil.isEmpty(password)) {
|
||||
log.error("机器人 {} 的信息不完整", robotId);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RobotAccountInfo(robotId, account, password, groupId);
|
||||
} finally {
|
||||
jedis.close();
|
||||
}
|
||||
} else {
|
||||
//数据库获取信息
|
||||
ITObject robotObj = robotArray.getTObject(0);
|
||||
|
||||
int id = robotObj.getInt("id");
|
||||
String account = robotObj.getString("acc");
|
||||
String password = robotObj.getString("password");
|
||||
|
||||
return new RobotAccountInfo(id, account, password, groupId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取机器人账户时发生异常: " + robotId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开机器人连接
|
||||
*/
|
||||
|
|
@ -339,68 +206,128 @@ public class RobotConnectionHandler {
|
|||
/**
|
||||
* 超时检查 6秒没有玩家加入 则退出房间
|
||||
*/
|
||||
private void readyTimeRobotExit(int robotId, RoomInfo room) {
|
||||
public void readyTimeRobotExit(RobotInfo robot) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
Thread.sleep(6000);
|
||||
//检查房间内是否只有机器人
|
||||
if (ifExitRoom(room)) {
|
||||
log.info("机器人 {} 准备时间超过6秒且房间人数不足,退出房间", robotId);
|
||||
//获取客户端连接
|
||||
TaurusClient client = robotClients.remove(robotId);
|
||||
if (client != null) {
|
||||
//发送离开房间协议
|
||||
ITObject param = new TObject();
|
||||
client.send("1005", param, response -> {
|
||||
log.debug("机器人 {} 发送离开房间请求", robotId);
|
||||
});
|
||||
//关闭连接
|
||||
client.clearResponse();
|
||||
}
|
||||
//延迟后断开连接
|
||||
Thread.sleep(1000);
|
||||
disconnectRobot(robotId);
|
||||
log.info("机器人 {} 准备时间超过6秒且房间人数不足,退出房间", robot.getRobotId());
|
||||
TaurusClient client = robotClients.get(robot.getRobotId());
|
||||
|
||||
if (client != null && client.isConnected()) {
|
||||
//发送离开房间协议
|
||||
ITObject param = new TObject();
|
||||
client.send("1005", param, response -> {
|
||||
log.debug("机器人 {} 发送离开房间请求", robot.getRobotId());
|
||||
});
|
||||
} else {
|
||||
log.warn("机器人 {} 连接不存在或未激活,跳过离开房间操作", robot.getRobotId());
|
||||
}
|
||||
|
||||
//延迟后断开连接
|
||||
Thread.sleep(1000);
|
||||
disconnectRobot(robot.getRobotId());
|
||||
} catch (InterruptedException e) {
|
||||
log.debug("超时检查线程被中断: {}", robotId);
|
||||
log.debug("超时检查线程被中断: {}", robot.getRobotId());
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
log.error("超时检查过程中发生异常", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否退出房间
|
||||
* 发送初始化协议
|
||||
*/
|
||||
private boolean ifExitRoom(RoomInfo room) {
|
||||
try {
|
||||
Jedis jedis0 = Redis.use().getJedis();
|
||||
try {
|
||||
String players = jedis0.hget(room.getRoomId(), "players");
|
||||
if (players != null && !players.equals("[]")) {
|
||||
Integer robotInRoom = RedisRoomListener.hasRobotInPlayerList(players);
|
||||
|
||||
//计算房间总人数
|
||||
String playersClean = players.substring(1, players.length() - 1);
|
||||
String[] playerIds = playersClean.split(",");
|
||||
int totalPlayers = 0;
|
||||
for (String playerIdStr : playerIds) {
|
||||
playerIdStr = playerIdStr.trim();
|
||||
if (!playerIdStr.isEmpty()) {
|
||||
totalPlayers++;
|
||||
}
|
||||
}
|
||||
|
||||
//如果机器人在房间中 且房间总人数小于2人 则退出房间
|
||||
return robotInRoom != null && totalPlayers < 2;
|
||||
}
|
||||
} finally {
|
||||
jedis0.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("检查房间玩家数量时发生异常", e);
|
||||
private void sendInitializationProtocol(TaurusClient client, RobotInfo robot) {
|
||||
if (client == null || !client.isConnected()) {
|
||||
log.warn("机器人 {} 没有有效的TCP连接,无法发送初始化协议", robot.getRobotId());
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
|
||||
ITObject param = new TObject();
|
||||
param.putString("type", "manager_connection");
|
||||
param.putString("client", "robot_mgr");
|
||||
param.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
client.send("init_connection", param, response -> {
|
||||
if (response != null && response.returnCode == 0) {
|
||||
log.info("机器人 {} 初始化协议发送成功", robot.getRobotId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送准备消息给指定机器人
|
||||
*/
|
||||
public void sendReadyMessage(RobotInfo robot) {
|
||||
TaurusClient client = robotClients.get(robot.getRobotId());
|
||||
|
||||
if (client == null || !client.isConnected()) {
|
||||
log.warn("机器人 {} 没有有效的TCP连接,无法发送准备消息", robot.getRobotId());
|
||||
return;
|
||||
}
|
||||
|
||||
ITObject readyParam = new TObject();
|
||||
readyParam.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
client.send("1003", readyParam, response -> {
|
||||
log.debug("机器人 {} 发送准备请求响应: {}", robot.getRobotId(), response);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调接口
|
||||
*/
|
||||
public interface RoomCreatedCallback {
|
||||
void onRoomCreated(RobotInfo robot, int groupId, String roomId, int wanfaId);
|
||||
}
|
||||
|
||||
private RoomCreatedCallback roomCreatedCallback;
|
||||
|
||||
public void setRoomCreatedCallback(RoomCreatedCallback callback) {
|
||||
this.roomCreatedCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送创建房间请求
|
||||
*/
|
||||
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());
|
||||
robotClients.remove(robot.getRobotId());
|
||||
return;
|
||||
}
|
||||
|
||||
ITObject param = new TObject();
|
||||
param.putInt("groupId", groupId);
|
||||
param.putInt("wanfaId", wanfaId);
|
||||
param.putInt("robotId", robot.getRobotId());
|
||||
param.putString("session", robot.getSession() + "," + robot.getToken());
|
||||
client.send(Protocol.CREATE_ROOM_FOR_ROBOT, param, response -> {
|
||||
if (response != null && response.returnCode == 0) {
|
||||
ITObject responseData = response.messageData.param;
|
||||
String roomId = responseData.getString("roomKey");
|
||||
log.info("机器人 {} 成功创建房间 {}", robot.getRobotId(), roomId);
|
||||
if (roomCreatedCallback != null) {
|
||||
roomCreatedCallback.onRoomCreated(robot, groupId, roomId, wanfaId);
|
||||
}
|
||||
}
|
||||
});
|
||||
/*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));
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -12,9 +12,11 @@ public class RobotInfo {
|
|||
private boolean isOnline; //是否在线
|
||||
private boolean isConnected; //是否已连接到游戏服务器
|
||||
private boolean isConnecting; //是否正在连接
|
||||
private String currentRoomId; //当前所在房间ID
|
||||
private int currentWanfaId; //当前玩法ID
|
||||
private String roomId; //当前所在房间ID
|
||||
private int wanfaId; //当前玩法ID
|
||||
private long lastActiveTime; //最后活跃时间
|
||||
private String session;
|
||||
private String token;
|
||||
|
||||
public RobotInfo() {
|
||||
this.lastActiveTime = System.currentTimeMillis();
|
||||
|
|
@ -83,23 +85,23 @@ public class RobotInfo {
|
|||
public void setConnecting(boolean connecting) {
|
||||
isConnecting = connecting;
|
||||
}
|
||||
|
||||
public String getCurrentRoomId() {
|
||||
return currentRoomId;
|
||||
|
||||
public String getRoomId() {
|
||||
return roomId;
|
||||
}
|
||||
|
||||
public void setCurrentRoomId(String currentRoomId) {
|
||||
this.currentRoomId = currentRoomId;
|
||||
|
||||
public void setRoomId(String roomId) {
|
||||
this.roomId = roomId;
|
||||
}
|
||||
|
||||
public int getCurrentWanfaId() {
|
||||
return currentWanfaId;
|
||||
|
||||
public int getWanfaId() {
|
||||
return wanfaId;
|
||||
}
|
||||
|
||||
public void setCurrentWanfaId(int currentWanfaId) {
|
||||
this.currentWanfaId = currentWanfaId;
|
||||
|
||||
public void setWanfaId(int wanfaId) {
|
||||
this.wanfaId = wanfaId;
|
||||
}
|
||||
|
||||
|
||||
public long getLastActiveTime() {
|
||||
return lastActiveTime;
|
||||
}
|
||||
|
|
@ -107,7 +109,24 @@ public class RobotInfo {
|
|||
public void setLastActiveTime(long lastActiveTime) {
|
||||
this.lastActiveTime = lastActiveTime;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RobotInfo{" +
|
||||
|
|
@ -115,8 +134,11 @@ public class RobotInfo {
|
|||
", account='" + account + '\'' +
|
||||
", isOnline=" + isOnline +
|
||||
", isConnected=" + isConnected +
|
||||
", currentRoomId='" + currentRoomId + '\'' +
|
||||
", currentWanfaId=" + currentWanfaId +
|
||||
", roomId='" + roomId + '\'' +
|
||||
", wanfaId=" + wanfaId +
|
||||
", lastActiveTime=" + lastActiveTime +
|
||||
", session='" + session + '\'' +
|
||||
", token='" + token + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
package com.group.robot.matcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.group.robot.RobotManager;
|
||||
import com.group.robot.handler.RobotConnectionHandler;
|
||||
import com.group.robot.info.RobotInfo;
|
||||
import com.taurus.core.entity.ITArray;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.plugin.database.DataBase;
|
||||
import com.taurus.core.plugin.redis.Redis;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import taurus.client.business.GroupRoomBusiness;
|
||||
|
||||
/**
|
||||
* 玩法房间轮询器 - 按玩法定期查询房间
|
||||
*/
|
||||
public class RoomWanfaMatcher {
|
||||
private static final Logger log = LoggerFactory.getLogger(RoomWanfaMatcher.class);
|
||||
|
||||
private final RobotManager robotManager;
|
||||
private final int groupId;
|
||||
private final int wanfaId;
|
||||
private final Object lock = new Object();
|
||||
private volatile ScheduledExecutorService scheduler;
|
||||
private volatile boolean isRunning = false;
|
||||
//机器人连接处理器
|
||||
private final RobotConnectionHandler robotConnectionHandler;
|
||||
|
||||
public RoomWanfaMatcher(RobotManager robotManager, int groupId, int wanfaId) {
|
||||
this.robotManager = robotManager;
|
||||
this.groupId = groupId;
|
||||
this.wanfaId = wanfaId;
|
||||
this.scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
this.robotConnectionHandler = RobotConnectionHandler.getInstance();
|
||||
|
||||
//设置房间创建回调
|
||||
this.robotConnectionHandler.setRoomCreatedCallback(this::onRoomCreated);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动轮询
|
||||
*/
|
||||
public void startPolling() {
|
||||
synchronized(lock) {
|
||||
if (isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (scheduler == null || scheduler.isShutdown()) {
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
}
|
||||
|
||||
isRunning = true;
|
||||
log.info("开始为玩法ID {} 启动房间轮询", wanfaId);
|
||||
|
||||
//10秒轮询一次
|
||||
scheduler.scheduleWithFixedDelay(this::pollRooms, 0, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询房间
|
||||
*/
|
||||
private void pollRooms() {
|
||||
try {
|
||||
if (!isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (Jedis jedis0 = Redis.use().getJedis(); Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
|
||||
Set<String> roomIds = jedis0.keys("room:*");
|
||||
if (roomIds.isEmpty()) {
|
||||
createRobotWanfaRoomTCP(groupId, this.wanfaId);
|
||||
}
|
||||
|
||||
int groupId = -1;
|
||||
|
||||
for (String roomId : roomIds) {
|
||||
int wanfaId = Integer.parseInt(jedis0.hget(roomId, "gpid"));
|
||||
if (wanfaId == this.wanfaId) {
|
||||
groupId = Integer.parseInt(jedis0.hget(roomId, "group"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (groupId != -1) {
|
||||
//检查该玩法是否配置了机器人
|
||||
String playKey = "g{" + groupId + "}:play:" + this.wanfaId;
|
||||
int leftoverRobot = Integer.parseInt(jedis11.hget(playKey, "leftover_robot"));
|
||||
|
||||
if (leftoverRobot > 0) {
|
||||
//满人房间
|
||||
int fullRooms = 0;
|
||||
//所有房间
|
||||
int totalRooms = 0;
|
||||
List<String> roomsList = new ArrayList<>();
|
||||
|
||||
//统计所有2人房间
|
||||
for (String roomId : roomIds) {
|
||||
int currentWanfaId = Integer.parseInt(jedis0.hget(roomId, "gpid"));
|
||||
int status = Integer.parseInt(jedis0.hget(roomId, "status"));
|
||||
int maxPlayers = Integer.parseInt(jedis0.hget(roomId, "maxPlayers"));
|
||||
|
||||
//处理当前玩法maxPlayers为2的房间
|
||||
if (maxPlayers == 2 && currentWanfaId == this.wanfaId && status == 0) {
|
||||
totalRooms++;
|
||||
|
||||
String playersStr = jedis0.hget(roomId, "players");
|
||||
int currentPlayers = 0;
|
||||
if (!playersStr.equals("[]")) {
|
||||
String playersClean = playersStr.substring(1, playersStr.length() - 1);
|
||||
if (!playersClean.isEmpty()) {
|
||||
String[] playerIds = playersClean.split(",");
|
||||
currentPlayers = playerIds.length;
|
||||
}
|
||||
}
|
||||
if (currentPlayers == maxPlayers) {
|
||||
fullRooms++;
|
||||
} else {
|
||||
roomsList.add(roomId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//该玩法机器人房间满了 创建新房间
|
||||
if (fullRooms == totalRooms && totalRooms > 0) {
|
||||
createRobotWanfaRoomTCP(groupId, this.wanfaId);
|
||||
}
|
||||
|
||||
for (String roomId : roomsList) {
|
||||
int group = Integer.parseInt(jedis0.hget(roomId, "group"));
|
||||
int status = Integer.parseInt(jedis0.hget(roomId, "status"));
|
||||
|
||||
//处理未开始的陪打房间
|
||||
if (status == 0) {
|
||||
String playersStr = jedis0.hget(roomId, "players");
|
||||
|
||||
//房间没人 加入房间
|
||||
if (playersStr.equals("[]")) {
|
||||
robotJoinRoom(group, roomId, this.wanfaId, true);
|
||||
} else {
|
||||
//房间有人 不是机器人则加入房间
|
||||
Integer robotInRoom = playerIsRobotRedis(playersStr);
|
||||
if (robotInRoom == null) {
|
||||
robotJoinRoom(group, roomId, this.wanfaId, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) { // 捕获所有Throwable,包括Error
|
||||
log.error("轮询玩法ID {} 的房间时发生严重错误", wanfaId, t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 机器人加入房间
|
||||
* */
|
||||
private void robotJoinRoom(int group, String roomId, int wanfaId, boolean isRobot) {
|
||||
//检查调度器是否可用
|
||||
if (!scheduler.isShutdown()) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
RobotInfo 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) {
|
||||
log.error("机器人加入房间时发生错误: groupId={}, roomId={}, wanfaId={}, isRobot={}", group, roomId, wanfaId, isRobot, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过TCP服务为指定群组和玩法创建房间
|
||||
*/
|
||||
private void createRobotWanfaRoomTCP(int groupId, int wanfaId) {
|
||||
try {
|
||||
RobotInfo robot = robotManager.getLoggedInRobotForWanfa(wanfaId);
|
||||
if (robot == null) {
|
||||
log.warn("未能获取到玩法ID {} 的已登录机器人", wanfaId);
|
||||
return;
|
||||
}
|
||||
//使用机器人连接处理器发送创建房间请求
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查玩家列表中是否包含机器人
|
||||
*/
|
||||
public static Integer playerIsRobotRedis(String playersStr) {
|
||||
String playersClean = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = playersClean.split(",");
|
||||
|
||||
for (String playerIdStr : playerIds) {
|
||||
try {
|
||||
int playerId = Integer.parseInt(playerIdStr.trim());
|
||||
//检查是否为机器人账户(jiqiren=9998)
|
||||
String checkSql = String.format("SELECT jiqiren FROM `account` WHERE id = %d", playerId);
|
||||
ITArray checkArray = DataBase.use().executeQueryByTArray(checkSql);
|
||||
|
||||
if (checkArray.size() > 0) {
|
||||
ITObject checkObj = checkArray.getTObject(0);
|
||||
int jiqiren = checkObj.getInt("jiqiren");
|
||||
if (jiqiren == 9998) { //是机器人
|
||||
return playerId;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("检查玩家是否为机器人时发生错误: {}", playerIdStr, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止轮询
|
||||
*/
|
||||
public void stopPolling() {
|
||||
synchronized(lock) {
|
||||
isRunning = false;
|
||||
if (scheduler != null && !scheduler.isShutdown()) {
|
||||
scheduler.shutdown();
|
||||
try {
|
||||
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("玩法ID {} 的房间轮询已停止", wanfaId);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -75,27 +75,27 @@ public class RoomCreator {
|
|||
Map<String, String> roomMap = new HashMap<>();
|
||||
|
||||
//基础房间信息
|
||||
roomMap.put("id", newRoomId); //房间ID
|
||||
roomMap.put("owner", "{user}:" + robotId); //房间所有者
|
||||
roomMap.put("AA", "0"); //AA支付标志
|
||||
roomMap.put("pay", gameInfo.getOrDefault("pay", "0")); //支付金额
|
||||
roomMap.put("agent", "1"); //代理标志
|
||||
roomMap.put("group", String.valueOf(groupId)); //群组ID
|
||||
roomMap.put("gpid", String.valueOf(wanfaId)); //玩法ID
|
||||
roomMap.put("payer", String.valueOf(robotId)); //支付者ID
|
||||
roomMap.put("maxPlayers", gameInfo.getOrDefault("maxPlayers", "4")); //最大玩家数
|
||||
roomMap.put("times", gameInfo.getOrDefault("times", "8")); //局数
|
||||
roomMap.put("opt", playConfig.getOrDefault("opt", "1")); //选项
|
||||
roomMap.put("status", "0"); //房间状态
|
||||
roomMap.put("hpOnOff", playConfig.getOrDefault("hpOnOff", "0")); //体力开关
|
||||
roomMap.put("rewardType", playConfig.getOrDefault("rewardType", "0")); //奖励类型
|
||||
roomMap.put("rewardValueType", playConfig.getOrDefault("rewardValueType", "0")); //奖励值类型
|
||||
roomMap.put("xipai_rewardType", playConfig.getOrDefault("xipai_rewardType", "0")); //洗牌奖励类型
|
||||
roomMap.put("xipai_rewardValueType", playConfig.getOrDefault("xipai_rewardValueType", "0")); //洗牌奖励值类型
|
||||
roomMap.put("dismiss_time", "30"); //解散时间
|
||||
roomMap.put("kick_time", "60"); //踢出时间
|
||||
roomMap.put("hp_times", playConfig.getOrDefault("hp_times", "1")); //体力次数
|
||||
|
||||
roomMap.put("gpid", String.valueOf(wanfaId)); //玩法ID
|
||||
roomMap.put("group", String.valueOf(groupId)); //群组ID
|
||||
roomMap.put("hpOnOff", "1"); //体力开关
|
||||
roomMap.put("hp_times", "1000"); //体力次数
|
||||
roomMap.put("id", newRoomId); //房间ID
|
||||
roomMap.put("kick_time", "30"); //踢出时间
|
||||
roomMap.put("owner", "{user}:" + robotId); //房间所有者
|
||||
roomMap.put("maxPlayers", "2"); //最大玩家数
|
||||
roomMap.put("opt", "2"); //选项
|
||||
roomMap.put("pay", "0"); //支付金额
|
||||
roomMap.put("payer", String.valueOf(robotId)); //支付者ID
|
||||
roomMap.put("rewardType", "0"); //奖励类型
|
||||
roomMap.put("rewardValueType", "0"); //奖励值类型
|
||||
roomMap.put("status", "0"); //房间状态
|
||||
roomMap.put("times", "4"); //局数
|
||||
roomMap.put("xipai_rewardType", "3"); //洗牌奖励类型
|
||||
roomMap.put("xipai_rewardValueType", "1"); //洗牌奖励值类型
|
||||
|
||||
//如果有体力配置
|
||||
String hpConfig = playConfig.get("hpConfig");
|
||||
if (hpConfig != null) {
|
||||
|
|
@ -236,20 +236,24 @@ public class RoomCreator {
|
|||
String groupKey = "group:" + groupId;
|
||||
|
||||
Map<String, String> defaultGroupInfo = new HashMap<>();
|
||||
defaultGroupInfo.put("id", String.valueOf(groupId));
|
||||
defaultGroupInfo.put("name", "机器人专用群组-" + groupId);
|
||||
defaultGroupInfo.put("owner", "999999"); //使用机器人系统账户ID
|
||||
defaultGroupInfo.put("type", "1"); //普通群组类型
|
||||
defaultGroupInfo.put("pay_type", "1"); //房主支付
|
||||
defaultGroupInfo.put("opt", "1"); //开启状态
|
||||
defaultGroupInfo.put("ban", "0"); //未禁用
|
||||
defaultGroupInfo.put("dissolve_opt", "1"); //解散选项
|
||||
defaultGroupInfo.put("kick_opt", "1"); //踢人选项
|
||||
defaultGroupInfo.put("ban_apply", "0"); //不禁止申请
|
||||
defaultGroupInfo.put("ban_chat1", "false");
|
||||
defaultGroupInfo.put("ban_chat2", "false");
|
||||
defaultGroupInfo.put("create_time", String.valueOf(System.currentTimeMillis() / 1000));
|
||||
defaultGroupInfo.put("gms", "1"); //成员数
|
||||
defaultGroupInfo.put("dissolve_opt", "1"); //解散选项
|
||||
defaultGroupInfo.put("exit_opt", "0");
|
||||
defaultGroupInfo.put("gms", "19");
|
||||
defaultGroupInfo.put("id", String.valueOf(groupId));
|
||||
defaultGroupInfo.put("kick_opt", "1"); //踢人选项
|
||||
defaultGroupInfo.put("name", "机器人专用群组-" + groupId);
|
||||
defaultGroupInfo.put("notice", "");
|
||||
defaultGroupInfo.put("opt", "1"); //开启状态
|
||||
defaultGroupInfo.put("option", "0"); //选项
|
||||
|
||||
defaultGroupInfo.put("owner", "999999"); //使用机器人系统账户ID
|
||||
defaultGroupInfo.put("pay_type", "1"); //房主支付
|
||||
defaultGroupInfo.put("type", "2"); //普通群组类型
|
||||
|
||||
jedis11.hmset(groupKey, defaultGroupInfo);
|
||||
|
||||
log.info("成功创建默认群组信息,键名: {}", groupKey);
|
||||
|
|
|
|||
Loading…
Reference in New Issue