├── .gitignore ├── README.md ├── doc ├── img │ ├── client.gif │ └── game.png ├── proto3 │ ├── base_battle.proto │ ├── common_enum.proto │ ├── common_msg.proto │ ├── local_server.proto │ ├── remote_server.proto │ └── rpc.proto ├── sql │ └── jgame_server.sql └── tool │ ├── Redis-x64-3.2.100.zip │ └── protoc-3.12.0-rc-2-win64.zip ├── game-battle-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── jacey │ │ └── game │ │ └── battle │ │ ├── ApplicationReadyEventListener.java │ │ ├── BattleServerApplication.java │ │ ├── action │ │ └── baseBattle │ │ │ ├── ConcedeAction.java │ │ │ ├── GetBattleInfoAction.java │ │ │ ├── PlacePiecesAction.java │ │ │ └── ReadyToStartGameAction.java │ │ ├── actor │ │ ├── BaseBattleActor.java │ │ ├── BaseMessageActor.java │ │ ├── BattleRoomManagerActor.java │ │ └── BattleServerActor.java │ │ ├── config │ │ └── SpringConfig.java │ │ ├── manager │ │ ├── ConfigManager.java │ │ ├── MessageManager.java │ │ ├── OnlineClientManager.java │ │ ├── SpringManager.java │ │ └── TableConfigManager.java │ │ └── service │ │ ├── BattleEventService.java │ │ └── impl │ │ └── BattleEventServiceImpl.java │ └── resources │ ├── application.conf │ ├── application.yml │ ├── config.properties │ ├── logback.xml │ ├── propertyConfig.xml │ ├── redis.properties │ ├── spring.xml │ └── tableConfig │ └── SystemConfig.xlsx ├── game-chat-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── jacey │ │ └── game │ │ └── chat │ │ ├── ApplicationReadyEventListener.java │ │ ├── ChatServerApplication.java │ │ ├── actor │ │ ├── BaseBattleChatRoomActor.java │ │ ├── BaseMessageActor.java │ │ ├── ChatRoomMangerActor.java │ │ └── ChatServerActor.java │ │ ├── config │ │ └── SpringConfig.java │ │ └── manager │ │ ├── ConfigManager.java │ │ ├── MessageManager.java │ │ ├── OnlineClientManager.java │ │ └── SpringManager.java │ └── resources │ ├── application.conf │ ├── application.yml │ ├── config.properties │ ├── logback.xml │ ├── propertyConfig.xml │ ├── redis.properties │ └── spring.xml ├── game-common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── jacey │ └── game │ └── common │ ├── action │ └── BaseMessageAction.java │ ├── annotation │ ├── MessageClassMapping.java │ └── MessageMethodMapping.java │ ├── constants │ ├── CookieConstant.java │ ├── GlobalConstant.java │ └── SystemConfigKeyConstant.java │ ├── exception │ └── RpcErrorException.java │ ├── manager │ ├── CoreManager.java │ └── IManager.java │ ├── msg │ ├── AbstractMessage.java │ ├── IMessage.java │ ├── LocalMessage.java │ ├── NetMessage.java │ ├── NetResponseMessage.java │ ├── RemoteMessage.java │ └── serializer │ │ ├── NetMessageSerializer.java │ │ └── RemoteMessageSerializer.java │ ├── network │ └── session │ │ └── ISession.java │ ├── proto3 │ ├── BaseBattle.java │ ├── CommonEnum.java │ ├── CommonMsg.java │ ├── LocalServer.java │ ├── RemoteServer.java │ └── Rpc.java │ └── utils │ ├── ClassScanner.java │ ├── DateTimeUtil.java │ ├── ImportExcelUtil.java │ ├── MD5Util.java │ └── StringUtil.java ├── game-db ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── jacey │ └── game │ └── db │ ├── constants │ ├── BattleRedisKeyConstant.java │ ├── BattleRedisKeyHelper.java │ ├── GmRedisKeyConstant.java │ ├── GmRedisKeyHelper.java │ ├── RedisKeyConstant.java │ └── RedisKeyHelper.java │ ├── dao │ ├── BattleInfoDAO.java │ ├── BattleServerLoadBalanceDAO.java │ ├── ChatServerLoadBalanceDAO.java │ ├── GatewayServerLoadBalanceDAO.java │ ├── GmUserDAO.java │ ├── LogicServerLoadBalanceDAO.java │ └── SessionIdDAO.java │ ├── entity │ ├── BattleRecordEntity.java │ ├── GmUserEntity.java │ ├── PlayStateEntity.java │ └── PlayUserEntity.java │ ├── redis │ └── serializer │ │ ├── ByteRedisSerializer.java │ │ ├── CommonRedisSerializer.java │ │ ├── IntegerRedisSerializer.java │ │ └── LongRedisSerializer.java │ ├── repository │ ├── BattleRecordRepository.java │ ├── GmUserRepository.java │ ├── PlayStateRepository.java │ └── PlayUserRepository.java │ └── service │ ├── BattleInfoService.java │ ├── BattleRecordService.java │ ├── BattleServerLoadBalanceService.java │ ├── ChatServerLoadBalanceService.java │ ├── GatewayServerLoadBalanceService.java │ ├── GmUserService.java │ ├── LogicServerLoadBalanceService.java │ ├── PlayStateService.java │ ├── PlayUserService.java │ ├── SessionIdService.java │ └── impl │ ├── BattleInfoServiceImpl.java │ ├── BattleRecordServiceImpl.java │ ├── BattleServerLoadBalanceServiceImpl.java │ ├── ChatServerLoadBalanceServiceImpl.java │ ├── GatewayServerLoadBalanceServiceImpl.java │ ├── GmUserServiceImpl.java │ ├── LogicServerLoadBalanceServiceImpl.java │ ├── PlayStateServiceImpl.java │ ├── PlayUserServiceImpl.java │ └── SessionIdServiceImpl.java ├── game-gateway-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── jacey │ │ └── game │ │ └── gateway │ │ ├── ApplicationReadyEventListener.java │ │ ├── GatewayServerApplication.java │ │ ├── actor │ │ ├── ChannelActor.java │ │ ├── GatewayActor.java │ │ └── ResponseActor.java │ │ ├── config │ │ └── SpringConfig.java │ │ ├── manager │ │ ├── ConfigManager.java │ │ ├── MessageManager.java │ │ ├── OnlineClientManager.java │ │ ├── ServerNodeManager.java │ │ └── SpringManager.java │ │ └── network │ │ ├── ServerNode.java │ │ └── netty │ │ ├── NettySocketServer.java │ │ ├── NettyWebSocketServer.java │ │ ├── tcp │ │ ├── codec │ │ │ ├── NettyProtocolDecoder.java │ │ │ └── NettyProtocolEncoder.java │ │ └── handle │ │ │ └── NettySocketHandle.java │ │ └── websocket │ │ └── handle │ │ └── NettyWebSocketHandle.java │ └── resources │ ├── application.conf │ ├── application.yml │ ├── config.properties │ ├── logback.xml │ ├── propertyConfig.xml │ ├── redis.properties │ └── spring.xml ├── game-gm-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── jacey │ │ └── game │ │ └── gm │ │ ├── ApplicationReadyEventListener.java │ │ ├── GmServerApplication.java │ │ ├── actor │ │ ├── BaseMessageActor.java │ │ └── GmActor.java │ │ ├── config │ │ ├── FilterConfig.java │ │ └── SpringConfig.java │ │ ├── controller │ │ ├── ClientController.java │ │ └── GmController.java │ │ ├── enums │ │ └── ResultEnum.java │ │ ├── filter │ │ └── RequestInterceptor.java │ │ ├── manager │ │ ├── MessageManager.java │ │ └── SpringManager.java │ │ ├── utils │ │ ├── CookieUtil.java │ │ └── ResultVOUtil.java │ │ └── vo │ │ └── ResultVO.java │ └── resources │ ├── application.conf │ ├── application.yml │ ├── logback.xml │ ├── propertyConfig.xml │ ├── redis.properties │ └── spring.xml ├── game-logic-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── jacey │ │ └── game │ │ └── logic │ │ ├── ApplicationReadyEventListener.java │ │ ├── LogicServerApplication.java │ │ ├── action │ │ └── match │ │ │ ├── CancelMatchAction.java │ │ │ └── MatchAction.java │ │ ├── actor │ │ ├── BaseMessageActor.java │ │ ├── LogicServerActor.java │ │ ├── LoginActor.java │ │ ├── MatchActor.java │ │ └── RegistActor.java │ │ ├── config │ │ └── SpringConfig.java │ │ ├── manager │ │ ├── ConfigManager.java │ │ ├── MessageManager.java │ │ ├── OnlineClientManager.java │ │ ├── SpringManager.java │ │ └── TableConfigManager.java │ │ └── service │ │ ├── MatchService.java │ │ └── impl │ │ └── MatchServiceImpl.java │ └── resources │ ├── application.conf │ ├── application.yml │ ├── config.properties │ ├── logback.xml │ ├── propertyConfig.xml │ ├── redis.properties │ ├── spring.xml │ └── tableConfig │ └── SystemConfig.xlsx ├── pom.xml └── release ├── battle └── pom.xml ├── build-first-build.bat ├── build-server-module.bat ├── chat └── pom.xml ├── gateway └── pom.xml ├── gm └── pom.xml ├── logic └── pom.xml ├── onekey run.bat ├── run battle.bat ├── run chat.bat ├── run gateway.bat ├── run gm.bat └── run logic.bat /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.tar.gz 18 | *.rar 19 | 20 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 21 | hs_err_pid* 22 | 23 | # ===================================== 24 | 25 | *.class 26 | 27 | #package file 28 | *.war 29 | *.ear 30 | 31 | #maven ignore 32 | target/ 33 | 34 | #eclipse ignore 35 | .settins/ 36 | .project 37 | .classpatch 38 | 39 | #idea 40 | .idea/ 41 | /idea/ 42 | *.ipr 43 | *.iml 44 | *.iws 45 | 46 | # test ignore 47 | test/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 概览 2 | 3 | ![概览](https://github.com/JaceyRx/JGameServer/blob/master/doc/img/game.png "概览") 4 | 5 | ## 模块组织结构 6 | 7 | ``` 8 | JGameServer 9 | ├── game-common --基础公共模块 10 | ├── game-db --基础数据库操作模块 11 | ├── game-gm-server --Gm服务器模块:作为各服务器的注册中心、提供服务器管理功能 12 | ├── game-gateway-server --网关服务器模块:用于请求转发与权限控制,支持分布式部署 13 | ├── game-logic-server --逻辑服务器模块:主要游戏业务功能所在处,支持分布式部署 14 | ├── game-chat-server --聊天服务器模块:用于聊天数据处理,支持分布式部署 15 | └── game-battle-server --对战服务器模块:对战相关请求处理,支持分布式部署 16 | ``` 17 | ## 执行流程 18 | 19 | 1. 客户端通过 HTTP 请求从GM服务器获取空闲Gateway服务器连接地址 20 | 2. 客户端连接网关服务器,长连接由gateway网关服务器维护 21 | 3. Gateway服务器接收客户端请求后,根据协议的不同通过Akka Remote 发送给其他业务服务器处理 22 | 23 | ## 协议说明 24 | 25 | ``` 26 | ----------------消息协议格式--------------------- 27 | packetLength | rpcNum | errorCode | body 28 | int int int byte[] 29 | 30 | 协议由四部分组成,前三部分为协议头,用于描述消息,第四部分为消息主体 31 | 第一部分:packetLength 4字节 int 类型 用于描述这个数据包的长度 32 | 第二部分:rpcNum 4字节 int 类型 用于描述当前消息的协议类型 33 | 第三部分:errorCode 4字节 int 类型 用于描述消息的错误类型 34 | 第四部分:body n字节 byte[] 类型 用于存储经protobuf序列化过的消息主体 35 | ``` 36 | 37 | ## 快速开始 38 | 39 | ``` 40 | 1. git clone https://github.com/JaceyRx/JGameServer.git 41 | 2. 创建名为 jgame_server 的 Mysql 数据库,并导入 doc/sql 目录下的.sql文件 42 | 3. 分别修改各 Server 模块的下的 config.properties (修改gm服务器所在服务器IP与当前服务器IP) 43 | 4. 分别修改各 Server 模块的下的 application.yml (修改Mysql的连接地址信息) 44 | 5. 分别修改各 Server 模块的下的 redis.properties (修改Redis的连接地址信息) 45 | 6. [首次运行]-到 release/ 目录下 运行 build-first-build.bat 首次启动编译脚本 46 | 7. 运行 release/ 目录下的 build-server-module.bat 脚本,编译各Server模块 47 | 8. 运行 release/ 目录下的 onekey run.bat 脚本,一键启动各服务器 48 | ``` 49 | 50 | ## TODO List 51 | - 独立的登录服务器 52 | - 独立的注册中心 53 | - Gm后台管理Web界面 54 | - 事件驱动模型的实现 55 | 56 | ## Tips 57 | ``` 58 | 1. 开发环境是 JDK1.8 高于或低于该版本JDK可能会无法运行 59 | 2. 请使用IDEA 打开项目 60 | ``` 61 | ## 测试客户端地址 62 | [TicTacToe-GUI](https://github.com/JaceyRx/TicTacToe-GUI "TicTacToe-GUI") 63 | 64 | ![客户端演示](https://github.com/JaceyRx/JGameServer/blob/master/doc/img/client.gif "客户端演示") 65 | -------------------------------------------------------------------------------- /doc/img/client.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaceyRx/JGameServer/7b4c877ce8d3dcc1620d435c1c4b57beaddd462d/doc/img/client.gif -------------------------------------------------------------------------------- /doc/img/game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaceyRx/JGameServer/7b4c877ce8d3dcc1620d435c1c4b57beaddd462d/doc/img/game.png -------------------------------------------------------------------------------- /doc/proto3/base_battle.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.jacey.game.common.proto3; 3 | 4 | option optimize_for = SPEED; 5 | 6 | import "common_enum.proto"; 7 | import "common_msg.proto"; 8 | 9 | // 一场战斗的信息 10 | message BattleInfo { 11 | repeated UserBriefInfo userBriefInfos = 1; // 玩家简略信息(按行动顺序排列) 12 | CurrentTurnInfo currentTurnInfo = 2; // 当前回合信息 13 | repeated int32 battleCellInfo = 3; // 九宫格从左上角开始,下标为0,然后逐行逐列递增下标。没有棋子的位置值为0,否则值为先后手的行动顺序(先手为1,后手为2) 14 | int64 battleStartTimestamp = 4; // 战斗开始的时间戳 15 | repeated int32 notReadyUserIds = 5; // 尚未准备开始游戏的玩家 16 | int32 lastEventNum = 6; // 对局中上一个事件编号 17 | } 18 | 19 | // 当前回合信息 20 | message CurrentTurnInfo { 21 | int32 turnCount = 1; // 当前回合数(开局后,先手首个回合为1,再轮到先手行动时,回合数+1) 22 | int32 userId = 2; // 当前回合的玩家 23 | int64 turnStartTimestamp = 3; // 当前回合开始的时间 24 | } 25 | 26 | // 战斗数据归档记录 27 | message BattleRecordData { 28 | BattleTypeEnum battleType = 1; 29 | string battleId = 2; 30 | repeated UserBriefInfo userBriefInfos = 3; // 玩家简略信息(按行动顺序排列) 31 | int64 battleStartTimestamp = 4; // 战斗开始的时间戳 32 | int64 battleEndTimestamp = 5; // 战斗结束的时间戳 33 | int32 turnCount = 6; // 对战了几回合 34 | int32 winnerUserId = 7; // 获胜者的userId(平局为0) 35 | GameOverReasonEnum gameOverReason = 8;// 游戏结束的原因 36 | } 37 | 38 | // 获取当前所在对局的信息(GetBattleInfo = 6001) 39 | message GetBattleInfoRequest { 40 | } 41 | message GetBattleInfoResponse { 42 | BattleInfo battleInfo = 1; 43 | } 44 | 45 | // 投降认输(Concede = 6002) 46 | message ConcedeRequest { 47 | } 48 | message ConcedeResponse { 49 | EventMsgList eventList = 1; 50 | } 51 | 52 | // 落子(PlacePieces = 6003) 53 | message PlacePiecesRequest { 54 | int32 lastEventNum = 1; // 对局中上一个事件编号,以此可知客户端是否已同步最新对局信息 55 | int32 index = 2; // 落在哪个位置(九宫格0-8的下标位置) 56 | } 57 | message PlacePiecesResponse { 58 | EventMsgList eventList = 1; 59 | } 60 | 61 | // 确认可以开始游戏(ReadyToStartGame = 6005) 62 | message ReadyToStartGameRequest { 63 | } 64 | message ReadyToStartGameResponse { 65 | } 66 | 67 | 68 | // ------------------------------ 事件相关 ------------------------------ 69 | 70 | // 事件类型 71 | enum EventTypeEnum { 72 | EventTypeGameOver = 0; // 对战结束 73 | EventTypeStartTurn = 1; // 回合开始 74 | EventTypeEndTurn = 2; // 回合结束 75 | EventTypePlacePieces = 3; // 落子 76 | } 77 | 78 | // 一个事件消息 79 | message EventMsg { 80 | int32 eventNum = 1; // 事件编号(从1计,一局游戏第1个事件为先手玩家的StartTurnEvent事件) 81 | EventTypeEnum eventType = 2; // 事件类型 82 | 83 | GameOverEvent gameOverEvent = 6; 84 | StartTurnEvent startTurnEvent = 7; 85 | EndTurnEvent endTurnEvent = 8; 86 | PlacePiecesEvent placePiecesEvent = 9; 87 | } 88 | 89 | // 多个事件组成的事件组 90 | message EventMsgList { 91 | repeated EventMsg msgList = 1; 92 | } 93 | 94 | // 游戏结束的原因 95 | enum GameOverReasonEnum { 96 | GameOverPlayerWin = 0; // 一方胜利 97 | GameOverPlayerConcede = 1; // 一方投降 98 | GameOverDraw = 2; // 平局 99 | } 100 | 101 | // 游戏结束事件 102 | message GameOverEvent { 103 | int32 winnerUserId = 1; // 获胜者的userId(平局为0) 104 | GameOverReasonEnum gameOverReason = 2;// 游戏结束的原因 105 | } 106 | 107 | // 回合开始事件 108 | message StartTurnEvent { 109 | CurrentTurnInfo currentTurnInfo = 1; // 当前回合信息 110 | } 111 | 112 | // 回合结束事件 113 | message EndTurnEvent { 114 | int32 endTurnUserId = 1; // 结束了哪个玩家的回合 115 | bool isForceEndTurn = 2; // 是否因为超时,由系统强制结束回合 116 | } 117 | 118 | // 落子事件 119 | message PlacePiecesEvent { 120 | int32 userId = 1; // 哪个玩家的操作 121 | int32 index = 2; // 落在哪个位置(九宫格0-8的下标位置) 122 | } 123 | 124 | // ------------------------------ 服务器推送 ------------------------------ 125 | 126 | // 战斗服务器推送给玩家场上发生的事件信息(BattleEventMsgListPush = 22001) 127 | message BattleEventMsgListPush { 128 | EventMsgList eventMsgList = 1; 129 | } 130 | -------------------------------------------------------------------------------- /doc/proto3/common_enum.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.jacey.game.common.proto3; 3 | 4 | option optimize_for = SPEED; 5 | 6 | // 服务器类型 7 | enum RemoteServerTypeEnum { 8 | ServerTypeLogic = 0; 9 | ServerTypeBattle = 1; 10 | ServerTypeGateway = 2; 11 | ServerTypeGm = 3; 12 | ServerTypeChat = 4; 13 | } 14 | 15 | // GM命令类型 16 | enum GmCmdTypeEnum { 17 | GmCmdReloadTableConfig = 0; // GM命令 重新加载配置表格 18 | GmCmdCloseServer = 1; // GM命令 关服 19 | } 20 | 21 | // 玩家在线状态 22 | enum UserOnlineStateEnum { 23 | Offline = 0; 24 | Online = 1; 25 | } 26 | 27 | // 玩家行为状态 28 | enum UserActionStateEnum { 29 | ActionNone = 0; 30 | Matching = 1; // 匹配中 31 | Playing = 2; // 对战中 32 | } 33 | 34 | // 对战类型 35 | enum BattleTypeEnum { 36 | NoneType = 0; 37 | BattleTypeTwoPlayer = 1; // 1V1 38 | } 39 | 40 | 41 | // 玩家被封禁原因 42 | enum UserForbidReasonEnum { 43 | UserForbidReasonGmOperate = 0; // GM管理员手工操作封禁 44 | UserForbidReasonCheat = 1; // 服务器发现明显只能是玩家破解、伪造数据包进行请求时,自动封禁 45 | } 46 | 47 | 48 | // 被强制下线的原因 49 | enum ForceOfflineReasonEnum { 50 | ForceOfflineServerNotAvailable = 0; // 服务器不可用 51 | ForceOfflineSameUserLogin = 1; // 同一账号同时异地登录,踢掉之前登录的 52 | } 53 | 54 | // 聊天室类型 55 | enum ChatRoomTypeEnum { 56 | TwoPlayerBattleChatRoomType = 0; // 1v1对战聊天室 57 | } 58 | // 对战聊天文本作用域 59 | enum BattleChatTextScopeEnum { 60 | TeammateScope = 0; // 队友 61 | EveryoneScope = 1; // 所有人(战局中的所有人。包括对手、队友) 62 | } -------------------------------------------------------------------------------- /doc/proto3/local_server.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.jacey.game.common.proto3; 3 | 4 | option optimize_for = SPEED; 5 | 6 | // 服务器内部通信协议名 7 | enum LocalRpcNameEnum { 8 | None = 0; // 由于proto3中enum首位必须是0所以设置该标识字段 9 | 10 | LocalRpcRegistToGmServer = 300001; // 向GM服务器注册 11 | 12 | LocalRpcLogicServerMatch = 310001; // logicServer循环通知自己进行匹配计算 13 | 14 | LocalRpcBattleServerInitBattle = 320001; // battleServer通知初始化战斗 15 | 16 | } 17 | -------------------------------------------------------------------------------- /doc/proto3/remote_server.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.jacey.game.common.proto3; 3 | 4 | option optimize_for = SPEED; 5 | 6 | import "common_enum.proto"; 7 | 8 | // 服务器间通信协议名 9 | enum RemoteRpcNameEnum { 10 | None = 0; // 由于proto3中enum首位必须是0所以设置该标识字段 11 | RemoteRpcRegistServer = 400101; // 逻辑、战斗、gateway服务器向GM服务器注册自己 12 | RemoteRpcNoticeExecuteGmCmd = 400102; // GM服务器向指定服务器发GM命令 13 | RemoteRpcNoticeGmServerTextMsg = 400103; // 逻辑、战斗、gateway服务器向GM服务器推送文本内容(比如异步回应GM命令执行情况) 14 | 15 | RemoteRpcNoticeBattleServerCreateNewBattle = 410101;// 主逻辑服务器在匹配成功后通知指定的战斗服务器创建战场 16 | 17 | RemoteRpcNoticeChatServerCreateNewBattleChatRoom = 420101; // 对战服务器在初始化战场成功后通知指定的聊天服务器创建对战聊天室 18 | 19 | RemoteRpcGatewayNoticeClientOfflinePush = 500001; // gateway监测到客户端离线后通知逻辑服、战斗服 20 | RemoteRpcLogicServerNoticeGatewayForceOfflineClient = 500002; // logicServer在发现同一账号二次登录时,通知旧session所在的gateway进行强制下线 21 | } 22 | 23 | // 服务器间通信错误码 24 | enum RemoteRpcErrorCodeEnum { 25 | RemoteRpcOk = 0; // 正常 26 | RemoteRpcServerError = 1; // 远程服务器错误 27 | 28 | RemoteRpcRegistServerErrorHasRegisted = 4001011; // 向GM服务器注册自己错误,已经注册过了(对应类型的服务器id被注册或者已经注册了主逻辑服务器又注册另外的主逻辑服务器) 29 | } 30 | 31 | // 逻辑、战斗、gateway服务器向GM服务器注册自己(RemoteRpcRegistServer = 400101) 32 | message RegistServerRequest { 33 | RemoteServerInfo serverInfo = 1; 34 | } 35 | message RegistServerResponse { 36 | } 37 | 38 | // 远程服务器信息 39 | message RemoteServerInfo { 40 | RemoteServerTypeEnum serverType = 1; // 远程服务器类型 41 | string akkaPath = 2; // 用akka进行连接的服务器地址 42 | int32 serverId = 3; // 服务器编号 43 | 44 | bool isMainLogicServer = 4; // 如果是逻辑服务器,需发是不是主逻辑服务器(只有主逻辑服务器处理注册、匹配等) 45 | string gatewayConnectPath = 5; // 如果是gateway,需发供客户端连接的地址 46 | } 47 | 48 | 49 | // GM服务器向指定服务器发GM命令(RemoteRpcNoticeExecuteGmCmd = 400102) 50 | message NoticeExecuteGmCmdRequest { 51 | GmCmdTypeEnum cmdType = 1; 52 | repeated string params = 2; // 不同指令所需的操作参数 53 | } 54 | message NoticeExecuteGmCmdResponse { 55 | } 56 | 57 | // 逻辑、战斗、gateway服务器向GM服务器推送文本内容(比如异步回应GM命令执行情况)(RemoteRpcNoticeGmServerTextMsg = 400103) 58 | message NoticeGmServerTextMsgRequest { 59 | RemoteServerTypeEnum serverType = 1; 60 | int32 serverId = 2; 61 | string text = 3; 62 | } 63 | message NoticeGmServerTextMsgResponse { 64 | } 65 | 66 | // 一个对战房间的信息 67 | message BattleRoomInfo { 68 | BattleTypeEnum battleType = 1; 69 | string battleId = 2; 70 | repeated int32 userIds = 3; // 按行动顺序排列的对战玩家userId 71 | } 72 | 73 | // 主逻辑服务器在匹配成功后通知指定的战斗服务器创建战场(RemoteRpcNoticeBattleServerCreateNewBattle = 410101) 74 | message NoticeBattleServerCreateNewBattleRequest { 75 | BattleRoomInfo battleRoomInfo = 1; 76 | } 77 | message NoticeBattleServerCreateNewBattleResponse { 78 | BattleRoomInfo battleRoomInfo = 1; 79 | } 80 | 81 | // 一个聊天室信息 82 | message ChatRoomInfo { 83 | ChatRoomTypeEnum chatRoomType = 1; // 聊天室类型 84 | string battleId = 2; // 对战id 85 | } 86 | 87 | // 对战服务器通知聊天服务器创建对战聊天室(RemoteRpcNoticeChatServerCreateNewBattleChatRoot = 420101) 88 | message NoticeChatServerCreateNewBattleChatRoomRequest { 89 | ChatRoomInfo chatRoomInfo = 1; 90 | } 91 | message NoticeChatServerCreateNewBattleChatRoomResponse { 92 | } 93 | 94 | // ------------------------------ 服务器推送 ------------------------------ 95 | 96 | // gateway监测到客户端离线后通知逻辑服、战斗服(RemoteRpcGatewayNoticeClientOfflinePush = 500001) 97 | message GatewayNoticeClientOfflinePush { 98 | int32 sessionId = 1; 99 | int32 userId = 2; // 如果该session对应的客户端登录成功,需发此字段 100 | bool isUserOffline = 3; // 是否是玩家也要下线(同一账号二次登录导致旧session断开,但对应玩家仍在线) 101 | } 102 | 103 | // logicServer在发现同一账号二次登录时,通知旧session所在的gateway进行强制下线(RemoteRpcLogicServerNoticeGatewayForceOfflineClient = 500002) 104 | message LogicServerNoticeGatewayForceOfflineClientPush { 105 | int32 sessionId = 1; 106 | ForceOfflineReasonEnum forceOfflineReason = 2; 107 | } 108 | -------------------------------------------------------------------------------- /doc/proto3/rpc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package com.jacey.game.common.proto3; 3 | 4 | option optimize_for = SPEED; 5 | 6 | // 客户端与服务器通讯协议名 7 | enum RpcNameEnum { 8 | None = 0; // 由于proto3中enum首位必须是0所以设置该标识字段 9 | Regist = 101; // 注册 10 | Login = 102; // 登录 11 | 12 | Match = 111; // 对战匹配 13 | CancelMatch = 112; // 取消对战匹配 14 | 15 | // ------------- 对战相关 ------------- 16 | GetBattleInfo = 6001; // 获取当前所在对局的信息 17 | Concede = 6002; // 投降认输 18 | PlacePieces = 6003; // 落子 19 | ReadyToStartGame = 6005; // 确认可以开始游戏 20 | 21 | // ------------(聊天相关) - (10001-14000)------------------------- 22 | JoinChatRoom = 10001; // 加入对战聊天室 23 | BattleChatText = 10002; // 对战聊天请求 24 | 25 | // ------------- 服务器推送 ------------- 26 | ForceOfflinePush = 20001; // 强制下线推送 27 | 28 | MatchResultPush = 21001; // 主逻辑服务器推送给玩家匹配结果 29 | 30 | BattleEventMsgListPush = 22001; // 战斗服务器推送给玩家场上发生的事件信息 31 | 32 | BattleChatTextPush = 23001; // 聊天服务器推送对战聊天内容 33 | } 34 | 35 | // 客户端与服务器通讯协议错误码 36 | enum RpcErrorCodeEnum { 37 | Ok = 0; // 正常 38 | ServerError = 1; // 服务器内部错误 39 | ClientError = 2; // 客户端请求参数非法 40 | ServerNotAvailable = 3; // 服务器当前不可用 41 | 42 | UserNotInBattle = 11; // 玩家不在对战中 43 | BattleNotStart = 12; // 游戏尚未开始(需双方都确认ReadyToStartGame) 44 | IsNotUserTurn = 13; // 不是该玩家的回合 45 | InputLastEventNumError = 14; // 客户端请求对战操作时附带的lastEventNum错误,说明发生丢包 46 | 47 | RegisErrorUsernameIsExist = 1011; // 无法注册,用户名已存在 48 | RegisErrorUsernameIllegal = 1012; // 无法注册,用户名非法 49 | RegisErrorPasswordIllegal = 1013; // 无法注册,密码非法 50 | LoginErrorUsernameIsNotExist = 1021; // 无法登录,用户名不存在 51 | LoginErrorPasswordWrong = 1022; // 无法登录,密码错误 52 | LoginErrorForbid = 1023; // 无法登录,账号被封禁 53 | 54 | MatchErrorMatching = 1111; // 无法匹配,目前就是匹配状态 55 | MatchErrorPlaying = 1112; // 无法匹配,已经在对战中 56 | MatchErrorOtherActionState = 1113; // 无法匹配,处于其他状态 57 | CancelMatchErrorPlaying = 1121; // 取消匹配失败,已经在对战中 58 | CancelMatchErrorNotMatching = 1122; // 取消匹配失败,没有在匹配中 59 | 60 | PlacePiecesErrorIndexError = 60031; // 请求落子错误,要落子的位置非法 61 | PlacePiecesErrorIndexIsNotEmpty = 60032; // 请求落子错误,要落子的位置已经有棋子 62 | ReadyToStartGameErrorAlreadyReady = 60051; // 确认可以开始游戏错误,已经确认过了 63 | ForceReadyToStartGameErrorAlreadyStart = 60052;// 请求强制开始游戏错误,游戏已经开始了 64 | 65 | BattleChatTextErrorNotJoinBattle = 100021; // 对战聊天发送失败,未加入对战 66 | } -------------------------------------------------------------------------------- /doc/tool/Redis-x64-3.2.100.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaceyRx/JGameServer/7b4c877ce8d3dcc1620d435c1c4b57beaddd462d/doc/tool/Redis-x64-3.2.100.zip -------------------------------------------------------------------------------- /doc/tool/protoc-3.12.0-rc-2-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaceyRx/JGameServer/7b4c877ce8d3dcc1620d435c1c4b57beaddd462d/doc/tool/protoc-3.12.0-rc-2-win64.zip -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/ApplicationReadyEventListener.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle; 2 | 3 | import com.jacey.game.battle.manager.*; 4 | import com.jacey.game.common.manager.CoreManager; 5 | import org.springframework.boot.context.event.ApplicationReadyEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | /** 10 | * @Description: manager 统一初始化 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | public class ApplicationReadyEventListener implements ApplicationListener { 15 | 16 | @Override 17 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 18 | ConfigurableApplicationContext context = applicationReadyEvent.getApplicationContext(); 19 | // 设置Spring context上下文 20 | SpringManager.getInstance().setContext(context); 21 | // 核心管理器注册 22 | CoreManager.getInstance().registManager(ConfigManager.getInstance()); 23 | CoreManager.getInstance().registManager(TableConfigManager.getInstance()); 24 | CoreManager.getInstance().registManager(SpringManager.getInstance()); 25 | CoreManager.getInstance().registManager(MessageManager.getInstance()); 26 | CoreManager.getInstance().registManager(OnlineClientManager.getInstance()); 27 | 28 | CoreManager.getInstance().init(); // 对所有manager进行初始化 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/BattleServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 9 | 10 | /** 11 | * @Description: 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @SpringBootApplication 16 | @ComponentScan("com.jacey.game") 17 | @EnableJpaRepositories("com.jacey.game.db.repository") 18 | @EntityScan("com.jacey.game.db.entity") 19 | public class BattleServerApplication { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication app = new SpringApplication(BattleServerApplication.class); 23 | app.addListeners(new ApplicationReadyEventListener()); 24 | app.run(args); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/action/baseBattle/ConcedeAction.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.action.baseBattle; 2 | 3 | import com.jacey.game.battle.service.BattleEventService; 4 | import com.jacey.game.common.action.BaseMessageAction; 5 | import com.jacey.game.common.annotation.MessageClassMapping; 6 | import com.jacey.game.common.exception.RpcErrorException; 7 | import com.jacey.game.common.msg.IMessage; 8 | import com.jacey.game.common.msg.NetMessage; 9 | import com.jacey.game.common.proto3.BaseBattle; 10 | import com.jacey.game.common.proto3.CommonMsg; 11 | import com.jacey.game.common.proto3.Rpc; 12 | import com.jacey.game.db.service.BattleInfoService; 13 | import com.jacey.game.db.service.BattleServerLoadBalanceService; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import java.util.List; 19 | import java.util.Set; 20 | 21 | /** 22 | * @Description: 认输 23 | * @Author: JaceyRuan 24 | * @Email: jacey.ruan@outlook.com 25 | */ 26 | @Slf4j 27 | @Component 28 | @MessageClassMapping(value = Rpc.RpcNameEnum.Concede_VALUE, isNet = false) 29 | public class ConcedeAction extends BaseMessageAction { 30 | 31 | @Autowired 32 | private BattleServerLoadBalanceService battleServerLoadBalanceService; 33 | @Autowired 34 | private BattleInfoService battleInfoService; 35 | @Autowired 36 | private BattleEventService battleEventService; 37 | 38 | @Override 39 | protected void LogRequest(IMessage requestMessage) throws Exception { 40 | NetMessage req = (NetMessage) requestMessage; 41 | log.info("【认输请求】 userId = {}:\n{}", req.getUserId(), req.getProtobufText(BaseBattle.ConcedeRequest.class)); 42 | } 43 | 44 | @Override 45 | protected void LogResponse(IMessage responseMessage) throws Exception { 46 | NetMessage resp = (NetMessage) responseMessage; 47 | log.info("【认输响应】 userId = {}:\n{}", resp.getUserId(), resp.getProtobufText(BaseBattle.ConcedeResponse.class)); 48 | } 49 | 50 | @Override 51 | protected IMessage doAction(IMessage requestMessage) throws Exception { 52 | NetMessage msg = (NetMessage) requestMessage; 53 | int userId = msg.getUserId(); 54 | 55 | String battleId = battleServerLoadBalanceService.getBattleUserIdToBattleId(userId); 56 | if (battleId == null) { 57 | // 对战不存在 58 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.UserNotInBattle_VALUE); 59 | } 60 | 61 | Set notReadyUserIds = battleInfoService.getOneBattleNotReadyUserIds(battleId); 62 | if (notReadyUserIds != null && notReadyUserIds.size() > 0) { 63 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.BattleNotStart_VALUE); 64 | } 65 | // 这里必须在doGameOverEvent之前取得,否则就会因为redis中对战相关信息被清除而无法取得 66 | // 获取对手id 67 | int opponentUserId = battleInfoService.getOneUserOneOpponentUserId(battleId, userId); 68 | // 构造游戏结束事件 69 | BaseBattle.GameOverEvent.Builder gameOverEventBuilder = BaseBattle.GameOverEvent.newBuilder(); 70 | gameOverEventBuilder.setGameOverReason(BaseBattle.GameOverReasonEnum.GameOverPlayerConcede); 71 | gameOverEventBuilder.setWinnerUserId(battleInfoService.getOneUserOneOpponentUserId(battleId, userId)); 72 | BaseBattle.EventMsg.Builder eventMsgBuilder = battleEventService.buildOneEvent(battleId, BaseBattle.EventTypeEnum.EventTypeGameOver, 73 | gameOverEventBuilder); 74 | //执行事件 75 | BaseBattle.EventMsgList.Builder eventMsgListBuilder = battleEventService.doEvent(battleId, eventMsgBuilder); 76 | 77 | // 推送给本场战斗中的所有对手玩家 78 | battleEventService.pushEventMsgListToOneBattlePlayer(opponentUserId, eventMsgListBuilder); 79 | // 响应认输事件回客户端 80 | BaseBattle.ConcedeResponse.Builder builder = BaseBattle.ConcedeResponse.newBuilder(); 81 | builder.setEventList(eventMsgListBuilder); 82 | return super.buildResponseNetMsg(userId, Rpc.RpcNameEnum.Concede_VALUE, builder); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/action/baseBattle/GetBattleInfoAction.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.action.baseBattle; 2 | 3 | import com.jacey.game.common.action.BaseMessageAction; 4 | import com.jacey.game.common.annotation.MessageClassMapping; 5 | import com.jacey.game.common.exception.RpcErrorException; 6 | import com.jacey.game.common.msg.IMessage; 7 | import com.jacey.game.common.msg.NetMessage; 8 | import com.jacey.game.common.proto3.BaseBattle; 9 | import com.jacey.game.common.proto3.CommonMsg; 10 | import com.jacey.game.common.proto3.Rpc; 11 | import com.jacey.game.db.service.BattleInfoService; 12 | import com.jacey.game.db.service.BattleServerLoadBalanceService; 13 | import com.jacey.game.db.service.PlayUserService; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import java.util.List; 19 | import java.util.Set; 20 | 21 | /** 22 | * @Description: 获取对战信息 23 | * @Author: JaceyRuan 24 | * @Email: jacey.ruan@outlook.com 25 | */ 26 | @Slf4j 27 | @Component 28 | @MessageClassMapping(value = Rpc.RpcNameEnum.GetBattleInfo_VALUE, isNet = false) 29 | public class GetBattleInfoAction extends BaseMessageAction { 30 | 31 | @Autowired 32 | private BattleServerLoadBalanceService battleServerLoadBalanceService; 33 | @Autowired 34 | private PlayUserService playUserService; 35 | @Autowired 36 | private BattleInfoService battleInfoService; 37 | 38 | @Override 39 | protected void LogRequest(IMessage requestMessage) throws Exception { 40 | NetMessage req = (NetMessage) requestMessage; 41 | log.info("【获取对战信息请求】 userId = {}:\n{}", req.getUserId(), req.getProtobufText(BaseBattle.GetBattleInfoRequest.class)); 42 | } 43 | 44 | @Override 45 | protected void LogResponse(IMessage responseMessage) throws Exception { 46 | NetMessage resp = (NetMessage) responseMessage; 47 | log.info("【获取对战信息响应】 userId = {}:\n{}", resp.getUserId(), resp.getProtobufText(BaseBattle.GetBattleInfoResponse.class)); 48 | } 49 | 50 | @Override 51 | protected IMessage doAction(IMessage requestMessage) throws Exception { 52 | NetMessage msg = (NetMessage) requestMessage; 53 | int userId = msg.getUserId(); 54 | // 根据userId获取battleId 55 | String battleId = battleServerLoadBalanceService.getBattleUserIdToBattleId(userId); 56 | if (battleId == null) { 57 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.UserNotInBattle_VALUE); 58 | } 59 | BaseBattle.GetBattleInfoResponse.Builder builder = BaseBattle.GetBattleInfoResponse.newBuilder(); 60 | BaseBattle.BattleInfo.Builder battleInfoBuilder = BaseBattle.BattleInfo.newBuilder(); 61 | // 根据对战id,获取对战双方userId 62 | List userIds = battleInfoService.getOneBattleUserIds(battleId); 63 | for (int oneUserId : userIds) { 64 | // 根据userId获取用户简介信息 65 | battleInfoBuilder.addUserBriefInfos(playUserService.getUserBriefInfoByUserId(oneUserId)); 66 | } 67 | // 设置对战开始时间 68 | battleInfoBuilder.setBattleStartTimestamp(battleInfoService.getOneBattleStartTimestamp(battleId)); 69 | // 设置当前棋盘中棋子信息 70 | battleInfoBuilder.addAllBattleCellInfo(battleInfoService.getAllBattleCellInfo(battleId)); 71 | // 设置上一个已发生事件的eventNum 72 | battleInfoBuilder.setLastEventNum(battleInfoService.getLastEventNum(battleId)); 73 | // 获取未准备用户id List 74 | Set notReadyUserIds = battleInfoService.getOneBattleNotReadyUserIds(battleId); 75 | // 判断是否有未准备玩家 76 | if (notReadyUserIds == null || notReadyUserIds.size() < 1) { 77 | // 设置当前回合信息 78 | battleInfoBuilder.setCurrentTurnInfo(battleInfoService.getBattleCurrentTurnInfo(battleId)); //设置当前回合的信息 79 | } else { 80 | // 设置为准备UserId List 81 | battleInfoBuilder.addAllNotReadyUserIds(notReadyUserIds); // 设置为准备玩家ids 82 | } 83 | builder.setBattleInfo(battleInfoBuilder); 84 | return super.buildResponseNetMsg(userId, Rpc.RpcNameEnum.GetBattleInfo_VALUE, builder); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/action/baseBattle/ReadyToStartGameAction.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.action.baseBattle; 2 | 3 | import com.jacey.game.battle.service.BattleEventService; 4 | import com.jacey.game.common.action.BaseMessageAction; 5 | import com.jacey.game.common.annotation.MessageClassMapping; 6 | import com.jacey.game.common.exception.RpcErrorException; 7 | import com.jacey.game.common.msg.IMessage; 8 | import com.jacey.game.common.msg.NetMessage; 9 | import com.jacey.game.common.proto3.BaseBattle; 10 | import com.jacey.game.common.proto3.CommonMsg; 11 | import com.jacey.game.common.proto3.Rpc; 12 | import com.jacey.game.db.service.BattleInfoService; 13 | import com.jacey.game.db.service.BattleServerLoadBalanceService; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import java.util.Set; 19 | 20 | /** 21 | * @Description: 确认可以开始游戏 22 | * @Author: JaceyRuan 23 | * @Email: jacey.ruan@outlook.com 24 | */ 25 | @Slf4j 26 | @Component 27 | @MessageClassMapping(value = Rpc.RpcNameEnum.ReadyToStartGame_VALUE, isNet = false) 28 | public class ReadyToStartGameAction extends BaseMessageAction { 29 | 30 | @Autowired 31 | private BattleServerLoadBalanceService battleServerLoadBalanceService; 32 | @Autowired 33 | private BattleInfoService battleInfoService; 34 | @Autowired 35 | private BattleEventService battleEventService; 36 | 37 | @Override 38 | protected void LogRequest(IMessage requestMessage) throws Exception { 39 | NetMessage req = (NetMessage) requestMessage; 40 | log.info("【准备完毕请求】 userId = {}:\n{}", req.getUserId(), req.getProtobufText(CommonMsg.MatchRequest.class)); 41 | } 42 | 43 | @Override 44 | protected void LogResponse(IMessage responseMessage) throws Exception { 45 | NetMessage resp = (NetMessage) responseMessage; 46 | log.info("【准备完毕响应】 userId = {}:\n{}", resp.getUserId(), resp.getProtobufText(CommonMsg.MatchResponse.class)); 47 | } 48 | 49 | @Override 50 | protected IMessage doAction(IMessage requestMessage) throws Exception { 51 | NetMessage msg = (NetMessage) requestMessage; 52 | int userId = msg.getUserId(); 53 | 54 | String battleId = battleServerLoadBalanceService.getBattleUserIdToBattleId(userId); 55 | if (battleId == null) { 56 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.UserNotInBattle_VALUE); 57 | } 58 | // 获取未准备用户列表 59 | Set notReadyUserIds = battleInfoService.getOneBattleNotReadyUserIds(battleId); 60 | if (notReadyUserIds == null || notReadyUserIds.contains(userId) == false) { 61 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.ReadyToStartGameErrorAlreadyReady_VALUE); // 确认可以开始游戏错误,已经确认过了 62 | } 63 | // 未准备玩家列表,移除当前用户 64 | notReadyUserIds.remove(userId); 65 | battleInfoService.removeOneBattleNotReadyUserId(battleId, userId); 66 | // 移除后,再获取一次列表。防止并发问题 67 | notReadyUserIds = battleInfoService.getOneBattleNotReadyUserIds(battleId); 68 | if (notReadyUserIds == null || notReadyUserIds.size() < 1) { 69 | // 开始第一个回合 70 | battleEventService.startFirstTurn(battleId); 71 | } 72 | 73 | BaseBattle.ReadyToStartGameResponse.Builder builder = BaseBattle.ReadyToStartGameResponse.newBuilder(); 74 | return super.buildResponseNetMsg(userId, Rpc.RpcNameEnum.ReadyToStartGame_VALUE, builder); //确认可以开始游戏 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/actor/BaseBattleActor.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.actor; 2 | 3 | import com.jacey.game.battle.manager.MessageManager; 4 | import com.jacey.game.battle.manager.SpringManager; 5 | import com.jacey.game.battle.service.BattleEventService; 6 | import com.jacey.game.battle.service.impl.BattleEventServiceImpl; 7 | import com.jacey.game.common.annotation.MessageMethodMapping; 8 | import com.jacey.game.common.msg.LocalMessage; 9 | import com.jacey.game.common.msg.RemoteMessage; 10 | import com.jacey.game.common.proto3.CommonEnum; 11 | import com.jacey.game.common.proto3.LocalServer; 12 | import com.jacey.game.common.proto3.RemoteServer; 13 | 14 | import java.rmi.Remote; 15 | 16 | /** 17 | * @Description: 用于专门处理1v1对战请求,一场战斗绑定一个 18 | * @Author: JaceyRuan 19 | * @Email: jacey.ruan@outlook.com 20 | */ 21 | public class BaseBattleActor extends BaseMessageActor { 22 | 23 | private BattleEventService battleEventService = SpringManager.getInstance().getBean(BattleEventServiceImpl.class); 24 | 25 | public BaseBattleActor() { 26 | super(); 27 | } 28 | 29 | public BaseBattleActor(String actionPackageName) { 30 | super(actionPackageName); 31 | } 32 | 33 | /** 34 | * battleServer通知初始化战斗 35 | * @param localMessage 本地通讯对象 36 | * @throws Exception 37 | */ 38 | @MessageMethodMapping(LocalServer.LocalRpcNameEnum.LocalRpcBattleServerInitBattle_VALUE) 39 | public void initBattle(LocalMessage localMessage) throws Exception { 40 | RemoteServer.BattleRoomInfo battleRoomInfo = (RemoteServer.BattleRoomInfo) localMessage.getLite(); 41 | // 战局初始化 42 | battleEventService.initBattle(battleRoomInfo); 43 | // 通知初始化对战聊天室 44 | RemoteServer.NoticeChatServerCreateNewBattleChatRoomRequest.Builder builder = RemoteServer 45 | .NoticeChatServerCreateNewBattleChatRoomRequest.newBuilder(); 46 | 47 | RemoteServer.ChatRoomInfo.Builder chatRoomInfoBuilder = RemoteServer.ChatRoomInfo.newBuilder(); 48 | chatRoomInfoBuilder.setChatRoomType(CommonEnum.ChatRoomTypeEnum.TwoPlayerBattleChatRoomType); 49 | chatRoomInfoBuilder.setBattleId(battleRoomInfo.getBattleId()); 50 | // 设置对战聊天房间信息 51 | builder.setChatRoomInfo(chatRoomInfoBuilder); 52 | 53 | RemoteMessage remoteMessage = new RemoteMessage( 54 | RemoteServer.RemoteRpcNameEnum.RemoteRpcNoticeChatServerCreateNewBattleChatRoom_VALUE, builder); 55 | // 推送 56 | MessageManager.getInstance().noticeChatServerCreateNewBattleChatRoom(remoteMessage, context().self()); 57 | } 58 | 59 | /** 60 | * 接收初始化聊天室信息 61 | */ 62 | @MessageMethodMapping(RemoteServer.RemoteRpcNameEnum.RemoteRpcNoticeChatServerCreateNewBattleChatRoom_VALUE) 63 | public void onReceivedNoticeBattleServerCreateNewBattle(RemoteMessage remoteMessage) { 64 | // TODO 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/config/SpringConfig.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.ImportResource; 5 | 6 | @Configuration 7 | @ImportResource(locations = { "classpath:spring.xml" }) 8 | public class SpringConfig { 9 | 10 | public SpringConfig() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/manager/ConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.configuration.Configuration; 6 | import org.apache.commons.configuration.ConfigurationException; 7 | import org.apache.commons.configuration.ConfigurationFactory; 8 | 9 | /** 10 | * @Description: 配置文件加载管理 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class ConfigManager implements IManager { 16 | 17 | private static ConfigManager configManager = new ConfigManager(); 18 | 19 | private static ConfigurationFactory factory; 20 | private static Configuration config; 21 | 22 | public static String REMOTE_GM_AKKA_PATH; // GM服务器Akka path 23 | public static int BATTLE_SERVER_ID; // 当前battle服务器id 24 | public static String BATTLE_SERVER_AKKA_PATH; // battle服务器akka oath 25 | 26 | private ConfigManager() {} 27 | 28 | public static ConfigManager getInstance() { 29 | return configManager; 30 | } 31 | 32 | 33 | @Override 34 | public void init() { 35 | log.info("------------ start load config ------------"); 36 | loadConfig(); 37 | log.info("------------ finish load config ------------"); 38 | } 39 | 40 | @Override 41 | public void shutdown() { 42 | 43 | } 44 | 45 | private void loadConfig() { 46 | factory = new ConfigurationFactory("propertyConfig.xml"); 47 | try { 48 | config = factory.getConfiguration(); 49 | } catch (ConfigurationException e) { 50 | log.error("【config初始化失败】, exception = ", e); 51 | System.exit(0); 52 | } 53 | 54 | REMOTE_GM_AKKA_PATH = config.getString("remote.gm.akka.path"); 55 | BATTLE_SERVER_ID = config.getInt("battle.server.id"); 56 | BATTLE_SERVER_AKKA_PATH = config.getString("battle.server.akka.path"); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/manager/SpringManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.data.redis.connection.RedisConnection; 7 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 8 | 9 | /** 10 | * @Description: 处理Spring相关内容 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class SpringManager implements IManager { 16 | 17 | private static SpringManager instance = new SpringManager(); 18 | 19 | public static SpringManager getInstance() { 20 | return instance; 21 | } 22 | 23 | private ConfigurableApplicationContext context; 24 | 25 | @Override 26 | public void init() { 27 | // 检查redis是否已连接 28 | try { 29 | JedisConnectionFactory factory = getBean(JedisConnectionFactory.class); 30 | RedisConnection connection = factory.getConnection(); 31 | if ("PONG".equals(connection.ping()) == false) { 32 | log.error("redis connect fail"); 33 | System.exit(0); 34 | } 35 | } catch (Exception e) { 36 | log.error("redis connect fail, error = ", e); 37 | System.exit(0); 38 | } 39 | 40 | } 41 | 42 | @Override 43 | public void shutdown() { 44 | } 45 | 46 | public Object getBean(String beanName) { 47 | return context.getBean(beanName); 48 | } 49 | 50 | public T getBean(Class object) { 51 | return context.getBean(object); 52 | } 53 | 54 | public void setContext(ConfigurableApplicationContext context) { 55 | this.context = context; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/manager/TableConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import com.jacey.game.common.utils.ImportExcelUtil; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import java.io.InputStream; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * @Description: 游戏系统配置数据加载 13 | * @Author: JaceyRuan 14 | * @Email: jacey.ruan@outlook.com 15 | */ 16 | @Slf4j 17 | public class TableConfigManager implements IManager { 18 | 19 | private TableConfigManager(){} 20 | 21 | private static TableConfigManager instance = new TableConfigManager(); 22 | 23 | public static TableConfigManager getInstance() { 24 | return instance; 25 | } 26 | 27 | // SystemConfig,系统配置表,key:paramKey, value:paramValue 28 | private Map systemConfigMap; 29 | 30 | public static final String TABLE_CONFIG_FILE_PATH = "tableConfig/"; 31 | 32 | private ClassLoader classLoader = TableConfigManager.class.getClassLoader(); 33 | 34 | @Override 35 | public void init() { 36 | log.info("------------ start load table config ------------"); 37 | loadTableConfig(); 38 | log.info("------------ finish load table config ------------"); 39 | } 40 | 41 | private void loadTableConfig() { 42 | // SystemConfig,系统配置表,key:paramKey, value:paramValue 43 | systemConfigMap = new HashMap(); 44 | InputStream inputStream = classLoader.getResourceAsStream(TABLE_CONFIG_FILE_PATH + "SystemConfig.xlsx"); 45 | // 字段名映射 46 | Map mappingMap = new HashMap(); 47 | mappingMap.put("参数名", "key"); 48 | mappingMap.put("参数值", "value"); 49 | try { 50 | systemConfigMap = ImportExcelUtil.parseExcel(inputStream, "SystemConfig.xlsx", mappingMap, 2); 51 | } catch (Exception e) { 52 | log.error("loadTableConfig error = ", e); 53 | } 54 | log.info("read table SystemConfig, data count = {}", systemConfigMap.size()); 55 | } 56 | 57 | public void reloadTableConfig() { 58 | log.info("------------ reload table config ------------"); 59 | loadTableConfig(); 60 | } 61 | 62 | public Integer getSystemIntConfigByKey(String key) { 63 | if (systemConfigMap.containsKey(key)) { 64 | return Integer.parseInt((String) systemConfigMap.get(key)); 65 | } else { 66 | return null; 67 | } 68 | } 69 | 70 | public String getSystemStringConfigByKey(String key) { 71 | return (String) systemConfigMap.get(key); 72 | } 73 | 74 | @Override 75 | public void shutdown() { 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /game-battle-server/src/main/java/com/jacey/game/battle/service/BattleEventService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.battle.service; 2 | 3 | import com.google.protobuf.GeneratedMessage; 4 | import com.google.protobuf.GeneratedMessageV3; 5 | import com.jacey.game.common.exception.RpcErrorException; 6 | import com.jacey.game.common.proto3.BaseBattle; 7 | import com.jacey.game.common.proto3.RemoteServer; 8 | 9 | /** 10 | * @Description: 用于对战事件处理 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | public interface BattleEventService { 15 | 16 | 17 | /** 18 | * 初始化对战 19 | * @param battleRoomInfo 20 | */ 21 | void initBattle(RemoteServer.BattleRoomInfo battleRoomInfo); 22 | 23 | /** 24 | * 开始第一回合(0回合,特殊处理。由最后准备完成。玩家调用) 25 | * @param battleId 26 | */ 27 | void startFirstTurn(String battleId) throws Exception; 28 | 29 | /** 30 | * 执行事件 31 | * @param battleId 32 | * @param firstEventBuilder 33 | * @return 34 | */ 35 | BaseBattle.EventMsgList.Builder doEvent(String battleId, BaseBattle.EventMsg.Builder firstEventBuilder) throws Exception; 36 | 37 | /** 38 | * 构造事件 39 | * @param battleId 40 | * @param eventType 41 | * @param eventBuilder 42 | * @return 43 | */ 44 | BaseBattle.EventMsg.Builder buildOneEvent(String battleId, BaseBattle.EventTypeEnum eventType, 45 | GeneratedMessageV3.Builder eventBuilder) throws RpcErrorException; 46 | 47 | /** 48 | * 推事事件消息列表给某一对战的所有玩家 49 | * @param battleId 50 | * @param eventMsgListBuilder 51 | */ 52 | void pushEventMsgListToAllBattlePlayers(String battleId, BaseBattle.EventMsgList.Builder eventMsgListBuilder); 53 | 54 | /** 55 | * 推送事件消息列表给某一对战的单个玩家 56 | * @param userId 57 | * @param eventMsgListBuilder 58 | */ 59 | void pushEventMsgListToOneBattlePlayer(int userId, BaseBattle.EventMsgList.Builder eventMsgListBuilder); 60 | 61 | /** 62 | * 推送事件消息列表给某一对战的所有对手 63 | * @param battleId 64 | * @param userId 65 | * @param eventMsgListBuilder 66 | */ 67 | void pushEventMsgListToAllOpponentBattlePlayers(String battleId, int userId, 68 | BaseBattle.EventMsgList.Builder eventMsgListBuilder); 69 | 70 | } 71 | -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "INFO" 3 | 4 | stdout-loglevel = "INFO" 5 | 6 | #log-config-on-start = on 7 | 8 | actor { 9 | provider = "akka.remote.RemoteActorRefProvider" 10 | 11 | allow-java-serialization = off 12 | 13 | serializers { 14 | net = "com.jacey.game.common.msg.serializer.NetMessageSerializer" 15 | remote = "com.jacey.game.common.msg.serializer.RemoteMessageSerializer" 16 | } 17 | 18 | serialization-bindings { 19 | "com.jacey.game.common.msg.NetMessage" = net 20 | "com.jacey.game.common.msg.RemoteMessage" = remote 21 | } 22 | } 23 | 24 | remote { 25 | artery { 26 | enabled = on 27 | transport = tcp 28 | canonical { 29 | port = 40000 30 | hostname = "" 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.jdbc.Driver 4 | username: root 5 | password: 123456 6 | url: jdbc:mysql://localhost/jgame_server?characterEncoding=utf-8&useSSL=false -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | remote.gm.akka.path = akka://gm@192.168.2.193:20000/user/gmActor 2 | 3 | battle.server.id = 1 4 | battle.server.akka.path = akka://battleServer_1@192.168.2.193:40000/user/battleServerActor -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 8 | 9 | 10 | 11 | 13 | log/battle.log 14 | 16 | log/battle-%d{yyyy-MM-dd}.%i.log 17 | 18 | 365 19 | 21 | 1000MB 22 | 23 | 24 | 25 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 33 | 34 | ERROR 35 | 36 | log/battle_error.log 37 | 39 | log/battle_error-%d{yyyy-MM-dd}.%i.log 40 | 41 | 365 42 | 44 | 1000MB 45 | 46 | 47 | 48 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 49 | 50 | UTF-8 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/propertyConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | redis.hostname = 192.168.2.193 2 | redis.port = 6379 3 | redis.password = root -------------------------------------------------------------------------------- /game-battle-server/src/main/resources/tableConfig/SystemConfig.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaceyRx/JGameServer/7b4c877ce8d3dcc1620d435c1c4b57beaddd462d/game-battle-server/src/main/resources/tableConfig/SystemConfig.xlsx -------------------------------------------------------------------------------- /game-chat-server/src/main/java/com/jacey/game/chat/ApplicationReadyEventListener.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.chat; 2 | 3 | import com.jacey.game.chat.manager.*; 4 | import com.jacey.game.common.manager.CoreManager; 5 | import org.springframework.boot.context.event.ApplicationReadyEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | /** 10 | * @Description: manager 统一初始化 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | public class ApplicationReadyEventListener implements ApplicationListener { 15 | 16 | @Override 17 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 18 | ConfigurableApplicationContext context = applicationReadyEvent.getApplicationContext(); 19 | // 设置Spring context上下文 20 | SpringManager.getInstance().setContext(context); 21 | // 核心管理器注册 22 | CoreManager.getInstance().registManager(ConfigManager.getInstance()); 23 | CoreManager.getInstance().registManager(SpringManager.getInstance()); 24 | CoreManager.getInstance().registManager(MessageManager.getInstance()); 25 | CoreManager.getInstance().registManager(OnlineClientManager.getInstance()); 26 | 27 | CoreManager.getInstance().init(); // 对所有manager进行初始化 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /game-chat-server/src/main/java/com/jacey/game/chat/ChatServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.chat; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 9 | 10 | /** 11 | * @Description: 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @SpringBootApplication 16 | @ComponentScan("com.jacey.game") 17 | @EnableJpaRepositories("com.jacey.game.db.repository") 18 | @EntityScan("com.jacey.game.db.entity") 19 | public class ChatServerApplication { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication app = new SpringApplication(ChatServerApplication.class); 23 | app.addListeners(new ApplicationReadyEventListener()); 24 | app.run(args); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /game-chat-server/src/main/java/com/jacey/game/chat/config/SpringConfig.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.chat.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.ImportResource; 5 | 6 | @Configuration 7 | @ImportResource(locations = { "classpath:spring.xml" }) 8 | public class SpringConfig { 9 | 10 | public SpringConfig() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /game-chat-server/src/main/java/com/jacey/game/chat/manager/ConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.chat.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.configuration.Configuration; 6 | import org.apache.commons.configuration.ConfigurationException; 7 | import org.apache.commons.configuration.ConfigurationFactory; 8 | 9 | /** 10 | * @Description: 配置文件加载管理 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class ConfigManager implements IManager { 16 | 17 | private static ConfigManager configManager = new ConfigManager(); 18 | 19 | private static ConfigurationFactory factory; 20 | private static Configuration config; 21 | 22 | public static String REMOTE_GM_AKKA_PATH; // GM服务器Akka path 23 | public static int CHAT_SERVER_ID; // 当前CHAT服务器id 24 | public static String CHAT_SERVER_AKKA_PATH; // CHAT服务器akka oath 25 | 26 | private ConfigManager() {} 27 | 28 | public static ConfigManager getInstance() { 29 | return configManager; 30 | } 31 | 32 | 33 | @Override 34 | public void init() { 35 | log.info("------------ start load config ------------"); 36 | loadConfig(); 37 | log.info("------------ finish load config ------------"); 38 | } 39 | 40 | @Override 41 | public void shutdown() { 42 | 43 | } 44 | 45 | private void loadConfig() { 46 | factory = new ConfigurationFactory("propertyConfig.xml"); 47 | try { 48 | config = factory.getConfiguration(); 49 | } catch (ConfigurationException e) { 50 | log.error("【config初始化失败】, exception = ", e); 51 | System.exit(0); 52 | } 53 | 54 | REMOTE_GM_AKKA_PATH = config.getString("remote.gm.akka.path"); 55 | CHAT_SERVER_ID = config.getInt("chat.server.id"); 56 | CHAT_SERVER_AKKA_PATH = config.getString("chat.server.akka.path"); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /game-chat-server/src/main/java/com/jacey/game/chat/manager/SpringManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.chat.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.data.redis.connection.RedisConnection; 7 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 8 | 9 | /** 10 | * @Description: 处理Spring相关内容 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class SpringManager implements IManager { 16 | 17 | private static SpringManager instance = new SpringManager(); 18 | 19 | public static SpringManager getInstance() { 20 | return instance; 21 | } 22 | 23 | private ConfigurableApplicationContext context; 24 | 25 | @Override 26 | public void init() { 27 | // 检查redis是否已连接 28 | try { 29 | JedisConnectionFactory factory = getBean(JedisConnectionFactory.class); 30 | RedisConnection connection = factory.getConnection(); 31 | if ("PONG".equals(connection.ping()) == false) { 32 | log.error("redis connect fail"); 33 | System.exit(0); 34 | } 35 | } catch (Exception e) { 36 | log.error("redis connect fail, error = ", e); 37 | System.exit(0); 38 | } 39 | 40 | } 41 | 42 | @Override 43 | public void shutdown() { 44 | } 45 | 46 | public Object getBean(String beanName) { 47 | return context.getBean(beanName); 48 | } 49 | 50 | public T getBean(Class object) { 51 | return context.getBean(object); 52 | } 53 | 54 | public void setContext(ConfigurableApplicationContext context) { 55 | this.context = context; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /game-chat-server/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "INFO" 3 | 4 | stdout-loglevel = "INFO" 5 | 6 | #log-config-on-start = on 7 | 8 | actor { 9 | provider = "akka.remote.RemoteActorRefProvider" 10 | 11 | allow-java-serialization = off 12 | 13 | serializers { 14 | net = "com.jacey.game.common.msg.serializer.NetMessageSerializer" 15 | remote = "com.jacey.game.common.msg.serializer.RemoteMessageSerializer" 16 | } 17 | 18 | serialization-bindings { 19 | "com.jacey.game.common.msg.NetMessage" = net 20 | "com.jacey.game.common.msg.RemoteMessage" = remote 21 | } 22 | } 23 | 24 | remote { 25 | artery { 26 | enabled = on 27 | transport = tcp 28 | canonical { 29 | port = 50000 30 | hostname = "" 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /game-chat-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.jdbc.Driver 4 | username: root 5 | password: 123456 6 | url: jdbc:mysql://localhost/jgame_server?characterEncoding=utf-8&useSSL=false -------------------------------------------------------------------------------- /game-chat-server/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | remote.gm.akka.path = akka://gm@192.168.2.193:20000/user/gmActor 2 | 3 | chat.server.id = 1 4 | chat.server.akka.path = akka://chatServer_1@192.168.2.193:50000/user/chatServerActor -------------------------------------------------------------------------------- /game-chat-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 8 | 9 | 10 | 11 | 13 | log/chat.log 14 | 16 | log/chat-%d{yyyy-MM-dd}.%i.log 17 | 18 | 365 19 | 21 | 1000MB 22 | 23 | 24 | 25 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 33 | 34 | ERROR 35 | 36 | log/chat_error.log 37 | 39 | log/chat_error-%d{yyyy-MM-dd}.%i.log 40 | 41 | 365 42 | 44 | 1000MB 45 | 46 | 47 | 48 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 49 | 50 | UTF-8 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /game-chat-server/src/main/resources/propertyConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /game-chat-server/src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | redis.hostname = 192.168.2.193 2 | redis.port = 6379 3 | redis.password = root -------------------------------------------------------------------------------- /game-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | JGameServer 7 | com.jacey.game 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | game-common 13 | 14 | 15 | 16 | 17 | com.typesafe.akka 18 | akka-actor_2.11 19 | 20 | 21 | com.typesafe.akka 22 | akka-remote_2.11 23 | 24 | 25 | 26 | com.google.protobuf 27 | protobuf-java 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-data-redis 33 | 34 | 35 | 36 | org.apache.poi 37 | poi 38 | 3.14 39 | 40 | 41 | org.apache.poi 42 | poi-ooxml 43 | 3.14 44 | 45 | 46 | org.apache.poi 47 | poi-examples 48 | 3.14 49 | 50 | 51 | org.apache.poi 52 | poi-excelant 53 | 3.14 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/action/BaseMessageAction.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.action; 2 | 3 | import com.google.protobuf.MessageLite; 4 | import com.jacey.game.common.msg.IMessage; 5 | import com.jacey.game.common.msg.NetMessage; 6 | import com.jacey.game.common.network.session.ISession; 7 | import lombok.extern.slf4j.Slf4j; 8 | 9 | /** 10 | * @Description: 基础消息处理Action类----所有自定义消息处理Action都应该继承该类 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public abstract class BaseMessageAction { 16 | 17 | protected abstract void LogRequest(IMessage requestMessage) throws Exception; 18 | 19 | protected abstract void LogResponse(IMessage responseMessage) throws Exception; 20 | 21 | protected abstract IMessage doAction(IMessage requestMessage) throws Exception; 22 | 23 | /** 24 | * Action消息处理主方法 25 | * @param requestMessage 26 | * @throws Exception 27 | */ 28 | public IMessage handleMessage(IMessage requestMessage) throws Exception { 29 | LogRequest(requestMessage); 30 | 31 | IMessage responseMessage = doAction(requestMessage); 32 | 33 | LogResponse(responseMessage); 34 | 35 | return responseMessage; 36 | } 37 | 38 | protected IMessage buildResponseNetMsg(int userId, int rpcName, MessageLite.Builder builder) { 39 | NetMessage message = new NetMessage(rpcName, builder); 40 | message.setUserId(userId); 41 | return message; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/annotation/MessageClassMapping.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 用于Action类上的注解,标记该Action类处理哪个客户端请求 10 | */ 11 | @Target(ElementType.TYPE) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface MessageClassMapping { 14 | 15 | int value(); 16 | 17 | boolean isNet() default true; 18 | } 19 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/annotation/MessageMethodMapping.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | 9 | /** 10 | * 用于函数注解,标记该函数处理哪些消息 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface MessageMethodMapping { 15 | 16 | int[] value(); 17 | 18 | boolean isNet() default false; 19 | } 20 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/constants/CookieConstant.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.constants; 2 | 3 | /** 4 | * @Description: TODO 5 | * @Author: JaceyRuan 6 | * @Email: jacey.ruan@outlook.com 7 | */ 8 | public class CookieConstant { 9 | 10 | public static final String TOKEN = "token"; 11 | 12 | /** 过期时间(单位:s) */ 13 | public static final Integer expire = 7200; 14 | } 15 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/constants/GlobalConstant.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.constants; 2 | 3 | public class GlobalConstant { 4 | 5 | public static final String GATEWAY_ACTOR_NAME = "gatewayActor"; 6 | public static final String LOGIC_SERVER_ACTOR_NAME = "logicServerActor"; 7 | public static final String BATTLE_SERVER_ACTOR_NAME = "battleServerActor"; 8 | public static final String CHAT_SERVER_ACTOR_NAME = "chatServerActor"; 9 | public static final String GM_ACTOR_NAME = "gmActor"; 10 | 11 | public static final String GATEWAY_SYSTEM_PREFIX = "gateway_"; 12 | public static final String LOGIC_SERVER_SYSTEM_PREFIX = "logicServer_"; 13 | public static final String BATTLE_SERVER_SYSTEM_PREFIX = "battleServer_"; 14 | public static final String CHAT_SERVER_SYSTEM_PREFIX = "chatServer_"; 15 | public static final String GM_SYSTEM_NAME = "gm"; 16 | } 17 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/constants/SystemConfigKeyConstant.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.constants; 2 | 3 | public class SystemConfigKeyConstant { 4 | 5 | public static final String USERNAME_MAX_LENGTH = "usernameMaxLength"; 6 | public static final String PASSWORD_MIN_LENGTH = "passwordMinLength"; 7 | public static final String PASSWORD_MAX_LENGTH = "passwordMaxLength"; 8 | public static final String NICKNAME_MAX_LENGTH = "nicknameMaxLength"; 9 | public static final String READY_TO_START_GAME_SECOND = "readyToStartGameSecond"; 10 | public static final String TURN_SECOND = "turnSecond"; 11 | } 12 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/exception/RpcErrorException.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.exception; 2 | 3 | /** 4 | * @Description: 自定义异常类 5 | * @Author: JaceyRuan 6 | * @Email: jacey.ruan@outlook.com 7 | */ 8 | public class RpcErrorException extends Exception { 9 | 10 | private static final long serialVersionUID = -7443764564324073078L; 11 | 12 | protected int errorCode; 13 | 14 | public RpcErrorException(int errorCode) { 15 | super(String.valueOf(errorCode)); 16 | this.errorCode = errorCode; 17 | } 18 | 19 | public int getErrorCode() { 20 | return errorCode; 21 | } 22 | 23 | public void setErrorCode(int errorCode) { 24 | this.errorCode = errorCode; 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/manager/CoreManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.manager; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | 7 | /** 8 | * @Description: 核心管理器--用于统一管理Manager(初始化与关闭) 9 | * @Author: JaceyRuan 10 | * @Email: jacey.ruan@outlook.com 11 | */ 12 | public class CoreManager implements IManager { 13 | 14 | private static CoreManager instance = new CoreManager(); 15 | private List allManagers = new ArrayList(); 16 | 17 | public static CoreManager getInstance() { 18 | return instance; 19 | } 20 | 21 | /** 22 | * 初始化每一个manager 23 | */ 24 | @Override 25 | public void init() { 26 | for (IManager m : allManagers) { 27 | m.init(); 28 | } 29 | } 30 | 31 | @Override 32 | public void shutdown() { 33 | int size = allManagers.size(); 34 | for (int i = size - 1; i >= 0; --i) { 35 | allManagers.get(i).shutdown(); 36 | } 37 | } 38 | 39 | public void registManager(IManager m) { 40 | allManagers.add(m); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/manager/IManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.manager; 2 | 3 | /** 4 | * @Description: 管理器接口抽象 5 | * @Author: JaceyRuan 6 | * @Email: jacey.ruan@outlook.com 7 | */ 8 | public interface IManager { 9 | 10 | void init(); 11 | 12 | void shutdown(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/AbstractMessage.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | 5 | /** 6 | * @Description: IMessage 接口方法的抽象实现 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public abstract class AbstractMessage implements IMessage { 11 | 12 | protected int rpcNum; 13 | protected Object lite; 14 | 15 | @Override 16 | public int getRpcNum() { 17 | return rpcNum; 18 | } 19 | 20 | @Override 21 | public void setRpcNum(int rpcNum) { 22 | this.rpcNum = rpcNum; 23 | } 24 | 25 | @Override 26 | public Object getLite() { 27 | return lite; 28 | } 29 | 30 | @Override 31 | public void setLite(Object lite) { 32 | this.lite = lite; 33 | } 34 | 35 | @Override 36 | public ByteBuf toBinaryMsg() { 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/IMessage.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | 5 | /** 6 | * @Description: 消息载体结构声明 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface IMessage { 11 | 12 | /** 13 | * 获取协议号 14 | * @return 15 | */ 16 | int getRpcNum(); 17 | 18 | /** 19 | * 设置协议编号 20 | * @param rpcNum 21 | */ 22 | void setRpcNum(int rpcNum); 23 | 24 | /** 25 | * 获取protobuf Lite对象 26 | * @return 27 | */ 28 | Object getLite(); 29 | 30 | /** 31 | * 设置protobuf Lite对象 32 | * @param lite 33 | */ 34 | void setLite(Object lite); 35 | 36 | /** 37 | * 转换成传输的二进制消息 38 | * @return 39 | */ 40 | ByteBuf toBinaryMsg(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/LocalMessage.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @Description: 内部服务器通讯实体 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public class LocalMessage extends AbstractMessage implements Serializable { 11 | 12 | private static final long serialVersionUID = -6314048852403909677L; 13 | 14 | public LocalMessage(int rpcNum) { 15 | this.rpcNum = rpcNum; 16 | } 17 | 18 | public LocalMessage(int rpcNum, Object lite) { 19 | this.rpcNum = rpcNum; 20 | this.lite = lite; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/NetResponseMessage.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @Description: 用于ChannelActor 区分远程服务器响应 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | @Getter 12 | @Setter 13 | public class NetResponseMessage { 14 | 15 | private NetMessage netMessage; 16 | 17 | public NetResponseMessage(NetMessage netMessage) { 18 | this.netMessage = netMessage; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/RemoteMessage.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg; 2 | 3 | import com.google.protobuf.MessageLite; 4 | import com.google.protobuf.MessageOrBuilder; 5 | import com.google.protobuf.TextFormat; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.lang.reflect.Method; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * @Description: 服务器之间通选的消息载体,用于GM服务器、逻辑服务器、对战服务器、网关服务器之间的通讯 16 | * @Author: JaceyRuan 17 | * @Email: jacey.ruan@outlook.com 18 | */ 19 | @Slf4j 20 | @Getter 21 | @Setter 22 | public class RemoteMessage extends AbstractMessage { 23 | 24 | /** 消息内容body */ 25 | private byte[] data; 26 | /** 错误代码 */ 27 | private int errorCode; 28 | 29 | public RemoteMessage() { 30 | } 31 | 32 | public RemoteMessage(int RpcNum, MessageLite lite) { 33 | this.rpcNum = RpcNum; 34 | this.errorCode = 0; 35 | this.data = lite.toByteArray(); 36 | } 37 | 38 | public RemoteMessage(int RpcNum, MessageLite.Builder builder) { 39 | this.rpcNum = RpcNum; 40 | this.errorCode = 0; 41 | this.data = builder.build().toByteArray(); 42 | } 43 | 44 | public RemoteMessage(int RpcNum, byte[] data) { 45 | this.rpcNum = RpcNum; 46 | this.errorCode = 0; 47 | this.data = data; 48 | } 49 | 50 | public RemoteMessage(int RpcNum, int errorCode) { 51 | this.rpcNum = RpcNum; 52 | this.errorCode = errorCode; 53 | this.data = null; 54 | } 55 | 56 | /** 57 | * 获取数据长度 58 | * @return 59 | */ 60 | public int getDataLength() { 61 | return data == null ? 0 : data.length; 62 | } 63 | 64 | /** 65 | * 获取数据包总长度 66 | * 包含总字节数、协议名数字、errorCode(前3部分每部分都是4字节)、protobuf二进制部分 67 | * @return 68 | */ 69 | public int getTotalLength() { 70 | return 12 + getDataLength(); 71 | } 72 | 73 | /** 内部类,用于缓存加载过的protobuf Lite */ 74 | private static class MessageLiteCache { 75 | static final Map cache = new HashMap(); 76 | 77 | private MessageLiteCache() { 78 | } 79 | } 80 | 81 | /** 82 | * 通过反射生成protobuf对象 83 | * @param clz 84 | * @param 85 | * @return 86 | */ 87 | public T getLite(Class clz) { 88 | try { 89 | MessageLite prototype = MessageLiteCache.cache.get(clz.getName()); 90 | if (prototype == null) { 91 | // 反射生成protobuf对象 92 | Method method = clz.getMethod("getDefaultInstance"); 93 | prototype = (MessageLite) method.invoke(null); 94 | MessageLiteCache.cache.put(clz.getName(), prototype); 95 | } 96 | if (prototype != null) { 97 | return (T) prototype.newBuilderForType().mergeFrom(data).buildPartial(); 98 | } 99 | } catch (Throwable t) { 100 | log.error("getLite error = ", t); 101 | } 102 | return null; 103 | } 104 | 105 | /** 106 | * 获取protobuf 文本 107 | * @param clz 108 | * @param 109 | * @return 110 | */ 111 | public String getProtobufText(Class clz) { 112 | try { 113 | MessageLite prototype = MessageLiteCache.cache.get(clz.getName()); 114 | if (prototype == null) { 115 | Method method = clz.getMethod("getDefaultInstance"); 116 | prototype = (MessageLite) method.invoke(null); 117 | MessageLiteCache.cache.put(clz.getName(), prototype); 118 | } 119 | if (prototype != null) { 120 | return TextFormat.printToUnicodeString((T) prototype.newBuilderForType().mergeFrom(data)); 121 | } 122 | } catch (Throwable t) { 123 | log.error("getProtobufText error = ", t); 124 | } 125 | 126 | return null; 127 | } 128 | 129 | 130 | } 131 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/serializer/NetMessageSerializer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg.serializer; 2 | 3 | import akka.serialization.Serializer; 4 | import com.jacey.game.common.msg.NetMessage; 5 | import scala.Option; 6 | 7 | import java.io.NotSerializableException; 8 | import java.nio.ByteBuffer; 9 | 10 | // 编解码规则:4字节协议名数字、4字节errorCode,4字节sessionId,4字节userId,4字节userIp的长度,之后如果发userIp,则是string转为的二进制,最后是protobuf二进制数据 11 | public class NetMessageSerializer implements Serializer { 12 | 13 | public NetMessageSerializer() { 14 | } 15 | 16 | private NetMessage toMsg(byte[] array) { 17 | NetMessage msg = new NetMessage(); 18 | int totalLength = array.length; 19 | ByteBuffer bb = ByteBuffer.wrap(array); 20 | msg.setRpcNum(bb.getInt()); 21 | msg.setErrorCode(bb.getInt()); 22 | msg.setSessionId(bb.getInt()); 23 | msg.setUserId(bb.getInt()); 24 | int ipLength = bb.getInt(); 25 | if (ipLength > 0) { 26 | byte[] ipBytes = new byte[ipLength]; 27 | bb.get(ipBytes); 28 | msg.setUserIp(new String(ipBytes)); 29 | } 30 | byte[] bytes = new byte[totalLength - ipLength - 20]; 31 | bb.get(bytes); 32 | msg.setData(bytes); 33 | return msg; 34 | } 35 | 36 | @Override 37 | public byte[] toBinary(Object arg0) { 38 | NetMessage msg = (NetMessage) arg0; 39 | 40 | int ipLength = 0; 41 | byte[] ipBytes = null; 42 | if (msg.getUserIp() != null) { 43 | ipBytes = msg.getUserIp().getBytes(); 44 | ipLength = ipBytes.length; 45 | } 46 | 47 | int totalLength = 20 + ipLength + msg.getDataLength(); 48 | ByteBuffer bb = ByteBuffer.allocate(totalLength); 49 | bb.putInt(msg.getRpcNum()); 50 | bb.putInt(msg.getErrorCode()); 51 | bb.putInt(msg.getSessionId()); 52 | bb.putInt(msg.getUserId()); 53 | bb.putInt(ipLength); 54 | if (ipBytes != null) { 55 | bb.put(ipBytes); 56 | } 57 | if (msg.getData() != null) { 58 | bb.put(msg.getData()); 59 | } 60 | return bb.array(); 61 | } 62 | 63 | @Override 64 | public Object fromBinary(byte[] arg0) { 65 | return toMsg(arg0); 66 | } 67 | 68 | @Override 69 | public Object fromBinary(byte[] arg0, Option> arg1) throws NotSerializableException { 70 | return toMsg(arg0); 71 | } 72 | 73 | @Override 74 | public Object fromBinary(byte[] arg0, Class arg1) throws NotSerializableException { 75 | return toMsg(arg0); 76 | } 77 | 78 | // 0-40被akka占用 79 | @Override 80 | public int identifier() { 81 | return 77; 82 | } 83 | 84 | @Override 85 | public boolean includeManifest() { 86 | return false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/msg/serializer/RemoteMessageSerializer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.msg.serializer; 2 | 3 | import akka.serialization.Serializer; 4 | import com.jacey.game.common.msg.RemoteMessage; 5 | import scala.Option; 6 | 7 | import java.io.NotSerializableException; 8 | import java.nio.ByteBuffer; 9 | 10 | // 编解码规则:4字节协议名数字、4字节errorCode,剩下的是protobuf二进制数据 11 | public class RemoteMessageSerializer implements Serializer { 12 | 13 | public RemoteMessageSerializer() { 14 | } 15 | 16 | private RemoteMessage toMsg(byte[] array) { 17 | RemoteMessage msg = new RemoteMessage(); 18 | int totalLength = array.length; 19 | ByteBuffer bb = ByteBuffer.wrap(array); 20 | msg.setRpcNum(bb.getInt()); 21 | msg.setErrorCode(bb.getInt()); 22 | byte[] bytes = new byte[totalLength - 8]; 23 | bb.get(bytes); 24 | msg.setData(bytes); 25 | return msg; 26 | } 27 | 28 | @Override 29 | public byte[] toBinary(Object arg0) { 30 | RemoteMessage msg = (RemoteMessage) arg0; 31 | ByteBuffer bb = ByteBuffer.allocate(8 + msg.getDataLength()); 32 | bb.putInt(msg.getRpcNum()); 33 | bb.putInt(msg.getErrorCode()); 34 | if (msg.getData() != null) { 35 | bb.put(msg.getData()); 36 | } 37 | return bb.array(); 38 | } 39 | 40 | @Override 41 | public Object fromBinary(byte[] arg0) { 42 | return toMsg(arg0); 43 | } 44 | 45 | @Override 46 | public Object fromBinary(byte[] arg0, Option> arg1) throws NotSerializableException { 47 | return toMsg(arg0); 48 | } 49 | 50 | @Override 51 | public Object fromBinary(byte[] arg0, Class arg1) throws NotSerializableException { 52 | return toMsg(arg0); 53 | } 54 | 55 | // 0-40被akka占用 56 | @Override 57 | public int identifier() { 58 | return 78; 59 | } 60 | 61 | @Override 62 | public boolean includeManifest() { 63 | return false; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/network/session/ISession.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.network.session; 2 | 3 | import com.jacey.game.common.msg.IMessage; 4 | 5 | /** 6 | * @Description: 自定义Session.结构声明接口 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface ISession { 11 | 12 | /** 13 | * 写数据 14 | * @param message 15 | */ 16 | void write(IMessage message); 17 | 18 | /** 19 | * 关闭session 20 | */ 21 | void close(); 22 | 23 | /** 24 | * 获取ip 25 | * @return 26 | */ 27 | String getRemotePath(); 28 | 29 | /** 30 | * 获取sessionId 31 | * @return 32 | */ 33 | long getSessionId(); 34 | 35 | /** 36 | * 根据key获取数据 37 | * @param key 38 | * @return 39 | */ 40 | Object getData(String key); 41 | 42 | /** 43 | * 存储数据 44 | * @param key 45 | * @param value 46 | */ 47 | void putData(String key, Object value); 48 | 49 | /** 50 | * 是否含有数据 51 | * @param key 52 | * @return 53 | */ 54 | boolean hasData(String key); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/utils/DateTimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.utils; 2 | 3 | import java.sql.Timestamp; 4 | import java.time.*; 5 | import java.time.format.DateTimeFormatter; 6 | import java.util.Date; 7 | 8 | public class DateTimeUtil { 9 | 10 | private static final ZoneOffset zdefaultZoneOffset = OffsetDateTime.now().getOffset(); 11 | private static final ZoneId defaultZoneId = ZoneId.systemDefault(); 12 | private static final DateTimeFormatter defaultDateTimeFormatter = DateTimeFormatter 13 | .ofPattern("yyyy-MM-dd HH:mm:ss"); 14 | 15 | public static long instantToTimestamp(Instant instant) { 16 | return instant.toEpochMilli(); 17 | } 18 | 19 | public static Instant timestampToInstant(long timestamp) { 20 | return Instant.ofEpochMilli(timestamp); 21 | } 22 | 23 | public static Instant localDateTimeToInstant(LocalDateTime localDateTime) { 24 | return localDateTime.toInstant(zdefaultZoneOffset); 25 | } 26 | 27 | public static LocalDateTime instantTolocalDateTime(Instant instant) { 28 | return LocalDateTime.ofInstant(instant, defaultZoneId); 29 | } 30 | 31 | public static LocalDateTime timestampToLocalDateTime(long timestamp) { 32 | return instantTolocalDateTime(timestampToInstant(timestamp)); 33 | } 34 | 35 | public static long localDateTimeToTimestamp(LocalDateTime localDateTime) { 36 | return instantToTimestamp(localDateTimeToInstant(localDateTime)); 37 | } 38 | 39 | public static String localDateTimeToDateTimeString(LocalDateTime localDateTime) { 40 | return localDateTime.format(defaultDateTimeFormatter); 41 | } 42 | 43 | public static LocalDateTime dateTimeStringToLocalDateTime(String dateTimeString) { 44 | return LocalDateTime.parse(dateTimeString, defaultDateTimeFormatter); 45 | } 46 | 47 | public static long getCurrentTimestamp() { 48 | return Instant.now().toEpochMilli(); 49 | } 50 | 51 | public static long getTodayZeroClockTimestamp() { 52 | LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN); 53 | return localDateTimeToTimestamp(localDateTime); 54 | } 55 | 56 | public static long dateToTimestamp(Date date) { 57 | Instant instant = date.toInstant(); 58 | LocalDateTime localDateTime = instant.atZone(defaultZoneId).toLocalDateTime(); 59 | return localDateTimeToTimestamp(localDateTime); 60 | } 61 | 62 | public static Date timestampToDate(long timestamp) { 63 | Timestamp t = new Timestamp(timestamp); 64 | Date d = new Date(t.getTime()); 65 | return d; 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | import java.security.MessageDigest; 8 | import java.security.NoSuchAlgorithmException; 9 | 10 | public class MD5Util { 11 | 12 | private static final Logger logger = LoggerFactory.getLogger(MD5Util.class); 13 | 14 | private static MessageDigest md5; 15 | 16 | private static char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 17 | 'f' }; 18 | static { 19 | try { 20 | md5 = MessageDigest.getInstance("MD5"); 21 | } catch (NoSuchAlgorithmException e) { 22 | logger.error("init fail, error = ", e); 23 | } 24 | } 25 | 26 | private static String md5(String str, String charset) { 27 | StringBuilder sb = new StringBuilder(); 28 | try { 29 | byte[] bb = md5.digest(str.getBytes(charset)); 30 | for (byte b : bb) { 31 | sb.append(hexDigits[b >>> 4 & 0xf]); 32 | sb.append(hexDigits[b & 0xf]); 33 | } 34 | } catch (UnsupportedEncodingException e) { 35 | logger.error("md5 error, error = ", e); 36 | } 37 | 38 | return sb.toString(); 39 | } 40 | 41 | public static String md5(byte[] data) { 42 | StringBuilder sb = new StringBuilder(); 43 | byte[] bb = md5.digest(data); 44 | for (byte b : bb) { 45 | sb.append(hexDigits[b >>> 4 & 0xf]); 46 | sb.append(hexDigits[b & 0xf]); 47 | } 48 | return sb.toString().toUpperCase(); 49 | } 50 | 51 | public static String md5(String str) { 52 | return md5(str, "UTF-8").toUpperCase(); 53 | } 54 | 55 | public static void main(String[] args) { 56 | System.out.println(md5("admin")); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /game-common/src/main/java/com/jacey/game/common/utils/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.common.utils; 2 | 3 | import java.util.Collection; 4 | 5 | public class StringUtil { 6 | 7 | public static boolean isNullOrEmpty(String str) { 8 | return str == null || "".equals(str); 9 | } 10 | 11 | public static boolean isDigitChar(char c) { 12 | return c >= '0' && c <= '9'; 13 | } 14 | 15 | public static boolean isLetterChar(char c) { 16 | return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 17 | } 18 | 19 | public static boolean isBaseChineseChar(char c) { 20 | return c >= '\u4E00' && c <= '\u9FA5'; 21 | } 22 | 23 | public static String getCollectionMemberString(Collection collection, String splitString) { 24 | if (collection == null || collection.size() == 0) { 25 | return ""; 26 | } else { 27 | if (StringUtil.isNullOrEmpty(splitString)) { 28 | splitString = ","; 29 | } 30 | StringBuilder sb = new StringBuilder(); 31 | for (T t : collection) { 32 | sb.append(t.toString()).append(splitString); 33 | } 34 | // 去掉末尾多加的一次分隔符 35 | sb.delete(sb.length() - splitString.length(), sb.length()); 36 | return sb.toString(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /game-db/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | JGameServer 7 | com.jacey.game 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | game-db 13 | jar 14 | 15 | 16 | 17 | com.jacey.game 18 | game-common 19 | 20 | 21 | 22 | 23 | redis.clients 24 | jedis 25 | 2.9.0 26 | 27 | 28 | 29 | com.google.protobuf 30 | protobuf-java 31 | 32 | 33 | 34 | com.esotericsoftware 35 | reflectasm 36 | 37 | 38 | 39 | com.google.guava 40 | guava 41 | 25.1-jre 42 | 43 | 44 | 45 | commons-configuration 46 | commons-configuration 47 | 48 | 49 | 50 | com.fasterxml.jackson.core 51 | jackson-databind 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-data-jpa 57 | 58 | 59 | 60 | mysql 61 | mysql-connector-java 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/constants/BattleRedisKeyConstant.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.constants; 2 | 3 | public class BattleRedisKeyConstant { 4 | 5 | // 当前进行中的对战battleId集合(set类型,value:进行中的对战battleId) 6 | public static final String BATTLE_PLAYING_BATTLE_IDS = "battlePlayingBattleIds"; 7 | // 一场战斗中按先后手顺利排列的userId(list类型,value:先后手顺利排列的userId) 8 | public static final String BATTLE_USER_IDS = "battleUserIds"; 9 | // 一场战斗中当前回合的信息(map类型,key:battleId, value:protobuf定义的CurrentTurnInfo) 10 | public static final String BATTLE_CURRENT_TURN_INFO = "battleCurrentTurnInfo"; 11 | // 一场战斗中当前棋盘中棋子信息(list类型,value:按下标位置排列的对应格子的棋子情况) 12 | public static final String BATTLE_CELL_INFO = "battleCellInfo"; 13 | // 一场战斗中发生的所有事件(list类型,value:protobuf定义的EventMsg) 14 | public static final String BATTLE_EVENT_LIST = "battleEventList"; 15 | // 一场战斗中上一个已发生事件的eventNum(map类型,key:battleId, value:该战场中上一个已发生事件的eventNum) 16 | public static final String BATTLE_LAST_EVENT_NUM = "battleLastEventNum"; 17 | // 一场战斗开始的时间戳(map类型,key:battleId, value:开始的时间戳) 18 | public static final String BATTLE_START_TIMESTAMP = "battleStartTimestamp"; 19 | // 一场战斗尚未准备开始游戏(为了照顾有些客户端可能载入资源过慢,在一定时限内,所有玩家都准备就绪后再正式开始对战)的玩家userId(set类型,value:尚未准备开始游戏的玩家userId) 20 | public static final String BATTLE_NOT_READY_USER_IDS = "battleNotReadyUserIds"; 21 | // 某日的对战战报(list类型,value:protobuf定义的BattleRecordData) 22 | public static final String BATTLE_RECORD_LIST = "battleRecordList"; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/constants/BattleRedisKeyHelper.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.constants; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.jacey.game.common.proto3.CommonEnum; 5 | 6 | public class BattleRedisKeyHelper { 7 | 8 | private static final String SPRITE_STRING = ":"; 9 | private static final Joiner joiner = Joiner.on(SPRITE_STRING); 10 | 11 | public static String join(Object... strs) { 12 | return joiner.join(strs); 13 | } 14 | 15 | public static String getBattlePlayingBattleIdsRedisKey(CommonEnum.BattleTypeEnum battleType) { 16 | return join(BattleRedisKeyConstant.BATTLE_PLAYING_BATTLE_IDS, battleType.getNumber()); 17 | } 18 | 19 | public static String getBattleUserIdsRedisKey(String battleId) { 20 | return join(BattleRedisKeyConstant.BATTLE_USER_IDS, battleId); 21 | } 22 | 23 | public static String getBattleCurrentTurnInfoRedisKey() { 24 | return BattleRedisKeyConstant.BATTLE_CURRENT_TURN_INFO; 25 | } 26 | 27 | public static String getBattleCellInfoRedisKey(String battleId) { 28 | return join(BattleRedisKeyConstant.BATTLE_CELL_INFO, battleId); 29 | } 30 | 31 | public static String getBattleEventListRedisKey(String battleId) { 32 | return join(BattleRedisKeyConstant.BATTLE_EVENT_LIST, battleId); 33 | } 34 | 35 | public static String getBattleStartTimestampRedisKey() { 36 | return BattleRedisKeyConstant.BATTLE_START_TIMESTAMP; 37 | } 38 | 39 | public static String getBattleLastEventNumRedisKey() { 40 | return BattleRedisKeyConstant.BATTLE_LAST_EVENT_NUM; 41 | } 42 | 43 | public static String getBattleNotReadyUserIdsRedisKey(String battleId) { 44 | return join(BattleRedisKeyConstant.BATTLE_NOT_READY_USER_IDS, battleId); 45 | } 46 | 47 | public static String getBattleRecordListRedisKey(CommonEnum.BattleTypeEnum battleType, long oneDayZeroClockTimestamp) { 48 | return join(BattleRedisKeyConstant.BATTLE_RECORD_LIST, battleType.getNumber(), oneDayZeroClockTimestamp); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/constants/GmRedisKeyConstant.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.constants; 2 | 3 | /** 4 | * @Description: TODO 5 | * @Author: JaceyRuan 6 | * @Email: jacey.ruan@outlook.com 7 | */ 8 | public class GmRedisKeyConstant { 9 | 10 | // 当前进行中的对战battleId集合(set类型,value:进行中的对战battleId) 11 | public static final String GM_USER_TOKEN = "gmUserToken"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/constants/GmRedisKeyHelper.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.constants; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.jacey.game.common.proto3.CommonEnum; 5 | 6 | /** 7 | * @Description: TODO 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public class GmRedisKeyHelper { 12 | 13 | private static final String SPRITE_STRING = ":"; 14 | private static final Joiner joiner = Joiner.on(SPRITE_STRING); 15 | 16 | public static String join(Object... strs) { 17 | return joiner.join(strs); 18 | } 19 | 20 | public static String getGmUserTokeRedisKey(String tokenKey) { 21 | return join(GmRedisKeyConstant.GM_USER_TOKEN, tokenKey); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/constants/RedisKeyConstant.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.constants; 2 | 3 | public class RedisKeyConstant { 4 | 5 | // 客户端自增的sessionId(value类型,自增的sessionId) 6 | public static final String SESSION_ID_AUTO_INCREASE = "sessionIdAutoIncrease"; 7 | // 在线客户端所连的gatewayId(map类型,key:sessionId, value:gatewayId) 8 | public static final String SESSION_ID_TO_GATEWAY_ID = "sessionIdToGatewayId"; 9 | // 在线客户端对应UserActor所在的logic服务器(map类型,key:sessionId, value:logicServerId) 10 | public static final String SESSION_ID_TO_LOGIC_SERVER_ID = "sessionIdToLogicServerId"; 11 | // 已登录成功玩家userId与sessionId的对应关系(map类型,key:userId, value:sessionId) 12 | public static final String USER_ID_TO_SESSION_ID = "userIdToSessionId"; 13 | // 已登录成功玩家sessionId与userId的对应关系(map类型,key:sessionId, value:userId) 14 | public static final String SESSION_ID_TO_USER_ID = "sessionIdToUserId"; 15 | // 对战中的玩家userId与battleId的对应关系(map类型,key:userId, value:battleId) 16 | public static final String BATTLE_USER_ID_TO_BATTLE_ID = "battleUserIdToBattleId"; 17 | // 进行中的battleId与处理这场战斗的battleServerId的对应关系(map类型,key:battleId, value:battleServerId) 18 | public static final String BATTLE_ID_TO_BATTLE_SERVER_ID = "battleIdToBattleServerId"; 19 | // 进行中的battleId与聊天服务器的绑定关系(map类型,key:battleId, value:battleServerId) 20 | public static final String BATTLE_ID_TO_CHAT_SERVER_ID = "battleIdToChatServerId"; 21 | // logic服务器的负载(zset类型,score:服务器负载, value:logicServerId) 22 | public static final String LOGIC_SERVER_LOAD_BALANCE = "logicServerLoadBalance"; 23 | // gateway服务器的负载(zset类型,score:服务器负载, value:gatewayId) 24 | public static final String GATEWAY_LOAD_BALANCE = "gatewayLoadBalance"; 25 | // battle服务器的负载(zset类型,score:服务器负载, value:battleServerId) 26 | public static final String BATTLE_SERVER_LOAD_BALANCE = "battleServerLoadBalance"; 27 | // chat服务器的负载(zset类型,score:服务器负载, value:chatServerId) 28 | public static final String CHAT_SERVER_LOAD_BALANCE = "chatServerLoadBalance"; 29 | // 已注册到GM服务器的logic服务器id对应的akka地址(map类型,key:logicServerId, value:akka地址) 30 | public static final String LOGIC_SERVER_ID_TO_AKKA_PATH = "logicServerIdToAkkaPath"; 31 | // 已注册到GM服务器的gateway服务器id对应的akka地址(map类型,key:gatewayId, value:akka地址) 32 | public static final String GATEWAY_ID_TO_AKKA_PATH = "gatewayIdToAkkaPath"; 33 | // 已注册到GM服务器的battle服务器id对应的akka地址(map类型,key:battleServerId, value:akka地址) 34 | public static final String BATTLE_SERVER_ID_TO_AKKA_PATH = "battleServerIdToAkkaPath"; 35 | // 已注册到GM服务器的chat服务器id对应的akka地址(map类型,key:chatServerId, value:akka地址) 36 | public static final String CHAT_SERVER_ID_TO_AKKA_PATH = "chatServerIdToAkkaPath"; 37 | // 已注册到GM服务器的gateway服务器id对应的供客户端连接的地址(map类型,key:gatewayId, value:供客户端连接的地址) 38 | public static final String GATEWAY_ID_TO_CONNECT_PATH = "gatewayIdToConnectPath"; 39 | // 已注册到GM服务器的主logic服务器id(value类型,mainLogicServerId) 40 | public static final String MAIN_LOGIC_SERVER_ID = "mainLogicServerId"; 41 | 42 | // 玩家自增的userId(value类型,自增的userId) 43 | public static final String USER_ID_AUTO_INCREASE = "userIdAutoIncrease"; 44 | // 玩家信息(map类型,key:userId, value:protobuf定义的UserData) 45 | public static final String USER_DATA = "userData"; 46 | // 玩家名与userId的对应关系(map类型,key:username, value:userId) 47 | public static final String USERNAME_TO_ID = "usernameToId"; 48 | // 玩家状态(map类型,key:userId, value:protobuf定义的UserState) 49 | public static final String USER_STATE = "userState"; 50 | } 51 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/constants/RedisKeyHelper.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.constants; 2 | 3 | import com.google.common.base.Joiner; 4 | 5 | public class RedisKeyHelper { 6 | 7 | private static final String SPRITE_STRING = ":"; 8 | private static final Joiner joiner = Joiner.on(SPRITE_STRING); 9 | 10 | public static String join(Object... strs) { 11 | return joiner.join(strs); 12 | } 13 | 14 | public static String getSessionIdAutoIncreaseRedisKey() { 15 | return RedisKeyConstant.SESSION_ID_AUTO_INCREASE; 16 | } 17 | 18 | public static String getSessionIdToGatewayIdRedisKey() { 19 | return RedisKeyConstant.SESSION_ID_TO_GATEWAY_ID; 20 | } 21 | 22 | public static String getSessionIdToLogicServerIdRedisKey() { 23 | return RedisKeyConstant.SESSION_ID_TO_LOGIC_SERVER_ID; 24 | } 25 | 26 | public static String getUserIdToSessionIdRedisKey() { 27 | return RedisKeyConstant.USER_ID_TO_SESSION_ID; 28 | } 29 | 30 | public static String getSessionIdToUserIdRedisKey() { 31 | return RedisKeyConstant.SESSION_ID_TO_USER_ID; 32 | } 33 | 34 | public static String getBattleUserIdToBattleIdRedisKey() { 35 | return RedisKeyConstant.BATTLE_USER_ID_TO_BATTLE_ID; 36 | } 37 | 38 | public static String getBattleIdToBattleServerIdRedisKey() { 39 | return RedisKeyConstant.BATTLE_ID_TO_BATTLE_SERVER_ID; 40 | } 41 | 42 | public static String getBattleIdToChatServerIdRedisKey() { 43 | return RedisKeyConstant.BATTLE_ID_TO_CHAT_SERVER_ID; 44 | } 45 | 46 | public static String getLogicServerLoadBalanceRedisKey() { 47 | return RedisKeyConstant.LOGIC_SERVER_LOAD_BALANCE; 48 | } 49 | 50 | public static String getGatewayLoadBalanceRedisKey() { 51 | return RedisKeyConstant.GATEWAY_LOAD_BALANCE; 52 | } 53 | 54 | public static String getBattleServerLoadBalanceRedisKey() { 55 | return RedisKeyConstant.BATTLE_SERVER_LOAD_BALANCE; 56 | } 57 | /** chatServer 负载key */ 58 | public static String getChatServerLoadBalanceRedisKey() { 59 | return RedisKeyConstant.CHAT_SERVER_LOAD_BALANCE; 60 | } 61 | 62 | public static String getUserIdAutoIncreaseRedisKey() { 63 | return RedisKeyConstant.USER_ID_AUTO_INCREASE; 64 | } 65 | 66 | public static String getUserDataRedisKey() { 67 | return RedisKeyConstant.USER_DATA; 68 | } 69 | 70 | public static String getUsernameToIdRedisKey() { 71 | return RedisKeyConstant.USERNAME_TO_ID; 72 | } 73 | 74 | public static String getUserStateRedisKey() { 75 | return RedisKeyConstant.USER_STATE; 76 | } 77 | 78 | public static String getLogicServerIdToAkkaPathRedisKey() { 79 | return RedisKeyConstant.LOGIC_SERVER_ID_TO_AKKA_PATH; 80 | } 81 | 82 | public static String getGatewayIdToAkkaPathRedisKey() { 83 | return RedisKeyConstant.GATEWAY_ID_TO_AKKA_PATH; 84 | } 85 | 86 | public static String getBattleServerIdToAkkaPathRedisKey() { 87 | return RedisKeyConstant.BATTLE_SERVER_ID_TO_AKKA_PATH; 88 | } 89 | 90 | public static String getChatServerIdToAkkaPathRedisKey() { 91 | return RedisKeyConstant.CHAT_SERVER_ID_TO_AKKA_PATH; 92 | } 93 | 94 | public static String getGatewayIdToConnectPathRedisKey() { 95 | return RedisKeyConstant.GATEWAY_ID_TO_CONNECT_PATH; 96 | } 97 | 98 | public static String getMainLogicServerIdRedisKey() { 99 | return RedisKeyConstant.MAIN_LOGIC_SERVER_ID; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/dao/GmUserDAO.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.dao; 2 | 3 | import com.jacey.game.db.constants.GmRedisKeyConstant; 4 | import com.jacey.game.db.constants.GmRedisKeyHelper; 5 | import com.jacey.game.db.constants.RedisKeyHelper; 6 | import org.springframework.data.redis.core.ValueOperations; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * @Description: gm服务器相关的redis操作 14 | * @Author: JaceyRuan 15 | * @Email: jacey.ruan@outlook.com 16 | */ 17 | @Repository(value = "GmUserDAO") 18 | public class GmUserDAO { 19 | 20 | @Resource(name = "stringTemplate") 21 | private ValueOperations gmUserTokenOps; 22 | 23 | /** 24 | * 设置缓存token 25 | * @param token 存储的token 26 | * @param expire 超时时间(单位秒) 27 | */ 28 | public void setGmUserToken(String token, Integer expire) { 29 | gmUserTokenOps.set(GmRedisKeyHelper.getGmUserTokeRedisKey(token), 30 | token, 31 | expire, 32 | TimeUnit.SECONDS); 33 | } 34 | 35 | /** 36 | * 获取缓存Token 37 | * @param token 存储的token 38 | */ 39 | public String getGmUserToken(String token) { 40 | return gmUserTokenOps.get(GmRedisKeyHelper.getGmUserTokeRedisKey(token)); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/dao/SessionIdDAO.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.dao; 2 | 3 | import com.jacey.game.db.constants.RedisKeyHelper; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.HashOperations; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.data.redis.core.ValueOperations; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import javax.annotation.Resource; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * @Description: SessionId Redis 操作DAO 16 | * @Author: JaceyRuan 17 | * @Email: jacey.ruan@outlook.com 18 | */ 19 | @Repository(value = "sessionIdDAO") 20 | public class SessionIdDAO { 21 | 22 | @SuppressWarnings("rawtypes") 23 | @Autowired 24 | RedisTemplate jedisTemplate; 25 | 26 | /** 客户端自增的sessionId(value类型,自增的sessionId)*/ 27 | @Resource(name = "stringTemplate") 28 | private ValueOperations sessionIdAutoIncreaseOps; 29 | 30 | 31 | /** 已登录成功玩家userId与sessionId的对应关系(map类型,key:userId, value:sessionId)*/ 32 | @Resource(name = "integerTemplate") 33 | private HashOperations userIdToSessionIdOps; 34 | 35 | /** 已登录成功玩家sessionId与userId的对应关系(map类型,key:sessionId, value:userId) */ 36 | @Resource(name = "integerTemplate") 37 | private HashOperations sessionIdToUserIdOps; 38 | 39 | 40 | 41 | public int addAndGetNextAvailableSessionId() { 42 | return sessionIdAutoIncreaseOps.increment(RedisKeyHelper.getSessionIdAutoIncreaseRedisKey(), 1).intValue(); 43 | } 44 | 45 | 46 | public Integer getOneUserIdToSessionId(int userId) { 47 | return userIdToSessionIdOps.get(RedisKeyHelper.getUserIdToSessionIdRedisKey(), String.valueOf(userId)); 48 | } 49 | 50 | public Map getAllUserIdToSessionId() { 51 | Map result = new HashMap(); 52 | Map map = userIdToSessionIdOps.entries(RedisKeyHelper.getUserIdToSessionIdRedisKey()); 53 | if (map != null) { 54 | for (Map.Entry entry : map.entrySet()) { 55 | result.put(Integer.parseInt(entry.getKey()), entry.getValue()); 56 | } 57 | } 58 | return result; 59 | } 60 | 61 | public void setOneUserIdToSessionId(int userId, int sessionId) { 62 | userIdToSessionIdOps.put(RedisKeyHelper.getUserIdToSessionIdRedisKey(), String.valueOf(userId), sessionId); 63 | } 64 | 65 | public void removeOneUserIdToSessionId(int userId) { 66 | userIdToSessionIdOps.delete(RedisKeyHelper.getUserIdToSessionIdRedisKey(), String.valueOf(userId)); 67 | } 68 | 69 | public Integer getOneSessionIdToUserId(int sessionId) { 70 | return sessionIdToUserIdOps.get(RedisKeyHelper.getSessionIdToUserIdRedisKey(), String.valueOf(sessionId)); 71 | } 72 | 73 | public void setOneSessionIdToUserId(int sessionId, int userId) { 74 | sessionIdToUserIdOps.put(RedisKeyHelper.getSessionIdToUserIdRedisKey(), String.valueOf(sessionId), userId); 75 | } 76 | 77 | public void removeOneSessionIdToUserId(int sessionId) { 78 | sessionIdToUserIdOps.delete(RedisKeyHelper.getSessionIdToUserIdRedisKey(), String.valueOf(sessionId)); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/entity/BattleRecordEntity.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.util.Date; 7 | 8 | /** 9 | * @Description: 对战数据归档 10 | * @Author: JaceyRuan 11 | * @Email: jacey.ruan@outlook.com 12 | */ 13 | @Data 14 | @Entity 15 | @Table(name = "battle_record") 16 | public class BattleRecordEntity { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | int id; 21 | 22 | /** 对战类型 */ 23 | int battleType; 24 | 25 | /** 对战id */ 26 | String battleId; 27 | 28 | /** 对战用户id String 逗号分隔 */ 29 | String userIdList; 30 | 31 | /** 对战开始时间 */ 32 | Date battleStartTimestamp; 33 | 34 | /** 对战结束时间 */ 35 | Date battleEndTimestamp; 36 | 37 | /** 回合数 */ 38 | int turnCount; 39 | 40 | /** 获胜方用户Id */ 41 | int winnerUserId; 42 | 43 | /** 获胜原因 */ 44 | int gameOverReason; 45 | 46 | @Id 47 | @GeneratedValue(strategy = GenerationType.IDENTITY) 48 | public int getId() { 49 | return id; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/entity/GmUserEntity.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * @Description: TODO 9 | * @Author: JaceyRuan 10 | * @Email: jacey.ruan@outlook.com 11 | */ 12 | @Data 13 | @Entity 14 | @Table(name = "gm_user") 15 | public class GmUserEntity { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | private int userId; 20 | /** 玩家名称 */ 21 | private String username; 22 | 23 | /** MD5加密密码 */ 24 | private String passwordMD5; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/entity/PlayStateEntity.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * @Description: 玩家状态 9 | * @Author: JaceyRuan 10 | * @Email: jacey.ruan@outlook.com 11 | */ 12 | @Data 13 | @Entity 14 | @Table(name = "play_state") 15 | public class PlayStateEntity { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | private int id; 20 | 21 | private int userId; 22 | 23 | /** 在线状态(在线or离线) */ 24 | private int userOnlineState; 25 | 26 | /** 行为状态(none or 匹配中 or 对战中 等) */ 27 | private int userActionState; 28 | 29 | /** 对战类型(1v1 or ..) */ 30 | private int BattleType; 31 | 32 | /** 对战id */ 33 | private String battleId; 34 | 35 | @Id 36 | @GeneratedValue(strategy = GenerationType.IDENTITY) 37 | public int getId() { 38 | return id; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/entity/PlayUserEntity.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.util.Date; 7 | 8 | /** 9 | * @Description: 玩家信息 10 | * @Author: JaceyRuan 11 | * @Email: jacey.ruan@outlook.com 12 | */ 13 | @Data 14 | @Entity 15 | @Table(name = "play_user") 16 | public class PlayUserEntity { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private int userId; 21 | /** 玩家名称 */ 22 | private String username; 23 | 24 | /** 玩家昵称 */ 25 | private String nickname; 26 | 27 | /** MD5加密密码 */ 28 | private String passwordMD5; 29 | 30 | /** 注册时间戳 */ 31 | private Date registTimestamp; 32 | 33 | /** 注册ip */ 34 | private String registIp; 35 | 36 | /** 最后一次登录时间 */ 37 | private Date lastLoginTimestamp; 38 | 39 | /** 最后一次登录ip */ 40 | private String lastLoginIp; 41 | 42 | @Id 43 | @GeneratedValue(strategy = GenerationType.IDENTITY) 44 | public int getUserId() { 45 | return userId; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/redis/serializer/ByteRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.redis.serializer; 2 | 3 | import org.springframework.data.redis.serializer.RedisSerializer; 4 | import org.springframework.data.redis.serializer.SerializationException; 5 | 6 | import java.nio.charset.Charset; 7 | 8 | public class ByteRedisSerializer implements RedisSerializer { 9 | 10 | public ByteRedisSerializer() { 11 | this(Charset.forName("UTF8")); 12 | } 13 | 14 | public ByteRedisSerializer(Charset charset) { 15 | } 16 | 17 | @Override 18 | public byte[] serialize(byte[] t) throws SerializationException { 19 | return t; 20 | } 21 | 22 | @Override 23 | public byte[] deserialize(byte[] bytes) throws SerializationException { 24 | return bytes; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/redis/serializer/CommonRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.redis.serializer; 2 | 3 | import org.springframework.data.redis.serializer.RedisSerializer; 4 | import org.springframework.data.redis.serializer.SerializationException; 5 | 6 | import java.nio.charset.Charset; 7 | import java.util.regex.Pattern; 8 | 9 | public class CommonRedisSerializer implements RedisSerializer { 10 | 11 | private final Charset charset; 12 | 13 | public CommonRedisSerializer() { 14 | this(Charset.forName("UTF8")); 15 | } 16 | 17 | public CommonRedisSerializer(Charset charset) { 18 | this.charset = charset; 19 | } 20 | 21 | @Override 22 | public byte[] serialize(Object t) throws SerializationException { 23 | return String.valueOf(t).getBytes(charset); 24 | } 25 | 26 | @Override 27 | public Object deserialize(byte[] bytes) throws SerializationException { 28 | if (bytes == null) 29 | return null; 30 | String value = new String(bytes, charset); 31 | if (isInteger(value)) { 32 | return Integer.parseInt(value); 33 | } 34 | return value; 35 | } 36 | 37 | public static boolean isInteger(String str) { 38 | Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); 39 | return pattern.matcher(str).matches(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/redis/serializer/IntegerRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.redis.serializer; 2 | 3 | import org.springframework.data.redis.serializer.RedisSerializer; 4 | 5 | import java.nio.charset.Charset; 6 | 7 | public class IntegerRedisSerializer implements RedisSerializer { 8 | 9 | private final Charset charset; 10 | 11 | public IntegerRedisSerializer() { 12 | this(Charset.forName("UTF8")); 13 | } 14 | 15 | public IntegerRedisSerializer(Charset charset) { 16 | this.charset = charset; 17 | } 18 | 19 | @Override 20 | public byte[] serialize(Integer t) { 21 | return String.valueOf(t).getBytes(charset); 22 | } 23 | 24 | @Override 25 | public Integer deserialize(byte[] bytes) { 26 | return (bytes == null ? null : Integer.parseInt(new String(bytes, charset))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/redis/serializer/LongRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.redis.serializer; 2 | 3 | import org.springframework.data.redis.serializer.RedisSerializer; 4 | 5 | import java.nio.charset.Charset; 6 | 7 | public class LongRedisSerializer implements RedisSerializer { 8 | 9 | private final Charset charset; 10 | 11 | public LongRedisSerializer() { 12 | this(Charset.forName("UTF8")); 13 | } 14 | 15 | public LongRedisSerializer(Charset charset) { 16 | this.charset = charset; 17 | } 18 | 19 | @Override 20 | public byte[] serialize(Long t) { 21 | return String.valueOf(t).getBytes(charset); 22 | } 23 | 24 | @Override 25 | public Long deserialize(byte[] bytes) { 26 | return (bytes == null ? null : Long.parseLong(new String(bytes, charset))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/repository/BattleRecordRepository.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.repository; 2 | 3 | import com.jacey.game.db.entity.BattleRecordEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @Description: 数据归档Repository 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public interface BattleRecordRepository extends JpaRepository { 12 | } 13 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/repository/GmUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.repository; 2 | 3 | import com.jacey.game.db.entity.BattleRecordEntity; 4 | import com.jacey.game.db.entity.GmUserEntity; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | /** 8 | * @Description: TODO 9 | * @Author: JaceyRuan 10 | * @Email: jacey.ruan@outlook.com 11 | */ 12 | public interface GmUserRepository extends JpaRepository { 13 | GmUserEntity findOneByUsername(String username); 14 | } 15 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/repository/PlayStateRepository.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.repository; 2 | 3 | import com.jacey.game.db.entity.PlayStateEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @Description: Mysql 玩家状态操作 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public interface PlayStateRepository extends JpaRepository { 12 | 13 | PlayStateEntity findOneByUserId(int userId); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/repository/PlayUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.repository; 2 | 3 | import com.jacey.game.db.entity.PlayUserEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * @Description: Mysql mysql 玩家信息表操作 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public interface PlayUserRepository extends JpaRepository { 12 | 13 | PlayUserEntity findOneByUsername(String user); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/BattleRecordService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | 4 | import com.jacey.game.db.entity.BattleRecordEntity; 5 | 6 | /** 7 | * @Description: 对战数据归档处理 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public interface BattleRecordService { 12 | 13 | void saveBattleRecord(BattleRecordEntity battleRecordEntity); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/BattleServerLoadBalanceService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @Description: 对战服务器负债操作 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface BattleServerLoadBalanceService { 11 | 12 | void setBattleUserIdToBattleId(int userId, String battleId); 13 | 14 | String getBattleUserIdToBattleId(int userId); 15 | 16 | void removeBattleUserIdToBattleId(int userId); 17 | 18 | Integer getOneBattleIdToBattleServerId(String battleId); 19 | 20 | void setOneBattleIdToBattleServerId(String battleId, int battleServerId); 21 | 22 | void removeOneBattleIdToBattleServerId(String battleId); 23 | 24 | /** 25 | * 设置某个Battle对战服务器负载情况 26 | * @param battleServerId 对战服务器id 27 | * @param count 负载情况(连接数) 28 | */ 29 | void setOneBattleServerLoadBalance(int battleServerId, int count); 30 | 31 | /** 32 | * 修改某个Battle对战服务器的负载情况 33 | * @param battleServerId 对战服务器id 34 | * @param changeCount 负载情况修改数值(连接数修改) 35 | */ 36 | void changeOneBattleServerLoadBalance(int battleServerId, int changeCount); 37 | 38 | /** 39 | * 移除某个Battle对战服务器负载情况 40 | * @param battleServerId 对战服务器id 41 | */ 42 | void removeOneBattleServerLoadBalance(int battleServerId); 43 | 44 | /** 45 | * 获取所有Battle对战服务器的负载信息 46 | * @return 47 | */ 48 | Map getAllBattleServerLoadBalance(); 49 | 50 | /** 51 | * 清除Battle对战服务器的所有负载信息 52 | */ 53 | void cleanBattleServerLoadBalance(); 54 | 55 | /** 56 | * 获取Battle空闲Battle对战服务器id 57 | * @return 58 | */ 59 | Integer getLeisureBattleServerId(); 60 | 61 | void setOneBattleServerIdToAkkaPath(int battleServerId, String akkaPath); 62 | 63 | String getOneBattleServerIdToAkkaPath(int battleServerId); 64 | 65 | Map getAllBattleServerIdToAkkaPath(); 66 | 67 | void removeOneBattleServerIdToAkkaPath(int battleServerId); 68 | 69 | void cleanBattleServerIdToAkkaPath(); 70 | 71 | 72 | 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/ChatServerLoadBalanceService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @Description: 聊天服务器负载操作 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface ChatServerLoadBalanceService { 11 | 12 | Integer getOneBattleIdToChatServerId(String battleId); 13 | 14 | void setOneBattleIdToChatServerId(String battleId, int chatServerId); 15 | 16 | void removeOneBattleIdToChatServerId(String battleId); 17 | 18 | /** 19 | * 设置某个Chat聊天服务器负载情况 20 | * @param ChatServerId 聊天服务器id 21 | * @param count 负载情况(连接数) 22 | */ 23 | void setOneChatServerLoadBalance(int ChatServerId, int count); 24 | 25 | /** 26 | * 修改某个Chat聊天服务器的负载情况 27 | * @param ChatServerId 聊天服务器id 28 | * @param changeCount 负载情况修改数值(连接数修改) 29 | */ 30 | void changeOneChatServerLoadBalance(int ChatServerId, int changeCount); 31 | 32 | /** 33 | * 移除某个Chat聊天服务器负载情况 34 | * @param ChatServerId 聊天服务器id 35 | */ 36 | void removeOneChatServerLoadBalance(int ChatServerId); 37 | 38 | /** 39 | * 获取所有Chat聊天服务器的负载信息 40 | * @return 41 | */ 42 | Map getAllChatServerLoadBalance(); 43 | 44 | /** 45 | * 清除Chat聊天服务器的所有负载信息 46 | */ 47 | void cleanChatServerLoadBalance(); 48 | 49 | /** 50 | * 获取空闲Chat聊天服务器id 51 | * @return 52 | */ 53 | Integer getLeisureChatServerId(); 54 | 55 | void setOneChatServerIdToAkkaPath(int ChatServerId, String akkaPath); 56 | 57 | String getOneChatServerIdToAkkaPath(int ChatServerId); 58 | 59 | Map getAllChatServerIdToAkkaPath(); 60 | 61 | void removeOneChatServerIdToAkkaPath(int ChatServerId); 62 | 63 | void cleanChatServerIdToAkkaPath(); 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/GatewayServerLoadBalanceService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @Description: 网关服务器服务在操作 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface GatewayServerLoadBalanceService { 11 | 12 | /** 13 | * 设置sessionId与gatewayId绑定 14 | * @param sessionId 15 | * @param gatewayId 16 | */ 17 | public void setOneSessionIdToGatewayId(int sessionId, int gatewayId); 18 | 19 | /** 20 | * 获取该SessionId所绑定的Gateway网关id 21 | * @param sessionId 22 | * @return 23 | */ 24 | public Integer getOneSessionIdToGatewayId(int sessionId); 25 | 26 | /** 27 | * 移除该session与Gateway网关Id的绑定关系 28 | * @param sessionId 29 | */ 30 | public void removeOneSessionIdToGatewayId(int sessionId); 31 | 32 | /** 33 | * 设置某个Gateway网关服务器负载情况 34 | * @param gatewayId 网关服务器id 35 | * @param count 负载情况(连接数) 36 | */ 37 | public void setOneGatewayLoadBalance(int gatewayId, int count); 38 | 39 | /** 40 | * 修改某个Gateway网关服务器的负载情况 41 | * @param gatewayId 网关服务器id 42 | * @param changeCount 负载情况修改数值(连接数修改) 43 | */ 44 | public void changeOneGatewayLoadBalance(int gatewayId, int changeCount); 45 | 46 | /** 47 | * 移除某个Gateway网关服务器负载情况 48 | * @param gatewayId 网关服务器id 49 | */ 50 | public void removeOneGatewayLoadBalance(int gatewayId); 51 | 52 | /** 53 | * 获取所有Gateway网关服务器的负载信息 54 | * @return 55 | */ 56 | public Map getAllGatewayLoadBalance(); 57 | 58 | /** 59 | * 清除Gateway网关服务器的所有负载信息 60 | */ 61 | public void cleanGatewayLoadBalance(); 62 | 63 | /** 64 | * 获取Gateway空闲网关服务器id 65 | * @return 66 | */ 67 | public Integer getLeisureGatewayId(); 68 | 69 | void setOneGatewayIdToAkkaPath(int gatewayId, String akkaPath); 70 | 71 | String getOneGatewayIdToAkkaPath(int gatewayId); 72 | 73 | Map getAllGatewayIdToAkkaPath(); 74 | 75 | void removeOneGatewayIdToAkkaPath(int gatewayId); 76 | 77 | void cleanGatewayIdToAkkaPath(); 78 | 79 | /** 80 | * 设置网关服务器id与其连接地址绑定 81 | * @param gatewayId 网关服务器id 82 | * @param connectPath 连接地址(ip:port) 83 | */ 84 | public void setOneGatewayIdToConnectPath(int gatewayId, String connectPath); 85 | 86 | /** 87 | * 根据网关服务器id,获取其连接地址 88 | * @param gatewayId 网关服务器id 89 | * @return 90 | */ 91 | public String getOneGatewayIdToConnectPath(int gatewayId); 92 | 93 | /** 94 | * 根据网关服务器id,移除其与连接地址的绑定关系 95 | * @param gatewayId 网关服务器id 96 | */ 97 | public void removeOneGatewayIdToConnectPath(int gatewayId); 98 | 99 | 100 | /** 101 | * 清除所有网关服务器id与连接地址的绑定关系 102 | */ 103 | public void cleanGatewayIdToConnectPath(); 104 | } 105 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/GmUserService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import com.jacey.game.db.entity.GmUserEntity; 4 | 5 | /** 6 | * @Description: Gm用户操作 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface GmUserService { 11 | 12 | /** 13 | * 设置gm user token 缓存 14 | * @param token 15 | * @param expire 有效时间(单位:s) 16 | */ 17 | void setGmUserTokenCache(String token, Integer expire); 18 | 19 | /** 20 | * 获取缓存的token 21 | * @param token 22 | * @return 23 | */ 24 | String getGmUserTokenCache(String token); 25 | 26 | /** 27 | * 根据用户名获取Gm账户信息 28 | * @param username 29 | * @return 30 | */ 31 | GmUserEntity findGmUserByUsername(String username); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/LogicServerLoadBalanceService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @Description: logic服务器负债操作 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface LogicServerLoadBalanceService { 11 | 12 | 13 | /** 14 | * 设置sessionId与逻辑服务器id 绑定 15 | * @param sessionId 16 | * @param logicServerId 17 | */ 18 | public void setOneSessionIdToLogicServerId(int sessionId, int logicServerId); 19 | 20 | /** 21 | * 获取sessionId所绑定的逻辑服务器id 22 | * @param sessionId 23 | * @return 24 | */ 25 | public Integer getOneSessionIdToLogicServerId(int sessionId); 26 | 27 | /** 28 | * 29 | * @param sessionId 30 | */ 31 | public void removeOneSessionIdToLogicServerId(int sessionId); 32 | 33 | /** 34 | * 设置某个Logic逻辑服务器负载情况 35 | * @param logicServerId 逻辑服务器id 36 | * @param count 负载情况(连接数) 37 | */ 38 | void setOneLogicServerLoadBalance(int logicServerId, int count); 39 | 40 | /** 41 | * 修改某个Logic逻辑服务器的负载情况 42 | * @param logicServerId 逻辑服务器id 43 | * @param changeCount 负载情况修改数值(连接数修改) 44 | */ 45 | void changeOneLogicServerLoadBalance(int logicServerId, int changeCount); 46 | 47 | /** 48 | * 移除某个Logic逻辑服务器负载情况 49 | * @param logicServerId 逻辑服务器id 50 | */ 51 | public void removeOneLogicServerLoadBalance(int logicServerId); 52 | 53 | /** 54 | * 获取所有Logic逻辑服务器的负载信息 55 | * @return 56 | */ 57 | Map getAllLogicServerLoadBalance(); 58 | 59 | /** 60 | * 清除Logic逻辑服务器的所有负载信息 61 | */ 62 | void cleanLogicServerLoadBalance(); 63 | 64 | /** 65 | * 获取空闲Logic逻辑服务器id 66 | * @return 67 | */ 68 | Integer getLeisureLogicServerId(); 69 | 70 | /** 71 | * 设置Logic逻辑服务器id对应的AkkaPath 72 | * @param logicServerId 逻辑服务器id 73 | * @param akkaPath AkkaPath 74 | */ 75 | void setOneLogicServerIdToAkkaPath(int logicServerId, String akkaPath); 76 | 77 | /** 78 | * 获取Logic逻辑服务器id对应的AkkaPath 79 | * @param logicServerId 80 | * @return 81 | */ 82 | String getOneLogicServerIdToAkkaPath(int logicServerId); 83 | 84 | /** 85 | * 获取所有Logic逻辑服务器对应的AkkaPath 86 | * @return 87 | */ 88 | Map getAllLogicServerIdToAkkaPath(); 89 | 90 | /** 91 | * 移除某个Logic逻辑服务器对应的AkkaPath 92 | * @param logicServerId 93 | */ 94 | void removeOneLogicServerIdToAkkaPath(int logicServerId); 95 | 96 | /** 97 | * 清除所有Logic逻辑服务器AkkaPath 98 | */ 99 | void cleanLogicServerIdToAkkaPath(); 100 | 101 | /** 102 | * 设置主Logic逻辑服务器id 103 | * @param mainLogicServerId 104 | */ 105 | void setMainLogicServerId(int mainLogicServerId); 106 | 107 | /** 获取Logic逻辑服务器id */ 108 | int getMainLogicServerId(); 109 | 110 | } 111 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/PlayStateService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import com.jacey.game.common.proto3.CommonMsg; 4 | import com.jacey.game.db.entity.PlayStateEntity; 5 | 6 | /** 7 | * @Description: 玩家状态操作 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public interface PlayStateService { 12 | 13 | /** 14 | * 更新玩家在线状态 15 | * @param userId 16 | * @param isOnline 在线状态 17 | */ 18 | void changeUserOnlineState(int userId, boolean isOnline); 19 | 20 | /** 21 | * 获取 protobuf UserState 22 | * @param userId 23 | * @return 24 | */ 25 | CommonMsg.UserState getUserStateByUserId(int userId); 26 | 27 | /** 28 | * 用户状态状态 29 | * @param userId 30 | * @return 31 | */ 32 | PlayStateEntity getPlayStateByUserId(int userId); 33 | 34 | /** 35 | * 创建用户状态 36 | * @param playStateEntity 37 | */ 38 | void create(PlayStateEntity playStateEntity); 39 | 40 | /** 41 | * 修改用户状态 42 | * @param userId 用户id 43 | * @param userActionState 用户行为状态 44 | * @param battleType 对战类型 45 | * @param battleId 对战id(非匹配对战状态传null) 46 | */ 47 | void changeUserActionState(int userId, int userActionState, int battleType, String battleId); 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/PlayUserService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import com.jacey.game.common.proto3.CommonMsg; 4 | import com.jacey.game.db.entity.PlayUserEntity; 5 | 6 | /** 7 | * @Description: 用户数据处理 8 | * @Author: JaceyRuan 9 | * @Email: jacey.ruan@outlook.com 10 | */ 11 | public interface PlayUserService { 12 | 13 | /** 用户名是否已注册 */ 14 | boolean hasUsername(String username); 15 | 16 | /** 用户id是否已注册 */ 17 | boolean hasUserId(int userId); 18 | 19 | /** 根据用户名查询 */ 20 | PlayUserEntity findPlayUserByUsername(String username); 21 | 22 | /** 保存玩家信息 */ 23 | void createNewUser(PlayUserEntity playUserEntity); 24 | 25 | /** 26 | * 根据用户名查询userId 27 | * @param username 28 | * @return 29 | */ 30 | Integer getUserIdByUsername(String username); 31 | 32 | /** 33 | * 获取存储的玩家用户数据 34 | * @param userId 35 | * @return 36 | */ 37 | CommonMsg.UserData getUserDataByUserId(int userId) throws Exception; 38 | 39 | /** 40 | * 获取玩家简历信息(其他人可看) 41 | * @param userId 42 | * @return 43 | */ 44 | CommonMsg.UserBriefInfo getUserBriefInfoByUserId(int userId); 45 | 46 | /** 47 | * 更新玩家信息 48 | * @param userData 49 | */ 50 | void update(CommonMsg.UserData userData); 51 | 52 | /** 53 | * 获取玩家信息(玩家自己可查看的信息) 54 | * @param userId 55 | * @return 56 | */ 57 | CommonMsg.UserInfo getUserInfoByUserId(int userId) throws Exception; 58 | } 59 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/SessionIdService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @Description: sessionId操作 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface SessionIdService { 11 | 12 | /** 13 | * 添加和获取下一个可用的sessionId(redis提供的自增id) 14 | * @return 15 | */ 16 | public int addAndGetNextAvailableSessionId(); 17 | 18 | /** 19 | * 20 | * @param userId 21 | * @return 22 | */ 23 | public Integer getOneUserIdToSessionId(int userId); 24 | 25 | /** 26 | * 27 | * @return 28 | */ 29 | public Map getAllUserIdToSessionId(); 30 | 31 | /** 32 | * 33 | * @param userId 34 | * @param sessionId 35 | */ 36 | public void setOneUserIdToSessionId(int userId, int sessionId); 37 | 38 | /** 39 | * 40 | * @param userId 41 | */ 42 | public void removeOneUserIdToSessionId(int userId); 43 | 44 | /** 45 | * 46 | * @param sessionId 47 | * @return 48 | */ 49 | public Integer getOneSessionIdToUserId(int sessionId); 50 | 51 | /** 52 | * 53 | * @param sessionId 54 | * @param userId 55 | */ 56 | public void setOneSessionIdToUserId(int sessionId, int userId); 57 | 58 | /** 59 | * 60 | * @param sessionId 61 | */ 62 | public void removeOneSessionIdToUserId(int sessionId); 63 | 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/impl/BattleRecordServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service.impl; 2 | 3 | import com.jacey.game.db.entity.BattleRecordEntity; 4 | import com.jacey.game.db.repository.BattleRecordRepository; 5 | import com.jacey.game.db.service.BattleRecordService; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * @Description: 对战数据归档处理 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @Slf4j 16 | @Service 17 | public class BattleRecordServiceImpl implements BattleRecordService { 18 | 19 | @Autowired 20 | private BattleRecordRepository battleRecordRepository; 21 | 22 | @Override 23 | public void saveBattleRecord(BattleRecordEntity battleRecordEntity) { 24 | battleRecordRepository.save(battleRecordEntity); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/impl/ChatServerLoadBalanceServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service.impl; 2 | 3 | import com.jacey.game.db.dao.ChatServerLoadBalanceDAO; 4 | import com.jacey.game.db.service.ChatServerLoadBalanceService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @Description: 聊天服务器负载操作 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @Service 16 | public class ChatServerLoadBalanceServiceImpl implements ChatServerLoadBalanceService { 17 | 18 | @Autowired 19 | private ChatServerLoadBalanceDAO loadBalanceDAO; 20 | 21 | @Override 22 | public Integer getOneBattleIdToChatServerId(String battleId) { 23 | return loadBalanceDAO.getOneBattleIdToChatServerId(battleId); 24 | } 25 | 26 | @Override 27 | public void setOneBattleIdToChatServerId(String battleId, int chatServerId) { 28 | loadBalanceDAO.setOneBattleIdToChatServerId(battleId, chatServerId); 29 | } 30 | 31 | @Override 32 | public void removeOneBattleIdToChatServerId(String battleId) { 33 | loadBalanceDAO.removeOneBattleIdToChatServerId(battleId); 34 | } 35 | 36 | /** 37 | * 设置某个Chat聊天服务器负载情况 38 | * @param ChatServerId 聊天服务器id 39 | * @param count 负载情况(连接数) 40 | */ 41 | @Override 42 | public void setOneChatServerLoadBalance(int ChatServerId, int count) { 43 | loadBalanceDAO.setOneChatServerLoadBalance(ChatServerId, count); 44 | } 45 | 46 | /** 47 | * 修改某个Chat聊天服务器的负载情况 48 | * @param ChatServerId 聊天服务器id 49 | * @param changeCount 负载情况修改数值(连接数修改) 50 | */ 51 | @Override 52 | public void changeOneChatServerLoadBalance(int ChatServerId, int changeCount) { 53 | loadBalanceDAO.changeOneChatServerLoadBalance(ChatServerId, changeCount); 54 | } 55 | 56 | /** 57 | * 移除某个Chat聊天服务器负载情况 58 | * @param ChatServerId 聊天服务器id 59 | */ 60 | @Override 61 | public void removeOneChatServerLoadBalance(int ChatServerId) { 62 | loadBalanceDAO.removeOneChatServerLoadBalance(ChatServerId); 63 | } 64 | 65 | /** 66 | * 获取所有Chat聊天服务器的负载信息 67 | * @return 68 | */ 69 | @Override 70 | public Map getAllChatServerLoadBalance() { 71 | return loadBalanceDAO.getAllChatServerLoadBalance(); 72 | } 73 | 74 | /** 75 | * 清除Chat聊天服务器的所有负载信息 76 | */ 77 | @Override 78 | public void cleanChatServerLoadBalance() { 79 | loadBalanceDAO.cleanChatServerLoadBalance(); 80 | } 81 | 82 | /** 83 | * 获取空闲Chat聊天服务器id 84 | * @return 85 | */ 86 | @Override 87 | public Integer getLeisureChatServerId() { 88 | return loadBalanceDAO.getLeisureChatServerId(); 89 | } 90 | 91 | @Override 92 | public void setOneChatServerIdToAkkaPath(int ChatServerId, String akkaPath) { 93 | loadBalanceDAO.setOneChatServerIdToAkkaPath(ChatServerId, akkaPath); 94 | } 95 | 96 | @Override 97 | public String getOneChatServerIdToAkkaPath(int ChatServerId) { 98 | return loadBalanceDAO.getOneChatServerIdToAkkaPath(ChatServerId); 99 | } 100 | 101 | @Override 102 | public Map getAllChatServerIdToAkkaPath() { 103 | return loadBalanceDAO.getAllChatServerIdToAkkaPath(); 104 | } 105 | 106 | @Override 107 | public void removeOneChatServerIdToAkkaPath(int ChatServerId) { 108 | loadBalanceDAO.removeOneChatServerIdToAkkaPath(ChatServerId); 109 | } 110 | 111 | @Override 112 | public void cleanChatServerIdToAkkaPath() { 113 | loadBalanceDAO.cleanChatServerIdToAkkaPath(); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/impl/GmUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service.impl; 2 | 3 | import com.jacey.game.db.dao.GmUserDAO; 4 | import com.jacey.game.db.entity.GmUserEntity; 5 | import com.jacey.game.db.repository.GmUserRepository; 6 | import com.jacey.game.db.service.GmUserService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * @Description: 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @Service 16 | public class GmUserServiceImpl implements GmUserService { 17 | 18 | @Autowired 19 | private GmUserDAO gmUserDAO; 20 | @Autowired 21 | private GmUserRepository gmUserRepository; 22 | 23 | @Override 24 | public void setGmUserTokenCache(String token, Integer expire) { 25 | gmUserDAO.setGmUserToken(token, expire); 26 | } 27 | 28 | @Override 29 | public String getGmUserTokenCache(String token) { 30 | return gmUserDAO.getGmUserToken(token); 31 | } 32 | 33 | @Override 34 | public GmUserEntity findGmUserByUsername(String username) { 35 | return gmUserRepository.findOneByUsername(username); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/impl/PlayStateServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service.impl; 2 | 3 | import com.jacey.game.common.proto3.CommonEnum; 4 | import com.jacey.game.common.proto3.CommonEnum.UserOnlineStateEnum; 5 | import com.jacey.game.common.proto3.CommonMsg; 6 | import com.jacey.game.db.entity.PlayStateEntity; 7 | import com.jacey.game.db.repository.PlayStateRepository; 8 | import com.jacey.game.db.service.PlayStateService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | /** 13 | * @Description: 用户状态修改service 14 | * @Author: JaceyRuan 15 | * @Email: jacey.ruan@outlook.com 16 | */ 17 | @Service 18 | public class PlayStateServiceImpl implements PlayStateService { 19 | 20 | @Autowired 21 | private PlayStateRepository playStateRepository; 22 | 23 | 24 | 25 | @Override 26 | public void changeUserOnlineState(int userId, boolean isOnline) { 27 | PlayStateEntity playStateEntity = playStateRepository.findOneByUserId(userId); 28 | playStateEntity.setUserOnlineState(isOnline ? UserOnlineStateEnum.Online_VALUE : UserOnlineStateEnum.Offline_VALUE); 29 | playStateRepository.save(playStateEntity); 30 | } 31 | 32 | @Override 33 | public CommonMsg.UserState getUserStateByUserId(int userId) { 34 | PlayStateEntity playStateEntity = playStateRepository.findOneByUserId(userId); 35 | CommonMsg.UserState.Builder userState = CommonMsg.UserState.newBuilder(); 36 | userState.setOnlineStateValue(playStateEntity.getUserActionState()); 37 | userState.setActionStateValue(playStateEntity.getUserActionState()); 38 | if (playStateEntity.getUserActionState() == CommonEnum.UserActionStateEnum.Matching_VALUE) { 39 | // 处于匹配中 40 | userState.setBattleTypeValue(playStateEntity.getBattleType()); 41 | } else if (playStateEntity.getUserActionState() == CommonEnum.UserActionStateEnum.Playing_VALUE) { 42 | // 处于对战中 43 | userState.setBattleTypeValue(playStateEntity.getBattleType()); 44 | userState.setBattleId(playStateEntity.getBattleId()); 45 | } 46 | return userState.build(); 47 | } 48 | 49 | @Override 50 | public PlayStateEntity getPlayStateByUserId(int userId) { 51 | return playStateRepository.findOneByUserId(userId); 52 | } 53 | 54 | @Override 55 | public void create(PlayStateEntity playStateEntity) { 56 | playStateRepository.save(playStateEntity); 57 | } 58 | 59 | @Override 60 | public void changeUserActionState(int userId, int userActionState, int battleType, String battleId) { 61 | PlayStateEntity playStateEntity = playStateRepository.findOneByUserId(userId); 62 | playStateEntity.setUserActionState(userActionState); 63 | playStateEntity.setBattleType(battleType); 64 | playStateEntity.setBattleId(battleId); 65 | playStateRepository.save(playStateEntity); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /game-db/src/main/java/com/jacey/game/db/service/impl/SessionIdServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.db.service.impl; 2 | 3 | import com.jacey.game.db.dao.SessionIdDAO; 4 | import com.jacey.game.db.service.SessionIdService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @Description: sessionId操作 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @Service 16 | public class SessionIdServiceImpl implements SessionIdService { 17 | 18 | @Autowired 19 | private SessionIdDAO sessionIdDAO; 20 | 21 | /** 22 | * 添加和获取下一个可用的sessionId(redis提供的自增id) 23 | * @return 24 | */ 25 | @Override 26 | public int addAndGetNextAvailableSessionId() { 27 | return sessionIdDAO.addAndGetNextAvailableSessionId(); 28 | } 29 | 30 | /** 31 | * 32 | * @param userId 33 | * @return 34 | */ 35 | @Override 36 | public Integer getOneUserIdToSessionId(int userId) { 37 | return sessionIdDAO.getOneUserIdToSessionId(userId); 38 | } 39 | 40 | /** 41 | * 42 | * @return 43 | */ 44 | @Override 45 | public Map getAllUserIdToSessionId() { 46 | return sessionIdDAO.getAllUserIdToSessionId(); 47 | } 48 | 49 | /** 50 | * 51 | * @param userId 52 | * @param sessionId 53 | */ 54 | @Override 55 | public void setOneUserIdToSessionId(int userId, int sessionId) { 56 | sessionIdDAO.setOneUserIdToSessionId(userId, sessionId); 57 | } 58 | 59 | /** 60 | * 61 | * @param userId 62 | */ 63 | @Override 64 | public void removeOneUserIdToSessionId(int userId) { 65 | sessionIdDAO.removeOneUserIdToSessionId(userId); 66 | } 67 | 68 | /** 69 | * 70 | * @param sessionId 71 | * @return 72 | */ 73 | @Override 74 | public Integer getOneSessionIdToUserId(int sessionId) { 75 | return sessionIdDAO.getOneSessionIdToUserId(sessionId); 76 | } 77 | 78 | /** 79 | * 80 | * @param sessionId 81 | * @param userId 82 | */ 83 | @Override 84 | public void setOneSessionIdToUserId(int sessionId, int userId) { 85 | sessionIdDAO.setOneSessionIdToUserId(sessionId, userId); 86 | } 87 | 88 | /** 89 | * 90 | * @param sessionId 91 | */ 92 | @Override 93 | public void removeOneSessionIdToUserId(int sessionId) { 94 | sessionIdDAO.removeOneSessionIdToUserId(sessionId); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/ApplicationReadyEventListener.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway; 2 | 3 | import com.jacey.game.common.manager.CoreManager; 4 | import com.jacey.game.gateway.manager.*; 5 | import org.springframework.boot.context.event.ApplicationReadyEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | /** 10 | * @Description: manager 统一初始化 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | public class ApplicationReadyEventListener implements ApplicationListener { 15 | 16 | @Override 17 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 18 | ConfigurableApplicationContext context = applicationReadyEvent.getApplicationContext(); 19 | // 设置Spring context上下文 20 | SpringManager.getInstance().setContext(context); 21 | // 核心管理器注册 22 | CoreManager.getInstance().registManager(ConfigManager.getInstance()); 23 | CoreManager.getInstance().registManager(SpringManager.getInstance()); 24 | CoreManager.getInstance().registManager(MessageManager.getInstance()); 25 | CoreManager.getInstance().registManager(OnlineClientManager.getInstance()); 26 | CoreManager.getInstance().registManager(ServerNodeManager.getInstance()); 27 | 28 | CoreManager.getInstance().init(); // 对所有manager进行初始化 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/GatewayServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 9 | 10 | /** 11 | * @Description: 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @SpringBootApplication 16 | @ComponentScan("com.jacey.game") 17 | @EnableJpaRepositories("com.jacey.game.db.repository") 18 | @EntityScan("com.jacey.game.db.entity") 19 | public class GatewayServerApplication { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication app = new SpringApplication(GatewayServerApplication.class); 23 | app.addListeners(new ApplicationReadyEventListener()); 24 | app.run(args); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/actor/ResponseActor.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.actor; 2 | 3 | import akka.actor.UntypedAbstractActor; 4 | import com.jacey.game.common.msg.IMessage; 5 | import com.jacey.game.common.msg.NetMessage; 6 | import com.jacey.game.common.msg.NetResponseMessage; 7 | import com.jacey.game.common.proto3.Rpc; 8 | import io.netty.channel.Channel; 9 | import lombok.extern.slf4j.Slf4j; 10 | 11 | /** 12 | * @Description: 专门用于接收远程服务器的响应 13 | * @Author: JaceyRuan 14 | * @Email: jacey.ruan@outlook.com 15 | */ 16 | @Slf4j 17 | public class ResponseActor extends UntypedAbstractActor { 18 | 19 | private io.netty.channel.Channel channel; 20 | 21 | public ResponseActor(Channel channel) { 22 | this.channel = channel; 23 | } 24 | 25 | @Override 26 | public void onReceive(Object o) throws Throwable { 27 | if (o instanceof NetMessage) { 28 | NetMessage msg = (NetMessage) o; 29 | switch (msg.getRpcNum()) { 30 | case Rpc.RpcNameEnum.Login_VALUE: { 31 | // 远程逻辑服务器返回玩家登录成功后,不仅需要返回给玩家登录成功 32 | // 也需要通知自己的父Actor即ChannelActor为这个玩家的ChannelActor绑定userId 33 | context().parent().tell(new NetResponseMessage(msg), self()); 34 | break; 35 | } 36 | case Rpc.RpcNameEnum.ForceOfflinePush_VALUE: { 37 | // 强制离线响应 38 | write(msg); 39 | channel.close(); 40 | } 41 | default: { 42 | // 转发给客户端 43 | write(msg); 44 | break; 45 | } 46 | } 47 | } else { 48 | log.error("【消息解析失败】, not support msg type = {}", o.getClass().getName()); 49 | } 50 | } 51 | 52 | private void write(IMessage msg) { 53 | if (this.channel != null && this.channel.isActive() && this.channel.isWritable()) { 54 | channel.writeAndFlush(msg); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/config/SpringConfig.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.ImportResource; 5 | 6 | @Configuration 7 | @ImportResource(locations = { "classpath:spring.xml" }) 8 | public class SpringConfig { 9 | 10 | public SpringConfig() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/manager/ConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.configuration.Configuration; 6 | import org.apache.commons.configuration.ConfigurationException; 7 | import org.apache.commons.configuration.ConfigurationFactory; 8 | 9 | /** 10 | * @Description: 配置文件加载管理 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class ConfigManager implements IManager { 16 | 17 | private static ConfigManager configManager = new ConfigManager(); 18 | 19 | private static ConfigurationFactory factory; 20 | private static Configuration config; 21 | 22 | public static int CLIENT_PORT; 23 | /** 心跳配置 */ 24 | public static int SOCKET_READER_IDLE_TIME; // 空闲读 25 | public static int SOCKET_WRITER_IDLE_TIME; // 空闲写 26 | public static int SOCKET_ALL_IDLE_TIME; // 空闲(超过300.客户端无发包在,则为空闲) 27 | 28 | 29 | public static String REMOTE_GM_AKKA_PATH; // GM服务器Akka papth 30 | public static int GATEWAY_ID; // 当前网关服务器id 31 | public static String GATEWAY_CONNECT_PATH; // 网关服务器连接ip地址 32 | public static String GATEWAY_AKKA_PATH; // 网关服务器akka oath 33 | 34 | private ConfigManager() {} 35 | 36 | public static ConfigManager getInstance() { 37 | return configManager; 38 | } 39 | 40 | 41 | @Override 42 | public void init() { 43 | log.info("------------ start load config ------------"); 44 | loadConfig(); 45 | log.info("------------ finish load config ------------"); 46 | } 47 | 48 | @Override 49 | public void shutdown() { 50 | 51 | } 52 | 53 | private void loadConfig() { 54 | factory = new ConfigurationFactory("propertyConfig.xml"); 55 | try { 56 | config = factory.getConfiguration(); 57 | } catch (ConfigurationException e) { 58 | log.error("【config初始化失败】, exception = ", e); 59 | System.exit(0); 60 | } 61 | CLIENT_PORT = config.getInt("client.port"); 62 | 63 | SOCKET_READER_IDLE_TIME = config.getInt("socket.reader.idle.time"); 64 | SOCKET_WRITER_IDLE_TIME = config.getInt("socket.writer.idle.time"); 65 | SOCKET_ALL_IDLE_TIME = config.getInt("socket.all.idle.time"); 66 | 67 | REMOTE_GM_AKKA_PATH = config.getString("remote.gm.akka.path"); 68 | GATEWAY_ID = config.getInt("gateway.id"); 69 | GATEWAY_CONNECT_PATH = config.getString("gateway.connect.path"); 70 | GATEWAY_AKKA_PATH = config.getString("gateway.akka.path"); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/manager/ServerNodeManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import com.jacey.game.gateway.network.ServerNode; 5 | import com.jacey.game.gateway.network.netty.NettySocketServer; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | /** 9 | * @Description: 10 | * @Author: JaceyRuan 11 | * @Email: jacey.ruan@outlook.com 12 | */ 13 | @Slf4j 14 | public class ServerNodeManager implements IManager { 15 | 16 | private ServerNodeManager() {} 17 | 18 | private static ServerNodeManager instance = new ServerNodeManager(); 19 | 20 | public static ServerNodeManager getInstance() { 21 | return instance; 22 | } 23 | 24 | private ServerNode serverNode; 25 | 26 | @Override 27 | public void init() { 28 | serverNode = NettySocketServer.getInstance(); 29 | try { 30 | serverNode.start(); 31 | } catch (Exception e) { 32 | log.error("【服务器节点启动失败】 error = ", e); 33 | System.exit(0); 34 | } 35 | } 36 | 37 | @Override 38 | public void shutdown() { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/manager/SpringManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.data.redis.connection.RedisConnection; 7 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 8 | 9 | /** 10 | * @Description: 处理Spring相关内容 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class SpringManager implements IManager { 16 | 17 | private static SpringManager instance = new SpringManager(); 18 | 19 | public static SpringManager getInstance() { 20 | return instance; 21 | } 22 | 23 | private ConfigurableApplicationContext context; 24 | 25 | @Override 26 | public void init() { 27 | // 检查redis是否已连接 28 | try { 29 | JedisConnectionFactory factory = getBean(JedisConnectionFactory.class); 30 | RedisConnection connection = factory.getConnection(); 31 | if ("PONG".equals(connection.ping()) == false) { 32 | log.error("redis connect fail"); 33 | System.exit(0); 34 | } 35 | } catch (Exception e) { 36 | log.error("redis connect fail, error = ", e); 37 | System.exit(0); 38 | } 39 | 40 | } 41 | 42 | @Override 43 | public void shutdown() { 44 | } 45 | 46 | public Object getBean(String beanName) { 47 | return context.getBean(beanName); 48 | } 49 | 50 | public T getBean(Class object) { 51 | return context.getBean(object); 52 | } 53 | 54 | public void setContext(ConfigurableApplicationContext context) { 55 | this.context = context; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/network/ServerNode.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.network; 2 | 3 | /** 4 | * @Description: 服务器节点接口类。 5 | * @Author: JaceyRuan 6 | * @Email: jacey.ruan@outlook.com 7 | */ 8 | public interface ServerNode { 9 | 10 | void start() throws Exception; 11 | 12 | void shutdown(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/network/netty/NettySocketServer.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.network.netty; 2 | 3 | import com.jacey.game.gateway.manager.ConfigManager; 4 | import com.jacey.game.gateway.network.ServerNode; 5 | import com.jacey.game.gateway.network.netty.tcp.codec.NettyProtocolDecoder; 6 | import com.jacey.game.gateway.network.netty.tcp.codec.NettyProtocolEncoder; 7 | import com.jacey.game.gateway.network.netty.tcp.handle.NettySocketHandle; 8 | import io.netty.bootstrap.ServerBootstrap; 9 | import io.netty.channel.ChannelInitializer; 10 | import io.netty.channel.ChannelOption; 11 | import io.netty.channel.ChannelPipeline; 12 | import io.netty.channel.EventLoopGroup; 13 | import io.netty.channel.nio.NioEventLoopGroup; 14 | import io.netty.channel.socket.SocketChannel; 15 | import io.netty.channel.socket.nio.NioServerSocketChannel; 16 | import io.netty.handler.timeout.IdleStateHandler; 17 | import lombok.extern.slf4j.Slf4j; 18 | 19 | import java.net.InetSocketAddress; 20 | 21 | /** 22 | * @Description: Netty服务器 23 | * @Author: JaceyRuan 24 | * @Email: jacey.ruan@outlook.com 25 | */ 26 | @Slf4j 27 | public class NettySocketServer implements ServerNode { 28 | 29 | private NettySocketServer() {} 30 | 31 | private static NettySocketServer instance = new NettySocketServer(); 32 | 33 | public static NettySocketServer getInstance() { 34 | return instance; 35 | } 36 | 37 | // 避免使用默认线程数参数 38 | private EventLoopGroup bossGroup = new NioEventLoopGroup(4); 39 | private EventLoopGroup workerGroup = new NioEventLoopGroup(); 40 | 41 | @Override 42 | public void start() throws Exception { 43 | int serverPort = ConfigManager.CLIENT_PORT; 44 | // Netty 服务端启动引导 45 | ServerBootstrap bootstrap = new ServerBootstrap(); 46 | try { 47 | bootstrap.group(bossGroup, workerGroup) 48 | .channel(NioServerSocketChannel.class) 49 | .option(ChannelOption.SO_BACKLOG, 1024) 50 | .childHandler(new ChildChannelHandler()); 51 | bootstrap.bind(new InetSocketAddress(serverPort)).sync(); 52 | log.info("netty socket服务已启动,正在监听用户的请求@port:" + serverPort + "......"); 53 | } catch (Exception e) { 54 | bossGroup.shutdownGracefully(); 55 | workerGroup.shutdownGracefully(); 56 | throw e; 57 | } 58 | } 59 | 60 | private class ChildChannelHandler extends ChannelInitializer { 61 | 62 | @Override 63 | protected void initChannel(SocketChannel socketChannel) throws Exception { 64 | ChannelPipeline pipeline = socketChannel.pipeline(); 65 | pipeline.addLast(new NettyProtocolDecoder()); // 自定义解码器 66 | pipeline.addLast(new NettyProtocolEncoder()); // 自定义编码器 67 | // 心跳处理:客户端300秒没收发包,便会触发IdleStateEvent事件。到UserEventTriggered方法处理 68 | pipeline.addLast(new IdleStateHandler(ConfigManager.SOCKET_READER_IDLE_TIME, 69 | ConfigManager.SOCKET_WRITER_IDLE_TIME, 70 | ConfigManager.SOCKET_ALL_IDLE_TIME)); 71 | pipeline.addLast(new NettySocketHandle()); // 消息处理 72 | } 73 | 74 | } 75 | 76 | @Override 77 | public void shutdown() { 78 | 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/network/netty/tcp/codec/NettyProtocolDecoder.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.network.netty.tcp.codec; 2 | 3 | import com.jacey.game.common.msg.NetMessage; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.ByteToMessageDecoder; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Description: 自定义解码器 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | public class NettyProtocolDecoder extends ByteToMessageDecoder { 16 | 17 | private static final int HEADER_LENGTH = 12; 18 | 19 | @Override 20 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { 21 | int dataPackLength = byteBuf.readableBytes(); 22 | if (dataPackLength < HEADER_LENGTH) { 23 | return; 24 | } 25 | // ----------------消息协议格式------------------------- 26 | // packetLength | rpcNum | errorCode | body 27 | // int int int byte[] 28 | // 打标记 29 | byteBuf.markReaderIndex(); 30 | 31 | int totalLength = byteBuf.readInt(); 32 | // 数据包长度小于 packetLength。才读取(拆包) 33 | if (dataPackLength >= totalLength) { 34 | int rpcNum = byteBuf.readInt(); 35 | int errorCode = byteBuf.readInt(); 36 | byte[] bytes = new byte[totalLength - HEADER_LENGTH]; 37 | byteBuf.readBytes(bytes); 38 | NetMessage message = new NetMessage(rpcNum, bytes); 39 | message.setErrorCode(errorCode); 40 | list.add(message); 41 | } else { 42 | // 回滚到标记点 43 | byteBuf.resetReaderIndex(); 44 | return; 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/java/com/jacey/game/gateway/network/netty/tcp/codec/NettyProtocolEncoder.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gateway.network.netty.tcp.codec; 2 | 3 | import com.jacey.game.common.msg.NetMessage; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.MessageToByteEncoder; 7 | 8 | /** 9 | * @Description: 自定义编码器 10 | * @Author: JaceyRuan 11 | * @Email: jacey.ruan@outlook.com 12 | */ 13 | public class NettyProtocolEncoder extends MessageToByteEncoder { 14 | 15 | @Override 16 | protected void encode(ChannelHandlerContext channelHandlerContext, NetMessage netMessage, ByteBuf byteBuf) throws Exception { 17 | byteBuf.writeBytes(netMessage.toBinaryMsg()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "INFO" 3 | 4 | stdout-loglevel = "INFO" 5 | 6 | #log-config-on-start = on 7 | 8 | actor { 9 | provider = "akka.remote.RemoteActorRefProvider" 10 | 11 | allow-java-serialization = off 12 | 13 | serializers { 14 | net = "com.jacey.game.common.msg.serializer.NetMessageSerializer" 15 | remote = "com.jacey.game.common.msg.serializer.RemoteMessageSerializer" 16 | } 17 | 18 | serialization-bindings { 19 | "com.jacey.game.common.msg.NetMessage" = net 20 | "com.jacey.game.common.msg.RemoteMessage" = remote 21 | } 22 | } 23 | 24 | remote { 25 | artery { 26 | enabled = on 27 | transport = tcp 28 | canonical { 29 | port = 10000 30 | hostname = "" 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /game-gateway-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.jdbc.Driver 4 | username: root 5 | password: 123456 6 | url: jdbc:mysql://192.168.2.193:3306/jgame_server?characterEncoding=utf-8&useSSL=false -------------------------------------------------------------------------------- /game-gateway-server/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | client.port = 10001 2 | socket.reader.idle.time = 0 3 | socket.writer.idle.time = 0 4 | socket.all.idle.time = 300 5 | 6 | 7 | remote.gm.akka.path = akka://gm@192.168.2.193:20000/user/gmActor 8 | 9 | gateway.id = 1 10 | gateway.connect.path = 192.168.2.193:10001 11 | gateway.akka.path = akka://gateway_1@192.168.2.193:10000/user/gatewayActor -------------------------------------------------------------------------------- /game-gateway-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 8 | 9 | 10 | 11 | 13 | log/gateway.log 14 | 16 | log/gateway-%d{yyyy-MM-dd}.%i.log 17 | 18 | 365 19 | 21 | 1000MB 22 | 23 | 24 | 25 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 33 | 34 | ERROR 35 | 36 | log/gateway_error.log 37 | 39 | log/gateway_error-%d{yyyy-MM-dd}.%i.log 40 | 41 | 365 42 | 44 | 1000MB 45 | 46 | 47 | 48 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 49 | 50 | UTF-8 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/resources/propertyConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /game-gateway-server/src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | redis.hostname = 192.168.2.193 2 | redis.port = 6379 3 | redis.password = root -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/ApplicationReadyEventListener.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm; 2 | 3 | import com.jacey.game.common.manager.CoreManager; 4 | import com.jacey.game.gm.manager.MessageManager; 5 | import com.jacey.game.gm.manager.SpringManager; 6 | import org.springframework.boot.context.event.ApplicationReadyEvent; 7 | import org.springframework.context.ApplicationListener; 8 | import org.springframework.context.ConfigurableApplicationContext; 9 | 10 | /** 11 | * @Description: manager 统一初始化 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | public class ApplicationReadyEventListener implements ApplicationListener { 16 | 17 | @Override 18 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 19 | ConfigurableApplicationContext context = applicationReadyEvent.getApplicationContext(); 20 | // 设置Spring context上下文 21 | SpringManager.getInstance().setContext(context); 22 | // 核心管理器注册 23 | CoreManager.getInstance().registManager(SpringManager.getInstance()); 24 | CoreManager.getInstance().registManager(MessageManager.getInstance()); 25 | 26 | 27 | CoreManager.getInstance().init(); // 对所有manager进行初始化 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/GmServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 9 | 10 | /** 11 | * @Description: 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @SpringBootApplication 16 | @ComponentScan({"com.jacey.game"}) 17 | @EnableJpaRepositories("com.jacey.game.db.repository") 18 | @EntityScan("com.jacey.game.db.entity") 19 | public class GmServerApplication { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication app = new SpringApplication(GmServerApplication.class); 23 | app.addListeners(new ApplicationReadyEventListener()); 24 | app.run(args); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/config/FilterConfig.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.config; 2 | 3 | import com.jacey.game.gm.filter.RequestInterceptor; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistration; 6 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | /** 10 | * @Description: 拦截器配置 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Configuration 15 | public class FilterConfig implements WebMvcConfigurer { 16 | 17 | @Override 18 | public void addInterceptors(InterceptorRegistry registry) { 19 | //注册TestInterceptor拦截器 20 | InterceptorRegistration registration = registry.addInterceptor(new RequestInterceptor()); 21 | registration.addPathPatterns("/gm/**"); //所有路径都被拦截 22 | //添加不拦截路径 23 | registration.excludePathPatterns("/gateway", "/gm/gmUserLogin"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/config/SpringConfig.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.ImportResource; 5 | 6 | @Configuration 7 | @ImportResource(locations = { "classpath:spring.xml" }) 8 | public class SpringConfig { 9 | 10 | public SpringConfig() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/controller/ClientController.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.controller; 2 | 3 | import com.jacey.game.db.service.GatewayServerLoadBalanceService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @Description: 供客户端调用的接口 10 | * @Author: JaceyRuan 11 | * @Email: jacey.ruan@outlook.com 12 | */ 13 | @RestController 14 | public class ClientController { 15 | 16 | @Autowired 17 | private GatewayServerLoadBalanceService gatewayServerLoadBalanceService; 18 | 19 | /** 20 | * 获取空闲网关服务器连接地址 21 | * @return 22 | */ 23 | @RequestMapping("/gateway") 24 | public String getLeisureGateway() { 25 | Integer leisureGatewayId = gatewayServerLoadBalanceService.getLeisureGatewayId(); 26 | return leisureGatewayId == null ? null : gatewayServerLoadBalanceService.getOneGatewayIdToConnectPath(leisureGatewayId); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/controller/GmController.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.controller; 2 | 3 | import com.jacey.game.common.constants.CookieConstant; 4 | import com.jacey.game.db.entity.GmUserEntity; 5 | import com.jacey.game.db.service.GmUserService; 6 | import com.jacey.game.gm.enums.ResultEnum; 7 | import com.jacey.game.gm.utils.CookieUtil; 8 | import com.jacey.game.gm.utils.ResultVOUtil; 9 | import com.jacey.game.gm.vo.ResultVO; 10 | import org.apache.commons.lang.StringUtils; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestParam; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import javax.servlet.http.Cookie; 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | import java.util.UUID; 21 | 22 | /** 23 | * @Description: 服务器管理相关controller 24 | * @Author: JaceyRuan 25 | * @Email: jacey.ruan@outlook.com 26 | */ 27 | @RestController 28 | @RequestMapping("/gm") 29 | public class GmController { 30 | 31 | @Autowired 32 | private GmUserService gmUserService; 33 | 34 | /** 35 | * GM账户登录 36 | * @param gmUserName 37 | * @param passwordMD5 38 | */ 39 | @GetMapping("/gmUserLogin") 40 | public ResultVO GmUserLogin(@RequestParam("gmUserName") String gmUserName, @RequestParam("passwordMD5") String passwordMD5, 41 | HttpServletRequest request, 42 | HttpServletResponse response) { 43 | // 判断是否已登录 44 | Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); 45 | // redis获取是否有token 46 | if (cookie != null && 47 | !StringUtils.isEmpty(gmUserService.getGmUserTokenCache(cookie.getValue()))) { 48 | return ResultVOUtil.success(); 49 | } 50 | // 没有,查询数据库 51 | GmUserEntity gmUserEntity = gmUserService.findGmUserByUsername(gmUserName); 52 | if (gmUserEntity == null) { 53 | return ResultVOUtil.error(ResultEnum.LOGIN_FAIL); 54 | } 55 | if (!passwordMD5.equalsIgnoreCase(gmUserEntity.getPasswordMD5())) { 56 | return ResultVOUtil.error(ResultEnum.LOGIN_FAIL); 57 | } 58 | // 生成登录token,并缓存 59 | String token = UUID.randomUUID().toString(); 60 | Integer expire = CookieConstant.expire; // 过期时间 61 | gmUserService.setGmUserTokenCache(token, expire); 62 | 63 | // 添加token到cookie中 64 | CookieUtil.set(response, CookieConstant.TOKEN, token, CookieConstant.expire); 65 | 66 | return ResultVOUtil.success(); 67 | } 68 | 69 | 70 | @GetMapping("/executeGmCmd") 71 | public ResultVO ExecuteGmCmd() { 72 | // TODO 73 | return ResultVOUtil.success(); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/enums/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.enums; 2 | 3 | import lombok.Getter; 4 | 5 | 6 | @Getter 7 | public enum ResultEnum { 8 | LOGIN_FAIL(1, "登录失败"), 9 | ; 10 | 11 | private Integer code; 12 | 13 | private String message; 14 | 15 | ResultEnum(Integer code, String message) { 16 | this.code = code; 17 | this.message = message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/filter/RequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.filter; 2 | 3 | import com.jacey.game.common.constants.CookieConstant; 4 | import com.jacey.game.gm.utils.CookieUtil; 5 | import org.apache.commons.lang.StringUtils; 6 | import org.springframework.web.servlet.HandlerInterceptor; 7 | import org.springframework.web.servlet.ModelAndView; 8 | 9 | import javax.servlet.http.Cookie; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | /** 14 | * @Description: 请求拦截器 15 | * @Author: JaceyRuan 16 | * @Email: jacey.ruan@outlook.com 17 | */ 18 | public class RequestInterceptor implements HandlerInterceptor { 19 | 20 | /** 21 | * 在请求处理之前进行调用(Controller方法调用之前) 22 | */ 23 | @Override 24 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 25 | // 判断是否已登录 26 | Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); 27 | String token = cookie.getValue(); 28 | if (StringUtils.isEmpty(token)) { 29 | return false; 30 | } 31 | //如果设置为false时,被请求时,拦截器执行到此处将不会继续操作 32 | //如果设置为true时,请求将会继续执行后面的操作 33 | return true; 34 | } 35 | 36 | /** 37 | * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) 38 | */ 39 | @Override 40 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { 41 | } 42 | 43 | /** 44 | * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) 45 | */ 46 | @Override 47 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/manager/SpringManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | import org.springframework.data.redis.connection.RedisConnection; 8 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 9 | 10 | /** 11 | * @Description: 处理Spring相关内容 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | public class SpringManager implements IManager { 16 | 17 | private static final Logger logger = LoggerFactory.getLogger(SpringManager.class); 18 | 19 | private static SpringManager instance = new SpringManager(); 20 | 21 | public static SpringManager getInstance() { 22 | return instance; 23 | } 24 | 25 | private ConfigurableApplicationContext context; 26 | 27 | @Override 28 | public void init() { 29 | // 检查redis是否已连接 30 | try { 31 | JedisConnectionFactory factory = getBean(JedisConnectionFactory.class); 32 | RedisConnection connection = factory.getConnection(); 33 | if ("PONG".equals(connection.ping()) == false) { 34 | logger.error("redis connect fail"); 35 | System.exit(0); 36 | } 37 | } catch (Exception e) { 38 | logger.error("redis connect fail, error = ", e); 39 | System.exit(0); 40 | } 41 | 42 | // // 检查GM默认管理员账号是否创建,如果没有则需要新建 43 | // GmUserService gmUserService = SpringManager.getInstance().getBean(GmUserService.class); 44 | // if (gmUserService.hasGmUsername(AppConfigManager.GM_ADMIN_USERNAME) == false) { 45 | // logger.info("GM default admin is not exist, then create it"); 46 | // gmUserService.createNewGmUser(AppConfigManager.GM_ADMIN_USERNAME, AppConfigManager.GM_ADMIN_PASSWORD_MD5); 47 | // } 48 | } 49 | 50 | @Override 51 | public void shutdown() { 52 | } 53 | 54 | public Object getBean(String beanName) { 55 | return context.getBean(beanName); 56 | } 57 | 58 | public T getBean(Class object) { 59 | return context.getBean(object); 60 | } 61 | 62 | public void setContext(ConfigurableApplicationContext context) { 63 | this.context = context; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/utils/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.utils; 2 | 3 | import javax.servlet.http.Cookie; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | 7 | /** 8 | * @Description: TODO 9 | * @Author: JaceyRuan 10 | * @Email: jacey.ruan@outlook.com 11 | */ 12 | public class CookieUtil { 13 | 14 | /** 15 | * 设置cookie 16 | * @param response 17 | * @param key cookie 的key 18 | * @param value cookie 的值 19 | * @param maxAge cookie 的保存时间(单位:秒) 20 | */ 21 | public static void set(HttpServletResponse response, 22 | String key, 23 | String value, 24 | int maxAge) { 25 | Cookie cookie = new Cookie(key, value); 26 | cookie.setPath("/"); 27 | cookie.setMaxAge(maxAge); 28 | response.addCookie(cookie); 29 | 30 | } 31 | 32 | /** 33 | * 获取cookie 34 | * @param request 35 | * @param name 36 | * @return 37 | */ 38 | public static Cookie get(HttpServletRequest request, 39 | String name) { 40 | Cookie[] cookies = request.getCookies(); 41 | if (cookies != null) { 42 | for (Cookie cookie: cookies) { 43 | if (name.equals(cookie.getName())) { 44 | return cookie; 45 | } 46 | } 47 | } 48 | 49 | return null; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/utils/ResultVOUtil.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.utils; 2 | 3 | 4 | import com.jacey.game.gm.enums.ResultEnum; 5 | import com.jacey.game.gm.vo.ResultVO; 6 | 7 | /** 8 | * Created by 廖师兄 9 | * 2017-12-10 18:03 10 | */ 11 | public class ResultVOUtil { 12 | 13 | public static ResultVO success(Object object) { 14 | ResultVO resultVO = new ResultVO(); 15 | resultVO.setCode(0); 16 | resultVO.setMsg("成功"); 17 | resultVO.setData(object); 18 | return resultVO; 19 | } 20 | 21 | public static ResultVO success() { 22 | ResultVO resultVO = new ResultVO(); 23 | resultVO.setCode(0); 24 | resultVO.setMsg("成功"); 25 | return resultVO; 26 | } 27 | 28 | public static ResultVO error(ResultEnum resultEnum) { 29 | ResultVO resultVO = new ResultVO(); 30 | resultVO.setCode(resultEnum.getCode()); 31 | resultVO.setMsg(resultEnum.getMessage()); 32 | return resultVO; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /game-gm-server/src/main/java/com/jacey/game/gm/vo/ResultVO.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.gm.vo; 2 | 3 | import lombok.Data; 4 | 5 | 6 | @Data 7 | public class ResultVO { 8 | 9 | private Integer code; 10 | 11 | private String msg; 12 | 13 | private T data; 14 | } 15 | -------------------------------------------------------------------------------- /game-gm-server/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "INFO" 3 | 4 | stdout-loglevel = "INFO" 5 | 6 | #log-config-on-start = on 7 | 8 | actor { 9 | provider = "akka.remote.RemoteActorRefProvider" 10 | 11 | allow-java-serialization = off 12 | 13 | serializers { 14 | net = "com.jacey.game.common.msg.serializer.NetMessageSerializer" 15 | remote = "com.jacey.game.common.msg.serializer.RemoteMessageSerializer" 16 | } 17 | 18 | serialization-bindings { 19 | "com.jacey.game.common.msg.NetMessage" = net 20 | "com.jacey.game.common.msg.RemoteMessage" = remote 21 | } 22 | } 23 | 24 | remote { 25 | artery { 26 | enabled = on 27 | transport = tcp 28 | canonical { 29 | port = 20000 30 | hostname = "" 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /game-gm-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 80 3 | tomcat: 4 | max-threads: 800 5 | accept-count: 30000 6 | min-spare-threads: 20 7 | max-connections: 30000 8 | spring: 9 | datasource: 10 | driver-class-name: com.mysql.jdbc.Driver 11 | username: root 12 | password: 123456 13 | url: jdbc:mysql://localhost/jgame_server?characterEncoding=utf-8&useSSL=false -------------------------------------------------------------------------------- /game-gm-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 8 | 9 | 10 | 11 | 13 | log/gm.log 14 | 16 | log/gm-%d{yyyy-MM-dd}.%i.log 17 | 18 | 365 19 | 21 | 1000MB 22 | 23 | 24 | 25 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 33 | 34 | ERROR 35 | 36 | log/gm_error.log 37 | 39 | log/gm_error-%d{yyyy-MM-dd}.%i.log 40 | 41 | 365 42 | 44 | 1000MB 45 | 46 | 47 | 48 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 49 | 50 | UTF-8 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /game-gm-server/src/main/resources/propertyConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /game-gm-server/src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | redis.hostname = 192.168.2.193 2 | redis.port = 6379 3 | redis.password = root -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/ApplicationReadyEventListener.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic; 2 | 3 | import com.jacey.game.common.manager.CoreManager; 4 | import com.jacey.game.logic.manager.*; 5 | import org.springframework.boot.context.event.ApplicationReadyEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | /** 10 | * @Description: manager 统一初始化 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | public class ApplicationReadyEventListener implements ApplicationListener { 15 | 16 | @Override 17 | public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 18 | ConfigurableApplicationContext context = applicationReadyEvent.getApplicationContext(); 19 | // 设置Spring context上下文 20 | SpringManager.getInstance().setContext(context); 21 | // 核心管理器注册 22 | CoreManager.getInstance().registManager(ConfigManager.getInstance()); 23 | CoreManager.getInstance().registManager(TableConfigManager.getInstance()); 24 | CoreManager.getInstance().registManager(SpringManager.getInstance()); 25 | CoreManager.getInstance().registManager(MessageManager.getInstance()); 26 | CoreManager.getInstance().registManager(OnlineClientManager.getInstance()); 27 | 28 | CoreManager.getInstance().init(); // 对所有manager进行初始化 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/LogicServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 9 | 10 | /** 11 | * @Description: 12 | * @Author: JaceyRuan 13 | * @Email: jacey.ruan@outlook.com 14 | */ 15 | @SpringBootApplication 16 | @ComponentScan(value= {"com.jacey.game"}) 17 | @EnableJpaRepositories("com.jacey.game.db.repository") 18 | @EntityScan("com.jacey.game.db.entity") 19 | public class LogicServerApplication { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication app = new SpringApplication(LogicServerApplication.class); 23 | app.addListeners(new ApplicationReadyEventListener()); 24 | app.run(args); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/action/match/CancelMatchAction.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.action.match; 2 | 3 | import com.jacey.game.common.action.BaseMessageAction; 4 | import com.jacey.game.common.annotation.MessageClassMapping; 5 | import com.jacey.game.common.exception.RpcErrorException; 6 | import com.jacey.game.common.msg.IMessage; 7 | import com.jacey.game.common.msg.NetMessage; 8 | import com.jacey.game.common.proto3.CommonEnum.UserActionStateEnum; 9 | import com.jacey.game.common.proto3.CommonEnum.BattleTypeEnum; 10 | import com.jacey.game.common.proto3.CommonMsg; 11 | import com.jacey.game.common.proto3.Rpc; 12 | import com.jacey.game.db.entity.PlayStateEntity; 13 | import com.jacey.game.db.service.PlayStateService; 14 | import com.jacey.game.logic.service.MatchService; 15 | import lombok.extern.slf4j.Slf4j; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.stereotype.Component; 18 | 19 | /** 20 | * @Description: 取消匹配 21 | * @Author: JaceyRuan 22 | * @Email: jacey.ruan@outlook.com 23 | */ 24 | @Slf4j 25 | @Component 26 | @MessageClassMapping(Rpc.RpcNameEnum.CancelMatch_VALUE) 27 | public class CancelMatchAction extends BaseMessageAction { 28 | 29 | @Autowired 30 | private MatchService matchService; 31 | 32 | @Autowired 33 | private PlayStateService playStateService; 34 | 35 | @Override 36 | protected void LogRequest(IMessage requestMessage) throws Exception { 37 | NetMessage req = (NetMessage) requestMessage; 38 | log.info("【取消匹配请求】 userId = {}:\n{}", req.getUserId(), 39 | req.getProtobufText(CommonMsg.CancelMatchRequest.class)); 40 | } 41 | 42 | @Override 43 | protected void LogResponse(IMessage responseMessage) throws Exception { 44 | NetMessage resp = (NetMessage) responseMessage; 45 | log.info("【取消匹配请求】 userId = {}:\n{}", resp.getUserId(), 46 | resp.getProtobufText(CommonMsg.CancelMatchResponse.class)); 47 | } 48 | 49 | @Override 50 | protected IMessage doAction(IMessage requestMessage) throws Exception { 51 | NetMessage msg = (NetMessage) requestMessage; 52 | int userId = msg.getUserId(); 53 | 54 | PlayStateEntity playStateEntity = playStateService.getPlayStateByUserId(userId); 55 | UserActionStateEnum actionState = UserActionStateEnum.forNumber(playStateEntity.getUserActionState()); 56 | if (actionState == UserActionStateEnum.Playing) { 57 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.CancelMatchErrorPlaying_VALUE); 58 | } else if (actionState != UserActionStateEnum.Matching) { 59 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.CancelMatchErrorNotMatching_VALUE); 60 | } 61 | 62 | if (matchService.removeMatchPlayer(userId, BattleTypeEnum.forNumber(playStateEntity.getBattleType())) == false) { 63 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.ServerError_VALUE); 64 | } 65 | 66 | CommonMsg.CancelMatchResponse.Builder builder = CommonMsg.CancelMatchResponse.newBuilder(); 67 | return super.buildResponseNetMsg(userId, Rpc.RpcNameEnum.CancelMatch_VALUE, builder); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/action/match/MatchAction.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.action.match; 2 | 3 | import com.jacey.game.common.action.BaseMessageAction; 4 | import com.jacey.game.common.annotation.MessageClassMapping; 5 | import com.jacey.game.common.exception.RpcErrorException; 6 | import com.jacey.game.common.msg.IMessage; 7 | import com.jacey.game.common.msg.NetMessage; 8 | import com.jacey.game.common.proto3.CommonEnum; 9 | import com.jacey.game.common.proto3.CommonMsg; 10 | import com.jacey.game.common.proto3.Rpc; 11 | import com.jacey.game.db.entity.PlayStateEntity; 12 | import com.jacey.game.db.service.PlayStateService; 13 | import com.jacey.game.logic.service.MatchService; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | /** 19 | * @Description: 匹配请求处理 20 | * @Author: JaceyRuan 21 | * @Email: jacey.ruan@outlook.com 22 | */ 23 | @Slf4j 24 | @Component 25 | @MessageClassMapping(Rpc.RpcNameEnum.Match_VALUE) 26 | public class MatchAction extends BaseMessageAction { 27 | 28 | @Autowired 29 | private MatchService matchService; 30 | 31 | @Autowired 32 | private PlayStateService playStateService; 33 | 34 | @Override 35 | protected void LogRequest(IMessage requestMessage) throws Exception { 36 | NetMessage req = (NetMessage) requestMessage; 37 | log.info("【匹配请求】 userId = {}:\n{}", req.getUserId(), req.getProtobufText(CommonMsg.MatchRequest.class)); 38 | } 39 | 40 | @Override 41 | protected void LogResponse(IMessage responseMessage) throws Exception { 42 | NetMessage resp = (NetMessage) responseMessage; 43 | log.info("【匹配响应】 userId = {}:\n{}", resp.getUserId(), resp.getProtobufText(CommonMsg.MatchResponse.class)); 44 | } 45 | 46 | @Override 47 | protected IMessage doAction(IMessage requestMessage) throws Exception { 48 | NetMessage msg = (NetMessage) requestMessage; 49 | int userId = msg.getUserId(); 50 | 51 | CommonMsg.MatchRequest req = msg.getLite(CommonMsg.MatchRequest.class); 52 | CommonEnum.BattleTypeEnum battleType = req.getBattleType(); // 获取匹配类型 53 | 54 | // 获取玩家状态 55 | PlayStateEntity playStateEntity = playStateService.getPlayStateByUserId(userId); 56 | if (playStateEntity.getUserActionState() == CommonEnum.UserActionStateEnum.Matching_VALUE) { 57 | // 状态为匹配中 抛异常 58 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.MatchErrorMatching_VALUE); 59 | } else if (playStateEntity.getUserActionState() == CommonEnum.UserActionStateEnum.Playing_VALUE) { 60 | // 状态为对战中 抛异常 61 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.MatchErrorPlaying_VALUE); 62 | } else if (playStateEntity.getUserActionState() != CommonEnum.UserActionStateEnum.ActionNone_VALUE) { 63 | // 状态Not None 抛异常 64 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.MatchErrorOtherActionState_VALUE); 65 | } 66 | // 添加玩家到匹配队列中。 67 | if (matchService.addMatchPlayer(userId, battleType) == false) { 68 | throw new RpcErrorException(Rpc.RpcErrorCodeEnum.ServerError_VALUE); 69 | } 70 | // 生成响应 71 | CommonMsg.MatchResponse.Builder builder = CommonMsg.MatchResponse.newBuilder(); 72 | 73 | return super.buildResponseNetMsg(userId, Rpc.RpcNameEnum.Match_VALUE, builder); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/actor/MatchActor.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.actor; 2 | 3 | import com.jacey.game.common.annotation.MessageMethodMapping; 4 | import com.jacey.game.common.msg.LocalMessage; 5 | import com.jacey.game.common.msg.NetMessage; 6 | import com.jacey.game.common.msg.RemoteMessage; 7 | import com.jacey.game.common.proto3.CommonMsg; 8 | import com.jacey.game.common.proto3.LocalServer; 9 | import com.jacey.game.common.proto3.RemoteServer; 10 | import com.jacey.game.common.proto3.Rpc; 11 | import com.jacey.game.db.service.PlayUserService; 12 | import com.jacey.game.db.service.impl.PlayUserServiceImpl; 13 | import com.jacey.game.logic.manager.MessageManager; 14 | import com.jacey.game.logic.manager.SpringManager; 15 | import com.jacey.game.logic.service.MatchService; 16 | import com.jacey.game.logic.service.impl.MatchServiceImpl; 17 | import lombok.extern.slf4j.Slf4j; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @Description: 匹配处理Actor 接收消息并分发到下属action 23 | * @Author: JaceyRuan 24 | * @Email: jacey.ruan@outlook.com 25 | */ 26 | @Slf4j 27 | public class MatchActor extends BaseMessageActor { 28 | 29 | private final LocalMessage localMsgMatch = new LocalMessage(LocalServer.LocalRpcNameEnum.LocalRpcLogicServerMatch_VALUE); 30 | private MatchService matchService = SpringManager.getInstance().getBean(MatchServiceImpl.class); 31 | private PlayUserService userService = SpringManager.getInstance().getBean(PlayUserServiceImpl.class); 32 | 33 | public MatchActor() { 34 | super(); 35 | } 36 | 37 | public MatchActor(String actionPackageName) { 38 | super(actionPackageName); 39 | } 40 | 41 | /** 42 | * MatchActor启动时调用 43 | * 开启定时任务,每隔1秒发起匹配计算,查看是否有正在匹配的用户。有则通知battle服务器创建战场。 44 | * battle创建战场完成后,通知主logic 服务器,然后主logic服务器再通知对战用户双方 45 | */ 46 | @Override 47 | public void preStart() { 48 | super.preStart(); 49 | // logicServer循环通知自己进行匹配计算 50 | // 每隔1秒给自己发匹配消息,从而实现间隔1秒进行1次匹配计算 51 | super.schedule(0, 1, localMsgMatch); 52 | } 53 | 54 | /** 55 | * MatchActor 内部调用,用于定时执行匹配计算 56 | * @param localMessage 57 | * @throws Exception 58 | */ 59 | @MessageMethodMapping(LocalServer.LocalRpcNameEnum.LocalRpcLogicServerMatch_VALUE) 60 | public void doMatch(LocalMessage localMessage) throws Exception { 61 | matchService.doMatch(); 62 | } 63 | 64 | /** 65 | * 用于接收battle服务器创建战场成功后通知。logic服务器再通知客户端 66 | * @param remoteMsg 67 | * @throws Exception 68 | */ 69 | @MessageMethodMapping(RemoteServer.RemoteRpcNameEnum.RemoteRpcNoticeBattleServerCreateNewBattle_VALUE) 70 | public void onReceivedNoticeBattleServerCreateNewBattle(RemoteMessage remoteMsg) throws Exception { 71 | // 对战创建响应 72 | RemoteServer.NoticeBattleServerCreateNewBattleResponse response = remoteMsg 73 | .getLite(RemoteServer.NoticeBattleServerCreateNewBattleResponse.class); 74 | 75 | // 获取对战房间信息 76 | RemoteServer.BattleRoomInfo battleRoomInfo = response.getBattleRoomInfo(); 77 | // 获取对战玩家信息 78 | List userIds = battleRoomInfo.getUserIdsList(); 79 | // 匹配结果消息体构建 80 | CommonMsg.MatchResultPush.Builder pushBuilder = CommonMsg.MatchResultPush.newBuilder(); 81 | pushBuilder.setIsSuccess(true); // 匹配成功 82 | pushBuilder.setBattleType(battleRoomInfo.getBattleType()); // 匹配类型 83 | pushBuilder.setBattleId(battleRoomInfo.getBattleId()); // battleId 84 | // 玩家简略信息列表(按行动顺序排列) 85 | for (int userId : userIds) { 86 | pushBuilder.addUserBriefInfos(userService.getUserBriefInfoByUserId(userId)); 87 | } 88 | NetMessage netMsg = new NetMessage(Rpc.RpcNameEnum.MatchResultPush_VALUE, pushBuilder); 89 | for (int userId : userIds) { 90 | // 通知对战双方匹配结果 91 | MessageManager.getInstance().sendNetMsgToOneUser(userId, netMsg, CommonMsg.MatchResultPush.class); 92 | } 93 | } 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/config/SpringConfig.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.ImportResource; 5 | 6 | @Configuration 7 | @ImportResource(locations = { "classpath:spring.xml" }) 8 | public class SpringConfig { 9 | 10 | public SpringConfig() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/manager/ConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.configuration.Configuration; 6 | import org.apache.commons.configuration.ConfigurationException; 7 | import org.apache.commons.configuration.ConfigurationFactory; 8 | 9 | /** 10 | * @Description: 配置文件加载管理 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class ConfigManager implements IManager { 16 | 17 | private static ConfigManager configManager = new ConfigManager(); 18 | 19 | private static ConfigurationFactory factory; 20 | private static Configuration config; 21 | 22 | public static String REMOTE_GM_AKKA_PATH; // GM服务器Akka path 23 | public static int LOGIC_SERVER_ID; // 当前logic服务器id 24 | public static boolean IS_MAIN_LOGIC_SERVER; // 是否是主逻辑服务器 25 | public static String LOGIC_SERVER_AKKA_PATH; // logic服务器akka oath 26 | 27 | private ConfigManager() {} 28 | 29 | public static ConfigManager getInstance() { 30 | return configManager; 31 | } 32 | 33 | 34 | @Override 35 | public void init() { 36 | log.info("------------ start load config ------------"); 37 | loadConfig(); 38 | log.info("------------ finish load config ------------"); 39 | } 40 | 41 | @Override 42 | public void shutdown() { 43 | 44 | } 45 | 46 | private void loadConfig() { 47 | factory = new ConfigurationFactory("propertyConfig.xml"); 48 | try { 49 | config = factory.getConfiguration(); 50 | } catch (ConfigurationException e) { 51 | log.error("【config初始化失败】, exception = ", e); 52 | System.exit(0); 53 | } 54 | 55 | REMOTE_GM_AKKA_PATH = config.getString("remote.gm.akka.path"); 56 | LOGIC_SERVER_ID = config.getInt("logic.server.id"); 57 | IS_MAIN_LOGIC_SERVER = config.getBoolean("is.main.logic.server"); 58 | LOGIC_SERVER_AKKA_PATH = config.getString("logic.server.akka.path"); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/manager/OnlineClientManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.manager; 2 | 3 | import akka.actor.ActorRef; 4 | import com.jacey.game.common.manager.IManager; 5 | import com.jacey.game.db.service.LogicServerLoadBalanceService; 6 | import com.jacey.game.db.service.impl.LogicServerLoadBalanceServiceImpl; 7 | import io.netty.channel.Channel; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | /** 14 | * @Description: 在线客户端管理 15 | * @Author: JaceyRuan 16 | * @Email: jacey.ruan@outlook.com 17 | */ 18 | @Slf4j 19 | public class OnlineClientManager implements IManager { 20 | 21 | private OnlineClientManager(){} 22 | 23 | private static OnlineClientManager instance = new OnlineClientManager(); 24 | 25 | public static OnlineClientManager getInstance() { 26 | return instance; 27 | } 28 | 29 | private LogicServerLoadBalanceService logicServerLoadBalanceService; 30 | 31 | // key:sessionId, 32 | // value:这个客户端对应gateway中ResponseActor(玩家发的消息,gateway转发到logicServer,sender为ResponseActor) 33 | private final Map sessionIdToGatewayResponseActor = new ConcurrentHashMap(); 34 | 35 | 36 | @Override 37 | public void init() { 38 | logicServerLoadBalanceService = SpringManager.getInstance().getBean(LogicServerLoadBalanceServiceImpl.class); 39 | } 40 | 41 | @Override 42 | public void shutdown() { 43 | // 服务器关闭时,清除服务器连接地址、负载信息 44 | logicServerLoadBalanceService.removeOneLogicServerLoadBalance(ConfigManager.LOGIC_SERVER_ID); 45 | logicServerLoadBalanceService.removeOneLogicServerIdToAkkaPath(ConfigManager.LOGIC_SERVER_ID); 46 | if (ConfigManager.IS_MAIN_LOGIC_SERVER == true 47 | && logicServerLoadBalanceService.getMainLogicServerId() == ConfigManager.LOGIC_SERVER_ID) { 48 | logicServerLoadBalanceService.setMainLogicServerId(0); 49 | } 50 | // 清除连接本logicServer的玩家的sessionId与logicServerId的对应信息 51 | for (int sessionId : sessionIdToGatewayResponseActor.keySet()) { 52 | logicServerLoadBalanceService.removeOneSessionIdToLogicServerId(sessionId); 53 | } 54 | } 55 | 56 | /** 57 | * 获取在线用户数 58 | * @return 59 | */ 60 | public int getOnlineActorCount() { 61 | return sessionIdToGatewayResponseActor.size(); 62 | } 63 | 64 | /** 65 | * sessid 与 responseActor绑定 66 | * @param sessionId 67 | * @param gatewayResponseActor 68 | */ 69 | public void addSessionIdToGatewayResponseActor(int sessionId, ActorRef gatewayResponseActor) { 70 | sessionIdToGatewayResponseActor.put(sessionId, gatewayResponseActor); 71 | // SessionId与logicServerId绑定 72 | logicServerLoadBalanceService.setOneSessionIdToLogicServerId(sessionId, ConfigManager.LOGIC_SERVER_ID); 73 | if (MessageManager.getInstance().isAvailableForUpdateLoadBalance() == true) { 74 | logicServerLoadBalanceService.setOneLogicServerLoadBalance(ConfigManager.LOGIC_SERVER_ID, 75 | sessionIdToGatewayResponseActor.size()); 76 | } 77 | } 78 | 79 | public void removeSessionIdToGatewayResponseActor(int sessionId) { 80 | sessionIdToGatewayResponseActor.remove(sessionId); 81 | logicServerLoadBalanceService.removeOneSessionIdToLogicServerId(sessionId); 82 | if (MessageManager.getInstance().isAvailableForUpdateLoadBalance() == true) { 83 | logicServerLoadBalanceService.setOneLogicServerLoadBalance(ConfigManager.LOGIC_SERVER_ID, 84 | sessionIdToGatewayResponseActor.size()); 85 | } 86 | } 87 | 88 | 89 | public ActorRef getGatewayResponseActor(int sessionId) { 90 | return sessionIdToGatewayResponseActor.get(sessionId); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/manager/SpringManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.data.redis.connection.RedisConnection; 7 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 8 | 9 | /** 10 | * @Description: 处理Spring相关内容 11 | * @Author: JaceyRuan 12 | * @Email: jacey.ruan@outlook.com 13 | */ 14 | @Slf4j 15 | public class SpringManager implements IManager { 16 | 17 | private static SpringManager instance = new SpringManager(); 18 | 19 | public static SpringManager getInstance() { 20 | return instance; 21 | } 22 | 23 | private ConfigurableApplicationContext context; 24 | 25 | @Override 26 | public void init() { 27 | // 检查redis是否已连接 28 | try { 29 | JedisConnectionFactory factory = getBean(JedisConnectionFactory.class); 30 | RedisConnection connection = factory.getConnection(); 31 | if ("PONG".equals(connection.ping()) == false) { 32 | log.error("redis connect fail"); 33 | System.exit(0); 34 | } 35 | } catch (Exception e) { 36 | log.error("redis connect fail, error = ", e); 37 | System.exit(0); 38 | } 39 | 40 | } 41 | 42 | @Override 43 | public void shutdown() { 44 | } 45 | 46 | public Object getBean(String beanName) { 47 | return context.getBean(beanName); 48 | } 49 | 50 | public T getBean(Class object) { 51 | return context.getBean(object); 52 | } 53 | 54 | public void setContext(ConfigurableApplicationContext context) { 55 | this.context = context; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/manager/TableConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.manager; 2 | 3 | import com.jacey.game.common.manager.IManager; 4 | import com.jacey.game.common.utils.ImportExcelUtil; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.InputStream; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * @Description: 游戏系统配置数据加载 15 | * @Author: JaceyRuan 16 | * @Email: jacey.ruan@outlook.com 17 | */ 18 | @Slf4j 19 | public class TableConfigManager implements IManager { 20 | 21 | private TableConfigManager(){} 22 | 23 | private static TableConfigManager instance = new TableConfigManager(); 24 | 25 | public static TableConfigManager getInstance() { 26 | return instance; 27 | } 28 | 29 | // SystemConfig,系统配置表,key:paramKey, value:paramValue 30 | private Map systemConfigMap; 31 | 32 | public static final String TABLE_CONFIG_FILE_PATH = "tableConfig/"; 33 | 34 | private ClassLoader classLoader = TableConfigManager.class.getClassLoader(); 35 | 36 | @Override 37 | public void init() { 38 | log.info("------------ start load table config ------------"); 39 | loadTableConfig(); 40 | log.info("------------ finish load table config ------------"); 41 | } 42 | 43 | private void loadTableConfig() { 44 | // SystemConfig,系统配置表,key:paramKey, value:paramValue 45 | systemConfigMap = new HashMap(); 46 | InputStream inputStream = classLoader.getResourceAsStream(TABLE_CONFIG_FILE_PATH + "SystemConfig.xlsx"); 47 | // 字段名映射 48 | Map mappingMap = new HashMap(); 49 | mappingMap.put("参数名", "key"); 50 | mappingMap.put("参数值", "value"); 51 | try { 52 | systemConfigMap = ImportExcelUtil.parseExcel(inputStream, "SystemConfig.xlsx", mappingMap, 2); 53 | } catch (Exception e) { 54 | log.error("loadTableConfig error = ", e); 55 | } 56 | log.info("read table SystemConfig, data count = {}", systemConfigMap.size()); 57 | } 58 | 59 | public void reloadTableConfig() { 60 | log.info("------------ reload table config ------------"); 61 | loadTableConfig(); 62 | } 63 | 64 | public Integer getSystemIntConfigByKey(String key) { 65 | if (systemConfigMap.containsKey(key)) { 66 | return Integer.parseInt((String) systemConfigMap.get(key)); 67 | } else { 68 | return null; 69 | } 70 | } 71 | 72 | public String getSystemStringConfigByKey(String key) { 73 | return (String) systemConfigMap.get(key); 74 | } 75 | 76 | @Override 77 | public void shutdown() { 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /game-logic-server/src/main/java/com/jacey/game/logic/service/MatchService.java: -------------------------------------------------------------------------------- 1 | package com.jacey.game.logic.service; 2 | 3 | import com.jacey.game.common.proto3.CommonEnum; 4 | 5 | /** 6 | * @Description: 匹配业务处理 7 | * @Author: JaceyRuan 8 | * @Email: jacey.ruan@outlook.com 9 | */ 10 | public interface MatchService { 11 | 12 | /** 13 | * 执行匹配动作 14 | * @throws Exception 15 | */ 16 | void doMatch() throws Exception; 17 | 18 | /** 19 | * 添加玩家Id到匹配队列中 20 | * @param userId 21 | * @param battleType 22 | * @return 23 | * @throws Exception 24 | */ 25 | boolean addMatchPlayer(int userId, CommonEnum.BattleTypeEnum battleType) throws Exception; 26 | 27 | /** 28 | * 从匹配队列中移除某个对象 29 | * @param userId 30 | * @param battleType 31 | * @return 32 | * @throws Exception 33 | */ 34 | boolean removeMatchPlayer(int userId, CommonEnum.BattleTypeEnum battleType) throws Exception; 35 | 36 | /** 37 | * 停止匹配 38 | * @throws Exception 39 | */ 40 | void stopMatch() throws Exception; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = "INFO" 3 | 4 | stdout-loglevel = "INFO" 5 | 6 | #log-config-on-start = on 7 | 8 | actor { 9 | provider = "akka.remote.RemoteActorRefProvider" 10 | 11 | allow-java-serialization = off 12 | 13 | serializers { 14 | net = "com.jacey.game.common.msg.serializer.NetMessageSerializer" 15 | remote = "com.jacey.game.common.msg.serializer.RemoteMessageSerializer" 16 | } 17 | 18 | serialization-bindings { 19 | "com.jacey.game.common.msg.NetMessage" = net 20 | "com.jacey.game.common.msg.RemoteMessage" = remote 21 | } 22 | } 23 | 24 | remote { 25 | artery { 26 | enabled = on 27 | transport = tcp 28 | canonical { 29 | port = 30000 30 | hostname = "" 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.jdbc.Driver 4 | username: root 5 | password: 123456 6 | url: jdbc:mysql://localhost/jgame_server?characterEncoding=utf-8&useSSL=false -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | remote.gm.akka.path = akka://gm@192.168.2.193:20000/user/gmActor 2 | 3 | logic.server.id = 1 4 | is.main.logic.server = true 5 | logic.server.akka.path = akka://logicServer_1@192.168.2.193:30000/user/logicServerActor 6 | 7 | 8 | -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 8 | 9 | 10 | 11 | 13 | log/logic.log 14 | 16 | log/logic-%d{yyyy-MM-dd}.%i.log 17 | 18 | 365 19 | 21 | 1000MB 22 | 23 | 24 | 25 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 26 | 27 | UTF-8 28 | 29 | 30 | 31 | 33 | 34 | ERROR 35 | 36 | log/logic_error.log 37 | 39 | log/logic_error-%d{yyyy-MM-dd}.%i.log 40 | 41 | 365 42 | 44 | 1000MB 45 | 46 | 47 | 48 | [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - %msg%n 49 | 50 | UTF-8 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/propertyConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | redis.hostname = 192.168.2.193 2 | redis.port = 6379 3 | redis.password = root -------------------------------------------------------------------------------- /game-logic-server/src/main/resources/tableConfig/SystemConfig.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaceyRx/JGameServer/7b4c877ce8d3dcc1620d435c1c4b57beaddd462d/game-logic-server/src/main/resources/tableConfig/SystemConfig.xlsx -------------------------------------------------------------------------------- /release/build-first-build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | chcp 65001 3 | 4 | :: 1.第一次打包该项目需要整个项目打包一次。不然子模块将无法打包 5 | echo 编译 root pom 文件 6 | cd ..\ 7 | start mvn clean install -DskipTests 8 | 9 | ::pause 10 | 11 | 12 | -------------------------------------------------------------------------------- /release/build-server-module.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | chcp 65001 3 | 4 | echo 打包gm服务器 5 | cd gm 6 | start mvn clean install -DskipTests 7 | 8 | echo 打包logic服务器 9 | cd ..\logic 10 | start mvn clean install -DskipTests 11 | 12 | echo 打包gateway服务器 13 | cd ..\gateway 14 | start mvn clean install -DskipTests 15 | 16 | echo 打包chat服务器 17 | cd ..\chat 18 | start mvn clean install -DskipTests 19 | 20 | echo 打包battle服务器 21 | cd ..\battle 22 | start mvn clean install -DskipTests 23 | 24 | echo maven编译均已启动,请等待各类服务器编译成功后手工关闭各个窗口,注意查看是否编译成功 25 | pause -------------------------------------------------------------------------------- /release/onekey run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | start "GM" cmd /k call "run gm.bat" 4 | TIMEOUT /T 10 /NOBREAK 5 | 6 | start "Logic" cmd /k call "run logic.bat" 7 | start "Battle" cmd /k call "run battle.bat" 8 | start "Gateway" cmd /k call "run gateway.bat" 9 | start "Chat" cmd /k call "run chat.bat" -------------------------------------------------------------------------------- /release/run battle.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd battle\target 4 | java -jar battleServer.jar -------------------------------------------------------------------------------- /release/run chat.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd chat\target 4 | java -jar chatServer.jar -------------------------------------------------------------------------------- /release/run gateway.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd gateway\target 4 | java -jar gatewayServer.jar -------------------------------------------------------------------------------- /release/run gm.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd gm\target 4 | java -jar gmServer.jar -------------------------------------------------------------------------------- /release/run logic.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd logic\target 4 | java -jar logicServer.jar --------------------------------------------------------------------------------