Merge remote-tracking branch 'origin/master'
commit
f086ed23e1
|
|
@ -25,7 +25,26 @@
|
|||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!-- -->
|
||||
<!-- <build>-->
|
||||
<!-- <finalName>robot</finalName>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||
<!-- <version>3.6.1</version>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <!– <compilerArgument>-parameters</compilerArgument> –>-->
|
||||
<!-- <source>1.8</source>-->
|
||||
<!-- <target>1.8</target>-->
|
||||
<!-- <encoding>UTF-8</encoding>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
|
||||
<!-- </plugins>-->
|
||||
<!-- </build>-->
|
||||
|
||||
|
||||
<build>
|
||||
<finalName>robot</finalName>
|
||||
<plugins>
|
||||
|
|
@ -41,7 +60,29 @@
|
|||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>robot.mj.EXMainServer</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ public class Config {
|
|||
/** Web组加入房间协议 */
|
||||
public static final String WEB_GROUP_JOIN_ROOM = "225";
|
||||
|
||||
public static final String WEB_GROUP_JOIN_ROOM11 = "285";
|
||||
|
||||
|
||||
/** Web组主动重连协议 */
|
||||
public static final String WEB_GROUP_ACTIVE_RECONNECT = "226";
|
||||
|
||||
|
|
@ -37,10 +40,10 @@ public class Config {
|
|||
/*public static final String GAME_SERVER_HOST = "8.134.76.43";
|
||||
public static final String DEFAULT_GROUP_ID = "762479";*/
|
||||
public static final String DEFAULT_GROUP_ID = "426149";
|
||||
public static final String GAME_SERVER_HOST = "127.0.0.1";
|
||||
public static final String GAME_SERVER_HOST = "8.138.162.178";
|
||||
|
||||
/** 游戏服务器端口 */
|
||||
public static final String GAME_SERVER_PORT = "6421";
|
||||
public static final String GAME_SERVER_PORT = "16421";
|
||||
|
||||
/** 默认密码 */
|
||||
public static final String DEFAULT_PASSWORD = "123456";
|
||||
|
|
@ -48,5 +51,13 @@ public class Config {
|
|||
/** 默认PID */
|
||||
public static final String DEFAULT_PID = "22";
|
||||
|
||||
/**
|
||||
* 机器人HTTP服务端口(接收 web_group 通过 HTTP 发送的 225 协议)
|
||||
* 规则:TCP端口 + 1000(TCP=8722,HTTP=9722)
|
||||
*/
|
||||
public static final int HTTP_SERVER_PORT = 9722;
|
||||
|
||||
/** 机器人HTTP服务路径 */
|
||||
public static final String HTTP_PATH_JOIN_ROOM = "/robot/joinRoom";
|
||||
|
||||
}
|
||||
|
|
@ -229,15 +229,43 @@ public class EXGameController extends GameController {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 接收来自web_group的加入房间协议
|
||||
* 接收来自web_group的加入房间协议(TCP 入口,保留原有行为)
|
||||
* 核心逻辑已提取到 processWebGroupJoin,供 HTTP 入口复用
|
||||
*/
|
||||
@ActionKey(value = Config.WEB_GROUP_JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
|
||||
public void webGroup(Session session, ITObject params, int gid) {
|
||||
int robotId = params.getInt("robotid");
|
||||
String roomId = params.getString("roomid");
|
||||
int groupId = params.getInt("groupid");
|
||||
|
||||
|
||||
ITObject result = processWebGroupJoin(robotId, roomId, groupId, params);
|
||||
|
||||
// 仅在"ID冲突"场景下回错误响应,其他场景保持原有静默行为不变
|
||||
int code = result.containsKey("code") ? result.getInt("code") : 0;
|
||||
if (code == 1) {
|
||||
ITObject errorResponse = TObject.newInstance();
|
||||
errorResponse.putString("status", "failed");
|
||||
errorResponse.putString("message", result.containsKey("message") ? result.getString("message") : "处理失败");
|
||||
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 web_group 加入房间请求 - 核心逻辑(与传输方式无关)
|
||||
* 供 TCP 入口(webGroup)和 HTTP 入口(RobotHttpServer)共用
|
||||
*
|
||||
* @param robotId 机器人ID
|
||||
* @param roomId 房间ID
|
||||
* @param groupId 群组ID
|
||||
* @param params 原始参数
|
||||
* @return ITObject 处理结果,包含:
|
||||
* code (0=成功, 1=ID冲突需告知调用方, 2=不同机器人冲突静默忽略)
|
||||
* message (描述信息)
|
||||
*/
|
||||
public ITObject processWebGroupJoin(int robotId, String roomId, int groupId, ITObject params) {
|
||||
ITObject result = TObject.newInstance();
|
||||
String lockKey = "room_lock:" + roomId;
|
||||
synchronized (lockKey.intern()) {
|
||||
if (checkRobotInRoomRedis(roomId, String.valueOf(robotId))) {
|
||||
|
|
@ -249,11 +277,9 @@ public class EXGameController extends GameController {
|
|||
} else {
|
||||
if (isPlayerIdConflictInRoom(roomId, robotId)) {
|
||||
log.warn("检测到机器人{"+robotId+"}与房间{"+roomId+"}中的真人玩家 ID 冲突,拒绝加入");
|
||||
ITObject errorResponse = TObject.newInstance();
|
||||
errorResponse.putString("status", "failed");
|
||||
errorResponse.putString("message", "机器人 ID 与房间内玩家冲突");
|
||||
MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
return;
|
||||
result.putInt("code", 1);
|
||||
result.putString("message", "机器人 ID 与房间内玩家冲突");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -281,7 +307,9 @@ public class EXGameController extends GameController {
|
|||
if (robotId != existingRobotId) {
|
||||
//不同机器人的冲突
|
||||
log.warn("房间{"+roomId+"}中Redis已存在机器人{"+existingRobotId+"},当前机器人{"+robotId+"}不执行加入逻辑");
|
||||
return;
|
||||
result.putInt("code", 2);
|
||||
result.putString("message", "Redis已存在其他机器人,不执行加入逻辑");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -291,8 +319,76 @@ public class EXGameController extends GameController {
|
|||
joinRoomCommon(robotId, roomId, groupId, params);
|
||||
log.info("225 已进入房间准备成功:room:{"+roomId+"} robot:{"+robotId+"}");
|
||||
}
|
||||
result.putInt("code", 0);
|
||||
result.putString("message", "success");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * 接收来自web_group的加入房间协议
|
||||
// */
|
||||
// @ActionKey(value = Config.WEB_GROUP_JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
|
||||
// public void webGroup(Session session, ITObject params, int gid) {
|
||||
// int robotId = params.getInt("robotid");
|
||||
// String roomId = params.getString("roomid");
|
||||
// int groupId = params.getInt("groupid");
|
||||
//
|
||||
// String lockKey = "room_lock:" + roomId;
|
||||
// synchronized (lockKey.intern()) {
|
||||
// if (checkRobotInRoomRedis(roomId, String.valueOf(robotId))) {
|
||||
// log.info("机器人{"+robotId+"}已在房间{"+roomId+"}中(Redis 中存在),直接允许加入");
|
||||
// } else {
|
||||
// RobotUser existingRobotUser = getRobotRoomInfo(String.valueOf(robotId));
|
||||
// if (existingRobotUser != null && existingRobotUser.getCurrentRoomId() == Integer.parseInt(roomId)) {
|
||||
// log.info("机器人{"+robotId+"}已在房间{"+roomId+"}中(本地映射存在),直接允许加入");
|
||||
// } else {
|
||||
// if (isPlayerIdConflictInRoom(roomId, robotId)) {
|
||||
// log.warn("检测到机器人{"+robotId+"}与房间{"+roomId+"}中的真人玩家 ID 冲突,拒绝加入");
|
||||
// ITObject errorResponse = TObject.newInstance();
|
||||
// errorResponse.putString("status", "failed");
|
||||
// errorResponse.putString("message", "机器人 ID 与房间内玩家冲突");
|
||||
// MainServer.instance.sendResponse(gid, 1, errorResponse, session);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //检查Redis中该房间是否真的包含当前机器人
|
||||
// if (!checkRobotInRoomRedis(roomId, String.valueOf(robotId))) {
|
||||
// //Redis中不存在该机器人 清理本地可能的错误映射
|
||||
// List<RobotUser> robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId));
|
||||
// if (!robotUsers.isEmpty()) {
|
||||
// synchronized (robotUsers) {
|
||||
// RobotUser robotUser = robotUsers.get(0);
|
||||
// log.warn("房间{"+roomId+"}中Redis未找到机器人{"+robotId+"},但本地映射存在{"+robotUser.getRobotId()+"},清理本地映射");
|
||||
// robotRoomMapping.remove(robotUser.getConnecId());
|
||||
// robotRoomMapping.remove(robotUser.getRobotId());
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// //Redis中存在该机器人 检查是否是不同机器人的冲突
|
||||
// List<RobotUser> robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId));
|
||||
// if (!robotUsers.isEmpty()) {
|
||||
// synchronized (robotUsers) {
|
||||
// RobotUser robotUser = robotUsers.get(0);
|
||||
// int existingRobotId = Integer.parseInt(robotUser.getRobotId());
|
||||
//
|
||||
// if (robotId != existingRobotId) {
|
||||
// //不同机器人的冲突
|
||||
// log.warn("房间{"+roomId+"}中Redis已存在机器人{"+existingRobotId+"},当前机器人{"+robotId+"}不执行加入逻辑");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// log.info("225 开始进房间:room:{"+roomId+"} robot:{"+robotId+"}");
|
||||
// //加入房间
|
||||
// joinRoomCommon(robotId, roomId, groupId, params);
|
||||
// log.info("225 已进入房间准备成功:room:{"+roomId+"} robot:{"+robotId+"}");
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 接收来自web_group的主动重连协议
|
||||
*/
|
||||
|
|
@ -416,6 +512,8 @@ public class EXGameController extends GameController {
|
|||
//成功响应后才建立映射关系
|
||||
synchronized (robotRoomMapping) {
|
||||
robotRoomMapping.put(robotUser.getConnecId(), robotUser);
|
||||
robotConnectionManager.reconnectToGameServer(response, robotUser, client);
|
||||
|
||||
}
|
||||
|
||||
log.info("机器人{"+robotId+"}已成功加入房间{"+roomId+"},建立映射关系");
|
||||
|
|
|
|||
|
|
@ -17,19 +17,28 @@ import taurus.client.NetManager;
|
|||
|
||||
import static robot.mj.EXGameController.robotRoomMapping;
|
||||
|
||||
/**
|
||||
* 红中麻将机器人主服务器
|
||||
* TCP服务端接收robot_mgr的协议 同时作为客户端连接game_mj_cs处理AI逻辑
|
||||
*/
|
||||
|
||||
public class EXMainServer extends MainServer{
|
||||
private static final Logger log = LoggerFactory.getLogger(EXMainServer.class);
|
||||
|
||||
private static final RobotConnectionManager robotConnectionManager = new RobotConnectionManager();
|
||||
|
||||
/** 机器人HTTP服务(接收 web_group 通过 HTTP 发送的 225 协议,替代TCP异步方式) */
|
||||
private RobotHttpServer robotHttpServer;
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
// 启动机器人HTTP服务(接收 web_group 通过 HTTP 发送的 225 协议)
|
||||
// 替代原 TCP 异步多线程方式(TaurusClient+CompletableFuture),降低CPU占用
|
||||
try {
|
||||
robotHttpServer = new RobotHttpServer();
|
||||
robotHttpServer.start(Config.HTTP_SERVER_PORT);
|
||||
} catch (Exception e) {
|
||||
log.error("启动 RobotHttpServer 失败,端口:" + Config.HTTP_SERVER_PORT, e);
|
||||
}
|
||||
|
||||
//JVM关闭钩子
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
log.info("收到JVM关闭信号,开始优雅关闭...");
|
||||
|
|
@ -163,6 +172,12 @@ public class EXMainServer extends MainServer{
|
|||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// 停止机器人HTTP服务
|
||||
if (robotHttpServer != null) {
|
||||
robotHttpServer.stop();
|
||||
robotHttpServer = null;
|
||||
}
|
||||
|
||||
log.info("红中麻将机器人服务器已停止");
|
||||
}
|
||||
}
|
||||
|
|
@ -8,8 +8,8 @@ import com.taurus.core.events.Event;
|
|||
import com.taurus.core.events.IEventListener;
|
||||
import com.taurus.core.plugin.redis.Redis;
|
||||
import com.taurus.core.util.ICallback;
|
||||
import com.taurus.core.util.Logger;
|
||||
import com.taurus.core.util.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import robot.mj.business.AccountBusiness;
|
||||
import robot.mj.handler.HuNanHongZhong;
|
||||
|
|
@ -20,6 +20,7 @@ import taurus.client.TaurusClient;
|
|||
import taurus.client.SocketCode;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import taurus.util.ROBOTEventType;
|
||||
import com.taurus.core.util.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
|
@ -31,8 +32,9 @@ import static robot.mj.thread.ThreadPoolConfig.scheduleDelay;
|
|||
* 机器人连接管理器 - 管理与游戏服务器的连接
|
||||
*/
|
||||
public class RobotConnectionManager {
|
||||
private static final Logger log = Logger.getLogger(RobotConnectionManager.class);
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RobotConnectionManager.class);
|
||||
// private static final Logger log = LoggerFactory.getLogger(RobotConnectionManager.class);
|
||||
private static final Map<String, HuNanHongZhong> huNanHongZhongInstances = new ConcurrentHashMap<>();
|
||||
|
||||
//记录活跃连接 用于资源清理判断
|
||||
|
|
@ -45,8 +47,8 @@ public class RobotConnectionManager {
|
|||
private static final long MAX_CONNECTION_LIFETIME = 5 * 60 * 1000;
|
||||
private final EXGameController exGameController;
|
||||
|
||||
private final String host= Config.GAME_SERVER_HOST;
|
||||
private final int port= Integer.parseInt(Config.GAME_SERVER_PORT);
|
||||
private final String host = Config.GAME_SERVER_HOST;
|
||||
private final int port = Integer.parseInt(Config.GAME_SERVER_PORT);
|
||||
|
||||
public RobotConnectionManager() {
|
||||
exGameController = new EXGameController();
|
||||
|
|
@ -69,7 +71,7 @@ public class RobotConnectionManager {
|
|||
}
|
||||
|
||||
HuNanHongZhong newInstance = new HuNanHongZhong();
|
||||
|
||||
|
||||
//从Redis恢复状态
|
||||
boolean restored = newInstance.restoreFromRedis(connecId);
|
||||
if (restored) {
|
||||
|
|
@ -77,7 +79,7 @@ public class RobotConnectionManager {
|
|||
} else {
|
||||
log.info("创建新的HuNanHongZhong实例: " + connecId);
|
||||
}
|
||||
|
||||
|
||||
huNanHongZhongInstances.put(connecId, newInstance);
|
||||
log.info("当前HuNanHongZhong实例总数: " + huNanHongZhongInstances.size());
|
||||
return newInstance;
|
||||
|
|
@ -103,7 +105,7 @@ public class RobotConnectionManager {
|
|||
|
||||
//创建Taurus客户端
|
||||
TaurusClient client = new TaurusClient(host + ":" + port, clientId, TaurusClient.ConnectionProtocol.Tcp);
|
||||
|
||||
|
||||
//设置事件监听器
|
||||
setupEventListeners(client, connecId);
|
||||
|
||||
|
|
@ -204,18 +206,18 @@ public class RobotConnectionManager {
|
|||
try {
|
||||
//获取 msg
|
||||
Message message = (Message) event.getParameter("msg");
|
||||
|
||||
|
||||
ITObject param = message.param;
|
||||
//回调协议号
|
||||
String command = message.command;
|
||||
|
||||
log.info("收到游戏协议 " + command);
|
||||
//根据玩法 ID 处理不同的回调
|
||||
if (StringUtil.isNotEmpty(command)) {
|
||||
//直接处理协议
|
||||
handleProtocol(command, message, client, connecId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理游戏协议时发生异常:connecId: {}, command: {}", connecId, ((Message)event.getParameter("msg")).command, e);
|
||||
log.error("处理游戏协议时发生异常:connecId: {}, command: {}", connecId, ((Message) event.getParameter("msg")).command, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -243,14 +245,14 @@ public class RobotConnectionManager {
|
|||
* 机器人断线重连
|
||||
*/
|
||||
public void reconnectToGameServer(MessageResponse response, RobotUser robotUser, TaurusClient client) {
|
||||
String connecId = robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId();
|
||||
String connecId = robotUser.getCurrentRoomId() + "_" + robotUser.getRobotId();
|
||||
//先设置机器人状态为准备状态
|
||||
robotUser.setStatus(ROBOTEventType.ROBOT_INTOROOM_READY);
|
||||
|
||||
if(client.isConnected()){
|
||||
|
||||
if (client.isConnected()) {
|
||||
try {
|
||||
log.info(String.valueOf(response.messageData.param));
|
||||
if (response.messageData.param==null) {
|
||||
if (response.messageData.param == null) {
|
||||
log.info("警告:reconnectToGameServer 重连时未获取到参数");
|
||||
return;
|
||||
}
|
||||
|
|
@ -363,10 +365,10 @@ public class RobotConnectionManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
} finally {
|
||||
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
renconnect(robotUser);
|
||||
}
|
||||
}
|
||||
|
|
@ -376,326 +378,321 @@ public class RobotConnectionManager {
|
|||
*/
|
||||
private void handleProtocol(String command, Message message, TaurusClient client, String connecId) {
|
||||
RobotUser robotUser = robotRoomMapping.get(connecId);
|
||||
log.info("connecId " + connecId);
|
||||
|
||||
//更新连接的最后访问时间
|
||||
EXGameController.updateLastAccessTime(connecId);
|
||||
|
||||
if (robotUser == null) {
|
||||
log.info("未找到机器人用户信息,连接ID: " + connecId);
|
||||
return;
|
||||
for (Map.Entry<String, RobotUser> entry : robotRoomMapping.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
RobotUser user = entry.getValue();
|
||||
log.info("Key" + key);
|
||||
log.info("user seat" + user.getSeat());
|
||||
log.info("user connecId" + user.getConnecId());
|
||||
log.info("user robotId" + user.getRobotId());
|
||||
|
||||
log.info("robotRoomMapping " + robotRoomMapping);
|
||||
}
|
||||
|
||||
int robotId = Integer.parseInt(robotUser.getRobotId());
|
||||
ITObject param = message.param;
|
||||
HuNanHongZhong huNanHongZhong = getHuNanHongZhongInstance(connecId);
|
||||
Jedis jedis0 = Redis.use().getJedis();
|
||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||
try {
|
||||
//红中麻将 机器人处理事件
|
||||
//初始化手牌
|
||||
if ("811".equalsIgnoreCase(command)) {
|
||||
robotUser.setStatus(ROBOTEventType.ROBOT_INTOROOM_WORKING);
|
||||
huNanHongZhong.cardInHead(command, message, client);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
//更新连接的最后访问时间
|
||||
EXGameController.updateLastAccessTime(connecId);
|
||||
|
||||
if (robotUser == null) {
|
||||
log.info("未找到机器人用户信息,连接ID: " + connecId);
|
||||
return;
|
||||
}
|
||||
//出牌广播
|
||||
else if ("812".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.drawCard(command, message);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//摸牌
|
||||
else if ("819".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.getCard(command, message);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//出牌,牌权
|
||||
else if ("813".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.outCard(client);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//结算
|
||||
else if ("817".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.getHongZhongCardInhand().clear();
|
||||
huNanHongZhong.getChuGuoCardInhand().clear();
|
||||
log.info("红中结算");
|
||||
Integer type = param.getInt("type");
|
||||
if (type == 1 || type == 2) { //为1为大结算 为2为解散
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
||||
|
||||
//游戏结束后主动断开连接
|
||||
disconnectFromGameServer(connecId);
|
||||
|
||||
int robotId = Integer.parseInt(robotUser.getRobotId());
|
||||
ITObject param = message.param;
|
||||
HuNanHongZhong huNanHongZhong = getHuNanHongZhongInstance(connecId);
|
||||
Jedis jedis0 = Redis.use().getJedis();
|
||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||
try {
|
||||
//红中麻将 机器人处理事件
|
||||
//初始化手牌
|
||||
if ("811".equalsIgnoreCase(command)) {
|
||||
robotUser.setStatus(ROBOTEventType.ROBOT_INTOROOM_WORKING);
|
||||
huNanHongZhong.cardInHead(command, message, client);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
ITObject params = TObject.newInstance();
|
||||
params.putString("session", client.getSession());
|
||||
client.send("1003", params, new ICallback<MessageResponse>() {
|
||||
@Override
|
||||
public void action(MessageResponse messageResponse) {
|
||||
//出牌广播
|
||||
else if ("812".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.drawCard(command, message);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//摸牌
|
||||
else if ("819".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.getCard(command, message, robotUser);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//出牌,牌权
|
||||
else if ("813".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.outCard(client);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//结算
|
||||
else if ("817".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.getHongZhongCardInhand().clear();
|
||||
huNanHongZhong.getChuGuoCardInhand().clear();
|
||||
log.info("红中结算");
|
||||
Integer type = param.getInt("type");
|
||||
if (type == 1 || type == 2) { //为1为大结算 为2为解散
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
||||
|
||||
//游戏结束后主动断开连接
|
||||
disconnectFromGameServer(connecId);
|
||||
}
|
||||
});
|
||||
}
|
||||
//杠碰胡通知协议
|
||||
else if ("814".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.actionCard(param, client);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
} else if ("820".equalsIgnoreCase(command)) {
|
||||
HuNanHongZhong.changePlayer(command, message);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//服务器通知客户端有玩家执行了操作
|
||||
else if ("815".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.shanchuchuguopai(param);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//玩家加入房间
|
||||
else if ("2001".equalsIgnoreCase(command)) {
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = Redis.use().getJedis();
|
||||
try {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
ITObject params = TObject.newInstance();
|
||||
params.putString("session", client.getSession());
|
||||
client.send("1003", params, new ICallback<MessageResponse>() {
|
||||
@Override
|
||||
public void action(MessageResponse messageResponse) {
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget("room:"+roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
log.info("2002发送退出房间协议1005,robotId: {"+robotId+"}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理玩家加入房间检查时发生异常", e);
|
||||
} finally {
|
||||
//确保Jedis连接关闭
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
log.info("玩家{"+ robotUser.getCurrentRoomId()+"}加入房间:"+ param);
|
||||
}
|
||||
//玩家退出房间也要检查
|
||||
else if ("2002".equalsIgnoreCase(command)) {
|
||||
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = Redis.use().getJedis();
|
||||
try {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget("room:"+roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
log.info("2002发送退出房间协议1005,robotId: {"+robotId+"}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理玩家退出房间检查时发生异常");
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
}
|
||||
//玩家解散房间
|
||||
else if ("2005".equalsIgnoreCase(command)) {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
log.info("2005玩家发送解散房间协议,robotId: {"+robotId+"}");
|
||||
}
|
||||
//解散房间时候恢复机器人账号可以使用
|
||||
else if ("2008".equalsIgnoreCase(command)) {
|
||||
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
||||
disconnectFromGameServer(connecId);
|
||||
}
|
||||
else if ("2009".equalsIgnoreCase(command)) {
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = null;
|
||||
try {
|
||||
jedis = Redis.use().getJedis();
|
||||
Integer paramRobotId = param.getInt("aid");
|
||||
if (robotUser != null && paramRobotId != null) {
|
||||
});
|
||||
}
|
||||
//杠碰胡通知协议
|
||||
else if ("814".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.actionCard(param, client);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
} else if ("820".equalsIgnoreCase(command)) {
|
||||
HuNanHongZhong.changePlayer(command, message);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//服务器通知客户端有玩家执行了操作
|
||||
else if ("815".equalsIgnoreCase(command)) {
|
||||
huNanHongZhong.shanchuchuguopai(param);
|
||||
//处理完协议后保存到Redis
|
||||
HuNanHongZhong currentInstance = huNanHongZhongInstances.get(connecId);
|
||||
currentInstance.saveToRedis(connecId);
|
||||
}
|
||||
//玩家加入房间
|
||||
else if ("2001".equalsIgnoreCase(command)) {
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = Redis.use().getJedis();
|
||||
try {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget(roomKey, "players");
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
String playersStr = jedis.hget("room:" + roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == paramRobotId) {
|
||||
if (playerId == robotId) {
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(paramRobotId));
|
||||
//断开连接
|
||||
disconnectFromGameServer(connecId);
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(paramRobotId);
|
||||
log.info("2009发送退出房间协议1005,robotId: {"+paramRobotId+"}");
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
log.info("2002发送退出房间协议1005,robotId: {" + robotId + "}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理玩家加入房间检查时发生异常", e);
|
||||
} finally {
|
||||
//确保Jedis连接关闭
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("2009协议数字格式异常,robotId: " + param.get("aid") + ", connecId: " + connecId);
|
||||
} catch (NullPointerException e) {
|
||||
log.error("2009协议空指针异常,connecId: " + connecId);
|
||||
} catch (Exception e) {
|
||||
log.error("2009协议处理异常: " + e.getMessage() + ", connecId: " + connecId);
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
log.info("玩家{" + robotUser.getCurrentRoomId() + "}加入房间:" + param);
|
||||
}
|
||||
//玩家退出房间也要检查
|
||||
else if ("2002".equalsIgnoreCase(command)) {
|
||||
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = Redis.use().getJedis();
|
||||
try {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget("room:" + roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
log.info("2002发送退出房间协议1005,robotId: {" + robotId + "}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理玩家退出房间检查时发生异常");
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
}
|
||||
//玩家解散房间
|
||||
else if ("2005".equalsIgnoreCase(command)) {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
log.info("2005玩家发送解散房间协议,robotId: {" + robotId + "}");
|
||||
}
|
||||
//解散房间时候恢复机器人账号可以使用
|
||||
else if ("2008".equalsIgnoreCase(command)) {
|
||||
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
||||
disconnectFromGameServer(connecId);
|
||||
} else if ("2009".equalsIgnoreCase(command)) {
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = null;
|
||||
try {
|
||||
jedis = Redis.use().getJedis();
|
||||
Integer paramRobotId = param.getInt("aid");
|
||||
if (robotUser != null && paramRobotId != null) {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget(roomKey, "players");
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == paramRobotId) {
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(paramRobotId));
|
||||
//断开连接
|
||||
disconnectFromGameServer(connecId);
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(paramRobotId);
|
||||
log.info("2009发送退出房间协议1005,robotId: {" + paramRobotId + "}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("2009协议数字格式异常,robotId: " + param.get("aid") + ", connecId: " + connecId);
|
||||
} catch (NullPointerException e) {
|
||||
log.error("2009协议空指针异常,connecId: " + connecId);
|
||||
} catch (Exception e) {
|
||||
log.error("2009协议处理异常: " + e.getMessage() + ", connecId: " + connecId);
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理接收到的游戏协议异常");
|
||||
} finally {
|
||||
jedis0.close();
|
||||
jedis2.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加leftover_robot数量 机器人退出房间
|
||||
*/
|
||||
private void updateLeftoverRobot ( int robotId){
|
||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||
try {
|
||||
|
||||
jedis2.hset("gallrobot", String.valueOf(robotId), "0");
|
||||
|
||||
jedis2.hset("{grobot}:" + robotId, "start", "0");
|
||||
|
||||
log.info("机器人 {" + robotId + "} 退出房间,修改gallrobot为0");
|
||||
} finally {
|
||||
jedis2.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 机器人登录
|
||||
*/
|
||||
public void login (RobotUser robotUser){
|
||||
log.info("开始机器人登录,robotId: {" + robotUser.getRobotId() + "}");
|
||||
ITObject object = null;
|
||||
AccountBusiness accountBusiness = null;
|
||||
accountBusiness = new AccountBusiness();
|
||||
try {
|
||||
//先快速登录
|
||||
object = accountBusiness.fastLogin(Integer.parseInt(robotUser.getRobotId()));
|
||||
log.info("机器人登录成功,robotId: {" + robotUser.getRobotId() + "}");
|
||||
if (object == null) {
|
||||
object = accountBusiness.idPasswordLogin(Integer.parseInt(robotUser.getRobotId()), robotUser.getPassword());
|
||||
}
|
||||
ITObject finalObject = object;
|
||||
CompletableFuture.runAsync(() -> {
|
||||
if (finalObject != null) {
|
||||
//判断是否有房间
|
||||
if (finalObject.getTObject("account") != null) {
|
||||
ITObject validate = TObject.newInstance();
|
||||
validate.putString("token", finalObject.getString("token"));
|
||||
robotUser.setToken(finalObject.getString("token"));
|
||||
;
|
||||
robotUser.setLoginsession("{user}:" + robotUser.getRobotId());
|
||||
if (robotUser.getLoginsession() != null) {
|
||||
robotUser.setIsLogin(true);
|
||||
}
|
||||
if (finalObject.getTObject("account").get("roomid") != null) {
|
||||
String roomid = finalObject.getTObject("account").get("roomid").toString();
|
||||
robotUser.setCurrentRoomId(Integer.parseInt(roomid));
|
||||
connectGame(robotUser);
|
||||
|
||||
robotUser.setConnecId(robotUser.getCurrentRoomId() + "_" + robotUser.getRobotId());
|
||||
log.info("重启获取的机器人还有当前房间,准备加入: " + robotUser.getConnecId());
|
||||
exGameController.webGroupJoinRoom(robotUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("机器人登录异常");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理接收到的游戏协议异常");
|
||||
} finally {
|
||||
jedis0.close();
|
||||
jedis2.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加leftover_robot数量 机器人退出房间
|
||||
*/
|
||||
private void updateLeftoverRobot(int robotId) {
|
||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||
try {
|
||||
|
||||
jedis2.hset("gallrobot", String.valueOf(robotId), "0");
|
||||
|
||||
jedis2.hset("{grobot}:" + robotId, "start", "0");
|
||||
|
||||
log.info("机器人 {"+robotId+"} 退出房间,修改gallrobot为0");
|
||||
} finally {
|
||||
jedis2.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 机器人登录
|
||||
*/
|
||||
public void login(RobotUser robotUser){
|
||||
log.info("开始机器人登录,robotId: {"+robotUser.getRobotId()+"}");
|
||||
ITObject object = null;
|
||||
AccountBusiness accountBusiness = null;
|
||||
accountBusiness = new AccountBusiness();
|
||||
try {
|
||||
//先快速登录
|
||||
object = accountBusiness.fastLogin(Integer.parseInt(robotUser.getRobotId()));
|
||||
log.info("机器人登录成功,robotId: {"+robotUser.getRobotId()+"}");
|
||||
if(object==null){
|
||||
object = accountBusiness.idPasswordLogin(Integer.parseInt(robotUser.getRobotId()), robotUser.getPassword());
|
||||
}
|
||||
ITObject finalObject = object;
|
||||
CompletableFuture.runAsync(() -> {
|
||||
if (finalObject != null) {
|
||||
//判断是否有房间
|
||||
if(finalObject.getTObject("account")!=null){
|
||||
ITObject validate = TObject.newInstance();
|
||||
validate.putString("token", finalObject.getString("token"));
|
||||
robotUser.setToken(finalObject.getString("token"));;
|
||||
robotUser.setLoginsession("{user}:"+robotUser.getRobotId());
|
||||
if (robotUser.getLoginsession() != null) {
|
||||
robotUser.setIsLogin(true);
|
||||
}
|
||||
if(finalObject.getTObject("account").get("roomid")!=null){
|
||||
String roomid = finalObject.getTObject("account").get("roomid").toString();
|
||||
robotUser.setCurrentRoomId(Integer.parseInt(roomid));
|
||||
connectGame(robotUser);
|
||||
|
||||
robotUser.setConnecId(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId());
|
||||
log.info("重启获取的机器人还有当前房间,准备加入: "+robotUser.getConnecId());
|
||||
exGameController.webGroupJoinRoom(robotUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("机器人登录异常");
|
||||
}
|
||||
}
|
||||
|
||||
public void connectGame(RobotUser robotUser){
|
||||
if(robotUser.isLogin){
|
||||
if(robotUser.getClient()==null){
|
||||
TaurusClient client = new TaurusClient(robotUser.getGameHost()+":"+robotUser.getGamePort(), "hz"+robotUser.getRobotId(), TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.setSession(robotUser.getLoginsession());
|
||||
client.connect();
|
||||
setupEventListeners(client, robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId());
|
||||
robotUser.setIsconnect(client.isConnected());
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("连接超时异常");
|
||||
}
|
||||
robotUser.setClient(client);
|
||||
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
|
||||
}else{
|
||||
log.info("机器人已连接,准备加入房间");
|
||||
log.info("client.isConnected()"+robotUser.getClient().isConnected());
|
||||
if(robotUser.getClient().isConnected()){
|
||||
robotUser.setIsconnect(true);
|
||||
}else{
|
||||
log.info("reconnect"+robotUser.getClient().getGameID());
|
||||
TaurusClient client = new TaurusClient(robotUser.getGameHost()+":"+robotUser.getGamePort(), "hz"+robotUser.getRobotId(), TaurusClient.ConnectionProtocol.Tcp);
|
||||
public void connectGame (RobotUser robotUser){
|
||||
if (robotUser.isLogin) {
|
||||
if (robotUser.getClient() == null) {
|
||||
TaurusClient client = new TaurusClient(robotUser.getGameHost() + ":" + robotUser.getGamePort(), "hz" + robotUser.getRobotId(), TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.setSession(robotUser.getLoginsession());
|
||||
client.connect();
|
||||
setupEventListeners(client, robotUser.getCurrentRoomId() + "_" + robotUser.getRobotId());
|
||||
robotUser.setIsconnect(client.isConnected());
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
|
|
@ -703,44 +700,62 @@ public class RobotConnectionManager {
|
|||
log.error("连接超时异常");
|
||||
}
|
||||
robotUser.setClient(client);
|
||||
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
|
||||
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId() + "_" + robotUser.getRobotId(), robotUser);
|
||||
} else {
|
||||
log.info("机器人已连接,准备加入房间");
|
||||
log.info("client.isConnected()" + robotUser.getClient().isConnected());
|
||||
if (robotUser.getClient().isConnected()) {
|
||||
robotUser.setIsconnect(true);
|
||||
} else {
|
||||
log.info("reconnect" + robotUser.getClient().getGameID());
|
||||
TaurusClient client = new TaurusClient(robotUser.getGameHost() + ":" + robotUser.getGamePort(), "hz" + robotUser.getRobotId(), TaurusClient.ConnectionProtocol.Tcp);
|
||||
client.setSession(robotUser.getLoginsession());
|
||||
client.connect();
|
||||
robotUser.setIsconnect(client.isConnected());
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("连接超时异常");
|
||||
}
|
||||
robotUser.setClient(client);
|
||||
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId() + "_" + robotUser.getRobotId(), robotUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重连
|
||||
*/
|
||||
public void renconnect(RobotUser robotUser){
|
||||
TaurusClient client = robotUser.getClient();
|
||||
if(client!=null){
|
||||
if(client.isConnected()){
|
||||
client.connect();
|
||||
robotUser.setIsconnect(client.isConnected());
|
||||
/**
|
||||
* 重连
|
||||
*/
|
||||
public void renconnect (RobotUser robotUser){
|
||||
TaurusClient client = robotUser.getClient();
|
||||
if (client != null) {
|
||||
if (client.isConnected()) {
|
||||
client.connect();
|
||||
robotUser.setIsconnect(client.isConnected());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据connecId获取游戏服务器连接
|
||||
*/
|
||||
public TaurusClient getGameClient(String connecId) {
|
||||
return robotRoomMapping.get(connecId) != null ? robotRoomMapping.get(connecId).getClient() : null;
|
||||
}
|
||||
|
||||
|
||||
public int getTime(){
|
||||
return Integer.parseInt((System.currentTimeMillis() + "").substring(0, 10));
|
||||
}
|
||||
|
||||
public static void sleepTime(int time) {
|
||||
try {
|
||||
//添加延迟
|
||||
Thread.sleep(time);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("连接超时异常");
|
||||
/**
|
||||
* 根据connecId获取游戏服务器连接
|
||||
*/
|
||||
public TaurusClient getGameClient (String connecId){
|
||||
return robotRoomMapping.get(connecId) != null ? robotRoomMapping.get(connecId).getClient() : null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getTime () {
|
||||
return Integer.parseInt((System.currentTimeMillis() + "").substring(0, 10));
|
||||
}
|
||||
|
||||
public static void sleepTime ( int time){
|
||||
try {
|
||||
//添加延迟
|
||||
Thread.sleep(time);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("连接超时异常");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
package robot.mj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.entity.TObject;
|
||||
import com.taurus.core.util.Logger;
|
||||
import com.robot.Global;
|
||||
|
||||
|
||||
public class RobotHttpServer {
|
||||
private static final Logger log = Logger.getLogger(RobotHttpServer.class);
|
||||
|
||||
/** 工作线程数(同时处理的并发请求数) */
|
||||
private static final int WORKER_THREADS = 8;
|
||||
|
||||
/** HTTP 响应超时(用于优雅关闭,秒) */
|
||||
private static final int STOP_DELAY = 2;
|
||||
|
||||
private HttpServer server;
|
||||
private ExecutorService executor;
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
/**
|
||||
* 启动 HTTP 服务
|
||||
* @param port 监听端口
|
||||
* @throws IOException 端口被占用等异常
|
||||
*/
|
||||
public void start(int port) throws IOException {
|
||||
server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||
server.createContext(Config.HTTP_PATH_JOIN_ROOM, new JoinRoomHandler());
|
||||
executor = Executors.newFixedThreadPool(WORKER_THREADS);
|
||||
server.setExecutor(executor);
|
||||
server.start();
|
||||
log.info("RobotHttpServer已启动,监听端口:" + port + ",路径:" + Config.HTTP_PATH_JOIN_ROOM + ",工作线程:" + WORKER_THREADS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止 HTTP 服务
|
||||
*/
|
||||
public void stop() {
|
||||
if (server != null) {
|
||||
server.stop(STOP_DELAY);
|
||||
server = null;
|
||||
}
|
||||
if (executor != null) {
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(STOP_DELAY, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
executor = null;
|
||||
}
|
||||
log.info("RobotHttpServer已停止");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 /robot/joinRoom 请求的 Handler
|
||||
*/
|
||||
private class JoinRoomHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
// 仅接受 POST
|
||||
if (!"POST".equalsIgnoreCase(exchange.getRequestMethod())) {
|
||||
writeJsonResponse(exchange, 405, buildErrorResponse("Method Not Allowed", "只支持POST请求"));
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> respData = new HashMap<>();
|
||||
try {
|
||||
// 读取请求体
|
||||
String body = readRequestBody(exchange);
|
||||
log.info("HTTP 收到加入房间请求:" + body);
|
||||
|
||||
// 解析 JSON
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> data = gson.fromJson(body, Map.class);
|
||||
if (data == null) {
|
||||
writeJsonResponse(exchange, 400, buildErrorResponse("Bad Request", "请求体为空或非合法JSON"));
|
||||
return;
|
||||
}
|
||||
|
||||
Number robotIdNum = (Number) data.get("robotid");
|
||||
Object roomIdObj = data.get("roomid");
|
||||
Number groupIdNum = (Number) data.get("groupid");
|
||||
|
||||
if (robotIdNum == null || roomIdObj == null || groupIdNum == null) {
|
||||
writeJsonResponse(exchange, 400, buildErrorResponse("Bad Request", "缺少必要参数 robotid/roomid/groupid"));
|
||||
return;
|
||||
}
|
||||
|
||||
int robotId = robotIdNum.intValue();
|
||||
String roomId = String.valueOf(roomIdObj);
|
||||
int groupId = groupIdNum.intValue();
|
||||
|
||||
// 构造 ITObject 参数(与原 TCP 入参保持一致)
|
||||
ITObject params = TObject.newInstance();
|
||||
params.putInt("robotid", robotId);
|
||||
params.putString("roomid", roomId);
|
||||
params.putInt("groupid", groupId);
|
||||
|
||||
// 调用公共处理逻辑(与 TCP webGroup 方法共用)
|
||||
ITObject result = ((EXGameController) Global.gameCtr).processWebGroupJoin(robotId, roomId, groupId, params);
|
||||
|
||||
int code = result.containsKey("code") ? result.getInt("code") : 0;
|
||||
String message = result.containsKey("message") ? result.getString("message") : "success";
|
||||
respData.put("code", code);
|
||||
respData.put("message", message);
|
||||
} catch (Exception e) {
|
||||
log.error("HTTP处理加入房间请求异常", e);
|
||||
respData.put("code", 500);
|
||||
respData.put("message", "服务器内部错误: " + e.getMessage());
|
||||
}
|
||||
|
||||
writeJsonResponse(exchange, 200, respData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取请求体为字符串
|
||||
*/
|
||||
private String readRequestBody(HttpExchange exchange) throws IOException {
|
||||
InputStream in = exchange.getRequestBody();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[1024];
|
||||
int n;
|
||||
while ((n = in.read(buf)) > 0) {
|
||||
baos.write(buf, 0, n);
|
||||
}
|
||||
in.close();
|
||||
return new String(baos.toByteArray(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 JSON 响应
|
||||
*/
|
||||
private void writeJsonResponse(HttpExchange exchange, int httpCode, Map<String, Object> data) throws IOException {
|
||||
String json = gson.toJson(data);
|
||||
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
|
||||
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8");
|
||||
exchange.sendResponseHeaders(httpCode, bytes.length);
|
||||
OutputStream out = exchange.getResponseBody();
|
||||
out.write(bytes);
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造错误响应
|
||||
*/
|
||||
private Map<String, Object> buildErrorResponse(String error, String message) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("code", -1);
|
||||
data.put("error", error);
|
||||
data.put("message", message);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,22 +6,26 @@ import com.taurus.core.entity.ITArray;
|
|||
import com.taurus.core.entity.ITObject;
|
||||
import com.taurus.core.entity.TObject;
|
||||
import com.taurus.core.plugin.redis.Redis;
|
||||
import com.taurus.core.util.Logger;
|
||||
import com.taurus.core.util.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import robot.mj.info.RobotUser;
|
||||
import taurus.client.Message;
|
||||
import taurus.client.TaurusClient;
|
||||
import taurus.util.CardUtil;
|
||||
import taurus.util.HongZhongSuanFaTest;
|
||||
import taurus.util.Util;
|
||||
import com.taurus.core.util.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static robot.mj.thread.ThreadPoolConfig.getBusinessThreadPool;
|
||||
|
||||
public class HuNanHongZhong {
|
||||
private static final Logger log = LoggerFactory.getLogger(HuNanHongZhong.class);
|
||||
// private static final Logger log = LoggerFactory.getLogger(HuNanHongZhong.class);
|
||||
private static final Logger log = Logger.getLogger(HuNanHongZhong.class);
|
||||
|
||||
|
||||
//红中麻将手牌
|
||||
private final List<Integer> hongZhongCardInhand = new ArrayList<>();
|
||||
|
|
@ -78,7 +82,7 @@ public class HuNanHongZhong {
|
|||
public void setSession(String session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
|
@ -92,9 +96,9 @@ public class HuNanHongZhong {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将当前实例状态序列化为JSON字符串并保存到Redis
|
||||
*
|
||||
* @param connecId 连接ID
|
||||
*/
|
||||
public void saveToRedis(String connecId) {
|
||||
|
|
@ -122,6 +126,7 @@ public class HuNanHongZhong {
|
|||
|
||||
/**
|
||||
* 从Redis恢复实例状态
|
||||
*
|
||||
* @param connecId 连接ID
|
||||
* @return 是否成功恢复
|
||||
*/
|
||||
|
|
@ -140,14 +145,16 @@ public class HuNanHongZhong {
|
|||
if (stateMap.containsKey("hongZhongCardInhand")) {
|
||||
hongZhongCardInhand.clear();
|
||||
List<Integer> handCards = gson.fromJson(stateMap.get("hongZhongCardInhand"),
|
||||
new TypeToken<List<Integer>>(){}.getType());
|
||||
new TypeToken<List<Integer>>() {
|
||||
}.getType());
|
||||
if (handCards != null) hongZhongCardInhand.addAll(handCards);
|
||||
}
|
||||
|
||||
if (stateMap.containsKey("hongZhongchuguopai")) {
|
||||
hongZhongchuguopai.clear();
|
||||
List<Integer> handCards = gson.fromJson(stateMap.get("hongZhongchuguopai"),
|
||||
new TypeToken<List<Integer>>(){}.getType());
|
||||
new TypeToken<List<Integer>>() {
|
||||
}.getType());
|
||||
if (handCards != null) hongZhongchuguopai.addAll(handCards);
|
||||
}
|
||||
|
||||
|
|
@ -167,6 +174,7 @@ public class HuNanHongZhong {
|
|||
|
||||
/**
|
||||
* 从Redis清除实例状态
|
||||
*
|
||||
* @param connecId 连接ID
|
||||
*/
|
||||
public static void removeFromRedis(String connecId) {
|
||||
|
|
@ -184,6 +192,7 @@ public class HuNanHongZhong {
|
|||
|
||||
/**
|
||||
* 同步手牌
|
||||
*
|
||||
* @param handCard
|
||||
*/
|
||||
public void updateHandCard(List<Integer> handCard) {
|
||||
|
|
@ -227,18 +236,19 @@ public class HuNanHongZhong {
|
|||
* @param message 消息对象
|
||||
* @return
|
||||
*/
|
||||
public String getCard(String command, Message message) {
|
||||
log.info("摸牌协议-----{} message---{}", command, message);
|
||||
public String getCard(String command, Message message, RobotUser robotUser) {
|
||||
if (command.equalsIgnoreCase("819")) {
|
||||
ITObject param = message.param;
|
||||
if (param == null) {
|
||||
return null;
|
||||
}
|
||||
// {seat=2, Ishupai=0, isBaoTing=-1, tingcard=0, isgang=0, card=101, left_count=106}
|
||||
log.info("轮到用户:{}的用户摸牌, 牌为:{}", param.getInt("player"), param.getInt("card"));
|
||||
log.debug("用户id: {}", playerId);
|
||||
log.debug("座位号: {}", param.getInt("seat"));
|
||||
if (param.getInt("player") != null) {
|
||||
log.info("819机器人摸牌所有参数" + param);
|
||||
Integer seat1 = param.getInt("seat");
|
||||
Integer seat2 = robotUser.getSeat();
|
||||
log.info("819摸牌 后台发的座位号" + seat1);
|
||||
log.info("819摸牌 机器人座位号" + seat2);
|
||||
|
||||
if (Objects.equals(seat1, seat2)) {
|
||||
int drawnCard = param.getInt("card");
|
||||
|
||||
hongZhongSuanFaTest.drawnCards = drawnCard;
|
||||
|
|
@ -434,56 +444,55 @@ public class HuNanHongZhong {
|
|||
public String outCard(TaurusClient client) {
|
||||
// 调用分离分析方法,将刻子、顺子、红中单独拎出后分析剩余牌
|
||||
try {
|
||||
System.out.println("当前机器人手牌" + hongZhongCardInhand);
|
||||
log.info("[HuNanHongZhong] 出牌前分离分析手牌结构...");
|
||||
hongZhongSuanFaTest.separateAndAnalyzeHand(hongZhongCardInhand);
|
||||
System.out.println("当前机器人手牌" + hongZhongCardInhand);
|
||||
log.info("[HuNanHongZhong] 出牌前分离分析手牌结构...");
|
||||
hongZhongSuanFaTest.separateAndAnalyzeHand(hongZhongCardInhand);
|
||||
|
||||
// 红中麻将出牌
|
||||
String hongzhongOutCard = hongZhongSuanFaTest.outCardSuanFa(hongZhongCardInhand, hongZhongCard);
|
||||
// String hongzhongOutCard = hongZhongSuanFaTest.outCardSuanFa(list, hongZhongCard);
|
||||
ITObject params = TObject.newInstance();
|
||||
int cardToOut;
|
||||
if (StringUtil.isNotEmpty(hongzhongOutCard)) {
|
||||
cardToOut = Integer.parseInt(hongzhongOutCard);
|
||||
} else {
|
||||
cardToOut = hongZhongCardInhand.get(0);
|
||||
}
|
||||
params.putInt("card", cardToOut);
|
||||
|
||||
int outCountBefore = hongZhongchuguopai.size(); // 当前历史出牌数量
|
||||
|
||||
// 第n次出牌时,发送前n-1张出牌
|
||||
if (outCountBefore >= 1) {
|
||||
// 发送前n-1张(所有历史出牌)
|
||||
List<Integer> cardsToSend = hongZhongchuguopai.subList(0, outCountBefore);
|
||||
params.putTArray("outcard_list", CardUtil.maJiangToTArray(cardsToSend));
|
||||
}
|
||||
params.putTArray("card_list", CardUtil.maJiangToTArray(hongZhongCardInhand));
|
||||
log.info("机器人牌============{}", params);
|
||||
// 将当前出的牌添加到历史出牌列表
|
||||
hongZhongchuguopai.add(cardToOut);
|
||||
// 从手牌中移除
|
||||
hongZhongCardInhand.remove(Integer.valueOf(cardToOut));
|
||||
log.info("出牌: {}", cardToOut);
|
||||
log.info("目前机器人剩余手牌:{}", hongZhongCardInhand.toString());
|
||||
params.putString("session", session + "," + token);
|
||||
|
||||
//使用线程池替代CompletableFuture.runAsync + Thread.sleep
|
||||
getBusinessThreadPool().execute(() -> {
|
||||
try {
|
||||
int ot = new Random().nextInt(2);
|
||||
Thread.sleep(ot * 1000+1000);
|
||||
client.send("611", params, response -> {
|
||||
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("线程执行错误");
|
||||
// 红中麻将出牌
|
||||
String hongzhongOutCard = hongZhongSuanFaTest.outCardSuanFa(hongZhongCardInhand, hongZhongCard);
|
||||
// String hongzhongOutCard = hongZhongSuanFaTest.outCardSuanFa(list, hongZhongCard);
|
||||
ITObject params = TObject.newInstance();
|
||||
int cardToOut;
|
||||
if (StringUtil.isNotEmpty(hongzhongOutCard)) {
|
||||
cardToOut = Integer.parseInt(hongzhongOutCard);
|
||||
} else {
|
||||
cardToOut = hongZhongCardInhand.get(0);
|
||||
}
|
||||
});
|
||||
params.putInt("card", cardToOut);
|
||||
|
||||
int outCountBefore = hongZhongchuguopai.size(); // 当前历史出牌数量
|
||||
|
||||
// 第n次出牌时,发送前n-1张出牌
|
||||
if (outCountBefore >= 1) {
|
||||
// 发送前n-1张(所有历史出牌)
|
||||
List<Integer> cardsToSend = hongZhongchuguopai.subList(0, outCountBefore);
|
||||
params.putTArray("outcard_list", CardUtil.maJiangToTArray(cardsToSend));
|
||||
}
|
||||
params.putTArray("card_list", CardUtil.maJiangToTArray(hongZhongCardInhand));
|
||||
// 将当前出的牌添加到历史出牌列表
|
||||
hongZhongchuguopai.add(cardToOut);
|
||||
// 从手牌中移除
|
||||
hongZhongCardInhand.remove(Integer.valueOf(cardToOut));
|
||||
log.info("机器人 出牌"+ cardToOut);
|
||||
log.info("目前机器人剩余手牌"+ hongZhongCardInhand);
|
||||
params.putString("session", session + "," + token);
|
||||
log.info("机器人params" + params);
|
||||
//使用线程池替代CompletableFuture.runAsync + Thread.sleep
|
||||
getBusinessThreadPool().execute(() -> {
|
||||
try {
|
||||
int ot = new Random().nextInt(2);
|
||||
Thread.sleep(ot * 1000 + 1000);
|
||||
client.send("611", params, response -> {
|
||||
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("线程执行错误");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue