├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── README.md ├── bin ├── StartMultiServer.bat ├── StartSingleServer.bat ├── config.json ├── config_tcp_game.json ├── config_tcp_gate.json └── config_tcp_manager.json ├── cofig └── gameproto │ ├── all-build.bat │ ├── buildgo.bat │ ├── gamecode.proto │ ├── login.proto │ ├── msgs │ ├── build.bat │ ├── protos.proto │ └── share.proto │ └── share.proto └── src ├── GAServer ├── app │ └── app.go ├── config │ └── serviceConfig.go ├── data-structures │ ├── binary-tree │ │ ├── bst.go │ │ └── bst_test.go │ ├── graph │ │ ├── README.md │ │ ├── directed_graph.go │ │ ├── graph.go │ │ ├── graph_test.go │ │ └── undirected_graph.go │ ├── hash-tables │ │ ├── ht.go │ │ └── ht_test.go │ ├── heap │ │ ├── heap.go │ │ ├── heap_test.go │ │ └── util.go │ ├── linked-list │ │ ├── linked_list.go │ │ └── linked_list_test.go │ ├── list │ │ ├── list.go │ │ └── list_test.go │ ├── matrix │ │ ├── README.md │ │ ├── matrix.go │ │ └── matrix_test.go │ ├── priority-queue │ │ ├── priority_queue.go │ │ └── priority_queue_test.go │ ├── queue │ │ ├── queue.go │ │ └── queue_test.go │ └── stack │ │ ├── stack.go │ │ └── stack_test.go ├── db │ ├── dbclient.go │ └── dbclient_test.go ├── example │ ├── messages │ │ ├── build.bat │ │ ├── protos.pb.go │ │ └── protos.proto │ └── service │ │ └── server │ │ └── main.go ├── gateframework │ ├── agent.go │ └── gate.go ├── log │ ├── example_test.go │ ├── log.go │ └── loggroup.go ├── module │ └── module.go ├── network │ ├── agent.go │ ├── conn.go │ ├── processor.go │ ├── tcp_client.go │ ├── tcp_conn.go │ ├── tcp_msg.go │ ├── tcp_server.go │ ├── ws_client.go │ ├── ws_conn.go │ └── ws_server.go ├── service │ ├── service.go │ ├── serviceData.go │ └── service_test.go └── util │ ├── deepcopy.go │ ├── example_test.go │ ├── map.go │ ├── rand.go │ ├── semaphore.go │ ├── stack.go │ └── tools.go ├── Robot ├── agent │ ├── agent.go │ └── robot.go ├── robotMachine │ └── main.go └── robotTest │ ├── agent.go │ ├── r_test.go │ ├── robot.go │ └── robotTest.go ├── Server ├── center │ ├── centerserver.go │ └── serviceNode.go ├── cluster │ ├── cluster.go │ ├── regcenter.go │ └── remoteclient.go ├── config │ └── config.go ├── db │ ├── dbmgr.go │ └── gameMD.go ├── game │ ├── gameserver.go │ ├── module_test.go │ ├── player.go │ ├── playerChatModule.go │ ├── playerModuleBase.go │ └── playerShopModule.go ├── gate │ ├── agentActor.go │ ├── gameproto.go │ └── gateserver.go ├── login │ └── loginserver.go ├── server.go └── session │ ├── UnloginData.go │ ├── playerSession.go │ ├── sessionManager.go │ ├── session_test.go │ └── sessionserver.go └── gameproto ├── gamecode.pb.go ├── login.pb.go ├── msgs ├── protos.pb.go └── share.pb.go └── share.pb.go /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "exec",//"debug", 9 | "remotePath": "", 10 | "port": 2345, 11 | "host": "127.0.0.1", 12 | "program": "${workspaceRoot}\\bin\\server.exe", 13 | "env": {}, 14 | "args": [], 15 | "showLog": true 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // 将设置放入此文件中以覆盖默认值和用户设置。 2 | { 3 | "files.autoSave": "onFocusChange", 4 | 5 | "go.buildOnSave": true, 6 | 7 | "go.lintOnSave": true, 8 | 9 | "go.vetOnSave": true, 10 | 11 | "go.buildFlags": [], 12 | 13 | "go.lintFlags": [], 14 | 15 | "go.vetFlags": [], 16 | 17 | "go.useCodeSnippetsOnFunctionSuggest": false, 18 | 19 | "go.formatOnSave": true, 20 | 21 | "go.formatTool": "goreturns", 22 | 23 | "go.goroot": null, 24 | 25 | "go.gopath": "e:\\gopath;${workspaceRoot}" 26 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "go",//命令 xxx.exe 6 | "isShellCommand": true, 7 | //"args": ["build","-v","${file}"],//固定参数,多的用逗号分割 8 | "echoCommand":true,//是否显示命令 9 | "showOutput": "always", 10 | "suppressTaskName": true,// 11 | "options": { 12 | "env": { 13 | "GOPATH": "e:\\gopath;${workspaceRoot}"//工程目录和gopath 14 | } 15 | }, 16 | "tasks": [ 17 | { 18 | "taskName": "build", 19 | "args": ["build","-v","server"] 20 | }, 21 | { 22 | "taskName": "install", 23 | "args": ["install","-v","server"]//"${fileBasenameNoExtension}" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 停止维护。请移步新的项目 2 | - demo: https://github.com/magicsea/h5game 3 | - golang库:https://github.com/magicsea/ganet 4 | 5 | # ga_server 6 | 7 | 基于protoactor框架的actor游戏服务器。 8 | 9 | ## 设计动机 10 | - 一套面向actor的分布式游戏服务器 11 | - 实现可伸缩设计,缩可以放在一个进程,伸可以扩展多台机器均衡负载 12 | 13 | ## 目录结构 14 | - cofig:游戏协议,gameproto存放c2s/s2c协议,msgs存放s2s协议。打包将生成到src的gameproto目录 15 | - src/GAServer:基本库代码,主要是gate模块和service类型的封装 16 | - src/Robot:机器人测试代码,robotMachine是压力测试,robotTest是简单功能测试 17 | > 目前数据:robotCount= 500 time=ms 5457 all_qps= 91625.44 18 | - src/Server:里面是各种服务的实现。服务器的具体实现目录 19 | ## 启动 20 | - win编译出server执行文件 21 | - 可以直接执行server,默认读取config.json配置,所有服务在一个进程 22 | - 或者执行StartMultiServer.bat,启多个进程服务器,服务分开部署 23 | 24 | ## 登录流程 25 | 红色为单点,其他都是多点。 26 | login使用http协议和客户端沟通,其他请求通过gate转发 27 | ![image](http://on-img.com/chart_image/58f6d36be4b02e95ec64c368.png) 28 | 29 | ## 依赖 30 | 主要依赖protoactor里的库,具体参考protoactor的readme。简单的直接使用LiteIde执行go get一下就自动下载。google的几个库需要科学上网,没条件的下载我网盘里的[ google库](http://pan.baidu.com/s/1qYjUHJY) 31 | ## TODO 32 | - battleserver实现 33 | - gate加密 34 | - ... 35 | ## QQ群:285728047 36 | -------------------------------------------------------------------------------- /bin/StartMultiServer.bat: -------------------------------------------------------------------------------- 1 | start server.exe --config=config_tcp_manager.json 2 | start server.exe --config=config_tcp_gate.json 3 | start server.exe --config=config_tcp_game.json -------------------------------------------------------------------------------- /bin/StartSingleServer.bat: -------------------------------------------------------------------------------- 1 | start server.exe --config=config.json -------------------------------------------------------------------------------- /bin/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ver":"1.0", 3 | "db":{ 4 | "game":"root:tcg123456@tcp(192.168.3.194:3306)/tcg_new" 5 | }, 6 | "design":{ 7 | "path":"../config/csv/" 8 | }, 9 | "config":{ 10 | "log":{ 11 | "level":"info", 12 | "path":"log", 13 | "flag":18 14 | }, 15 | "_comment": "配置静态地址,value空表示本进程", 16 | "remote":{ 17 | "center":"127.0.0.1:8090" 18 | }, 19 | 20 | "_comment": "当前进程启动的所有服务配置,remoteAddr空表示本进程", 21 | "local":{ 22 | "login":{ 23 | "serviceName":"login", 24 | "serviceType":"login", 25 | "remoteAddr":"", 26 | "conf":{ 27 | "httpAddr":"127.0.0.1:9900" 28 | } 29 | }, 30 | "center":{ 31 | "serviceName":"center", 32 | "serviceType":"center", 33 | "remoteAddr":"127.0.0.1:8090" 34 | }, 35 | "session":{ 36 | "serviceName":"session", 37 | "serviceType":"session", 38 | "remoteAddr":"" 39 | }, 40 | "gate1":{ 41 | "serviceName":"gate1", 42 | "serviceType":"gate", 43 | "remoteAddr":"127.0.0.1:8070", 44 | "conf":{ 45 | "MaxConnNum":1000, 46 | "WsAddr":"", 47 | "TcpAddr":"127.0.0.1:7200" 48 | } 49 | }, 50 | "game1":{ 51 | "serviceName":"game1", 52 | "serviceType":"game", 53 | "remoteAddr":"" 54 | } 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /bin/config_tcp_game.json: -------------------------------------------------------------------------------- 1 | { 2 | "ver":"1.0", 3 | "config":{ 4 | "log":{ 5 | "level":"debug", 6 | "path":"log", 7 | "flag":18 8 | }, 9 | "_comment": "配置静态地址,value空表示本进程", 10 | "remote":{ 11 | "center":"127.0.0.1:8090", 12 | "session":"127.0.0.1:8091" 13 | }, 14 | 15 | "_comment": "当前进程启动的所有服务配置,remoteAddr空表示本进程", 16 | "local":{ 17 | "game1":{ 18 | "serviceName":"game1", 19 | "serviceType":"game", 20 | "remoteAddr":"127.0.0.1:9501" 21 | }, 22 | "game2":{ 23 | "serviceName":"game2", 24 | "serviceType":"game", 25 | "remoteAddr":"127.0.0.1:9502" 26 | } 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /bin/config_tcp_gate.json: -------------------------------------------------------------------------------- 1 | { 2 | "ver":"1.0", 3 | "config":{ 4 | "log":{ 5 | "level":"debug", 6 | "path":"log", 7 | "flag":18 8 | }, 9 | "_comment": "配置静态地址,value空表示本进程", 10 | "remote":{ 11 | "center":"127.0.0.1:8090", 12 | "session":"127.0.0.1:8091" 13 | }, 14 | 15 | "_comment": "当前进程启动的所有服务配置,remoteAddr空表示本进程", 16 | "local":{ 17 | "gate1":{ 18 | "serviceName":"gate1", 19 | "serviceType":"gate", 20 | "remoteAddr":"127.0.0.1:8071", 21 | "conf":{ 22 | "MaxConnNum":1000, 23 | "WsAddr":"", 24 | "TcpAddr":"127.0.0.1:7201" 25 | } 26 | }, 27 | "gate2":{ 28 | "serviceName":"gate2", 29 | "serviceType":"gate", 30 | "remoteAddr":"127.0.0.1:8072", 31 | "conf":{ 32 | "MaxConnNum":1000, 33 | "WsAddr":"", 34 | "TcpAddr":"127.0.0.1:7202" 35 | } 36 | } 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /bin/config_tcp_manager.json: -------------------------------------------------------------------------------- 1 | { 2 | "ver":"1.0", 3 | "config":{ 4 | "log":{ 5 | "level":"debug", 6 | "path":"log", 7 | "flag":18 8 | }, 9 | "_comment": "配置静态地址,value空表示本进程", 10 | "remote":{ 11 | "center":"127.0.0.1:8090", 12 | "session":"127.0.0.1:8091" 13 | }, 14 | 15 | "_comment": "当前进程启动的所有服务配置,remoteAddr空表示本进程", 16 | "local":{ 17 | "login":{ 18 | "serviceName":"login", 19 | "serviceType":"login", 20 | "remoteAddr":"", 21 | "conf":{ 22 | "httpAddr":"127.0.0.1:8080" 23 | } 24 | }, 25 | "center":{ 26 | "serviceName":"center", 27 | "serviceType":"center", 28 | "remoteAddr":"127.0.0.1:8090" 29 | }, 30 | "session":{ 31 | "serviceName":"session", 32 | "serviceType":"session", 33 | "remoteAddr":"127.0.0.1:8091" 34 | } 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /cofig/gameproto/all-build.bat: -------------------------------------------------------------------------------- 1 | echo "build msgs..." 2 | pushd msgs 3 | call build.bat 4 | popd 5 | 6 | echo "build cs proto..." 7 | call buildgo.bat 8 | -------------------------------------------------------------------------------- /cofig/gameproto/buildgo.bat: -------------------------------------------------------------------------------- 1 | protoc -I=. -I=.\.. -I=%GOPATH%\src -I=.\..\..\src --gogoslick_out=plugins=grpc:.\..\..\src\gameproto\ *.proto 2 | -------------------------------------------------------------------------------- /cofig/gameproto/gamecode.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package gameproto; 3 | 4 | enum C2GS_CMD { 5 | C2GS_NONE = 0; 6 | C2S_LOGIN = 1 ;// 登陆 7 | C2S_Test = 10;// 8 | 9 | C2S_HEART_INFO = 254 ;// 心跳包 10 | C2S_ACK = 255 ;// 确认包 11 | } 12 | 13 | enum GS2C_CMD { 14 | GS2C_NONE = 0; 15 | S2C_CONFIRM = 1 ;//确认信息 16 | 17 | S2C_LOGIN_END = 2 ;//登陆结束 18 | S2C_LOGIN_CHAR_INFO = 3 ;//用户信息 19 | 20 | S2C_Test = 10;// 21 | 22 | } -------------------------------------------------------------------------------- /cofig/gameproto/login.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package gameproto; 3 | //http登录结果 4 | message UserLoginResult { 5 | uint32 uid = 1; 6 | string gateAddr = 2; 7 | string key = 3; 8 | int32 result = 4; 9 | } 10 | 11 | 12 | message PlatformUser { 13 | enum PlatformType { 14 | Engine = 0; 15 | DEVICE = 99; 16 | 17 | } 18 | string platformId=1; 19 | PlatformType platform=2; 20 | string platformSession=3; 21 | int32 platformUid=4; 22 | int32 serverID=5; 23 | string channelId=6; 24 | int32 version=7; 25 | string key = 8; 26 | } 27 | 28 | 29 | message LoginReturn { 30 | int32 errCode=1; 31 | int32 serverTime=2; 32 | string args=3; 33 | int32 bFirst=4; 34 | } 35 | -------------------------------------------------------------------------------- /cofig/gameproto/msgs/build.bat: -------------------------------------------------------------------------------- 1 | protoc -I=. -I=.\..\..\..\src -I=%GOPATH%\src -I=..\.. --gogoslick_out=plugins=grpc:.\..\..\..\src\gameproto\msgs\ *.proto 2 | -------------------------------------------------------------------------------- /cofig/gameproto/msgs/protos.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package msgs; 3 | import "github.com/AsynkronIT/protoactor-go/actor/protos.proto"; 4 | import "share.proto"; 5 | //==========Login=========== 6 | //登入游戏验证 7 | message CheckLogin { 8 | uint64 uid = 1; 9 | string key = 2; 10 | } 11 | message HeartBeatMsg { 12 | } 13 | 14 | //=========shop============= 15 | enum ShopMsgType { 16 | C2S_ShopBuy = 0; 17 | S2C_ShopBuy = 1; 18 | C2S_ShopSell = 2; 19 | S2C_ShopSell = 3; 20 | } 21 | 22 | message C2S_ShopBuyMsg { 23 | uint32 itemId = 1; 24 | } 25 | message S2C_ShopBuyMsg { 26 | uint32 itemId = 1; 27 | GAErrorCode result = 2; 28 | } 29 | //=========bag============== 30 | enum BagMsgType { 31 | S2C_Bag = 0; 32 | } 33 | 34 | //=========chat============= 35 | enum ChatMsgType { 36 | C2S_PrivateChat = 0; 37 | S2C_PrivateChat = 1; 38 | S2C_PrivateOtherChat = 2; 39 | C2S_WorldChat = 3; 40 | S2C_WorldChat = 4; 41 | } 42 | 43 | 44 | message C2S_PrivateChatMsg { 45 | string targetName = 1; 46 | string msg = 2; 47 | } 48 | 49 | message S2C_PrivateChatMsg { 50 | string targetName = 1; 51 | string msg = 2; 52 | GAErrorCode result = 3; 53 | } 54 | 55 | message S2C_PrivateOtherChatMsg { 56 | string sendName = 1; 57 | string msg = 2; 58 | } 59 | 60 | message C2S_WorldChatMsg { 61 | string msg = 1; 62 | } 63 | message S2C_WorldChatMsg { 64 | string sendName = 1; 65 | string msg = 2; 66 | } 67 | 68 | 69 | 70 | //客户端消息转rpc通用消息 71 | message FrameMsg { 72 | ChannelType channel = 1; 73 | uint32 msgId = 2; 74 | bytes rawData = 3; 75 | } 76 | 77 | message FrameMsgReq { 78 | FrameMsg frame = 1; 79 | uint32 cno = 2; 80 | } 81 | message FrameMsgRep { 82 | //uint32 msgId = 1; 83 | //uint32 cno = 2; 84 | GAErrorCode errCode = 1; 85 | } 86 | //gate发送协议 87 | //单 88 | message UnicastFrameMsg { 89 | FrameMsg frameMsg = 1; 90 | uint64 target = 2; 91 | } 92 | //组 93 | message MulticastFrameMsg { 94 | FrameMsg frameMsg = 1; 95 | repeated uint64 targets = 2; 96 | } 97 | //广播 98 | message BroadcastFrameMsg { 99 | FrameMsg frameMsg = 1; 100 | } 101 | 102 | //加入到管理 103 | message AddAgentToParent { 104 | uint64 uid = 1; 105 | actor.PID sender = 2; 106 | } 107 | //移除管理 108 | message RemoveAgentFromParent { 109 | uint64 uid = 1; 110 | } 111 | 112 | message NewChild { 113 | 114 | } 115 | message NewChildResult { 116 | actor.PID pid = 1; 117 | } 118 | 119 | message Connect { 120 | actor.PID Sender = 1; 121 | } 122 | 123 | message Connected { 124 | string Message = 1; 125 | } 126 | 127 | message SpawnAgent { 128 | 129 | } 130 | 131 | //服务器状态 132 | enum ServiceState { 133 | ServiceStateFree = 0; 134 | ServiceFull = 1; 135 | ServiceStop = 2; 136 | } 137 | 138 | message ServiceValue { 139 | string Key = 1; 140 | string Value = 2; 141 | } 142 | //注册服务器 143 | message AddService { 144 | string serviceName = 1; 145 | string serviceType = 2; 146 | actor.PID pid = 3; 147 | repeated ServiceValue values = 4; 148 | } 149 | //发送成功的通用返回 150 | message SendOK { 151 | } 152 | //解注册服务器 153 | message RemoveService { 154 | string serviceName = 1; 155 | string serviceType = 2; 156 | } 157 | //分配服务器 158 | message ApplyService { 159 | string serviceType = 1; 160 | } 161 | 162 | //分配服务器,返回 163 | message ApplyServiceResult { 164 | string serviceType = 1; 165 | string serviceName = 2; 166 | actor.PID pid = 3; 167 | repeated ServiceValue values = 4; 168 | GAErrorCode result = 5; 169 | } 170 | //分配所有服务器 171 | message GetTypeServices { 172 | string serviceType = 1; 173 | } 174 | 175 | message GetTypeServicesResult { 176 | repeated actor.PID pids = 1; 177 | } 178 | 179 | //长传更新服务器信息 180 | message UploadService { 181 | string serviceName = 1; 182 | uint32 load = 2; 183 | ServiceState state = 3; 184 | } 185 | 186 | 187 | //登录 188 | message UserLogin { 189 | string account = 1; 190 | uint64 uid = 2; 191 | } 192 | 193 | 194 | //获取玩家session信息 195 | message GetSessionInfo { 196 | uint64 uid = 1; 197 | } 198 | message GetSessionInfoByName { 199 | string name = 1; 200 | } 201 | message GetSessionInfoResult { 202 | UserBaseInfo userInfo = 1; 203 | actor.PID agentPID = 2; 204 | GAErrorCode result = 3; 205 | } 206 | 207 | //玩家断线 208 | message ClientDisconnect { 209 | } 210 | //gate收到消息 211 | message ReceviceClientMsg { 212 | bytes rawdata = 1; 213 | } 214 | //玩家离开 215 | message UserLeave { 216 | uint64 uid = 1; 217 | ServerType from = 2; 218 | string reason = 3; 219 | } 220 | 221 | //踢下线 222 | message Kick { 223 | uint64 uid = 1; 224 | string reason = 2; 225 | } 226 | 227 | //服务器check 228 | message ServerCheckLogin { 229 | uint64 uid = 1; 230 | string key = 2; 231 | actor.PID agentPID = 3; 232 | } 233 | 234 | //服务器绑定信息 235 | message UserBindServer { 236 | ChannelType channel = 1; 237 | actor.PID pid = 2; 238 | } 239 | 240 | //人物基本信息 241 | message UserBaseInfo { 242 | string account = 1; 243 | string name = 2; 244 | uint64 uid = 3; 245 | uint64 lv = 4; 246 | uint64 exp = 5; 247 | uint64 exptime = 6; 248 | } 249 | //验证结果 250 | message CheckLoginResult { 251 | GAErrorCode result = 1; 252 | UserBaseInfo baseInfo = 2; 253 | repeated UserBindServer bindServers = 3; 254 | } 255 | 256 | //创建玩家 257 | message CreatePlayer { 258 | uint64 uid = 1; 259 | actor.PID agentPID = 2; 260 | actor.PID sender = 3; 261 | actor.PID gatePID = 4; 262 | string key = 5; 263 | } 264 | message CreatePlayerResult { 265 | GAErrorCode result = 1; 266 | UserBaseInfo baseInfo = 2; 267 | actor.PID playerPID = 3;//gs的player地址 268 | CreatePlayer transData = 4; 269 | } 270 | 271 | //掉线 272 | message PlayerOutline { 273 | string reason = 1; 274 | } 275 | 276 | //心跳 277 | message Tick { 278 | } 279 | 280 | -------------------------------------------------------------------------------- /cofig/gameproto/msgs/share.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package msgs; 3 | 4 | //错误类型 5 | enum GAErrorCode { 6 | OK = 0; 7 | Fail = 1; 8 | Error = 2; 9 | ServerFull = 3; 10 | KeyError = 4; 11 | NoFoundTarget = 5; 12 | 13 | //old code 14 | IMPORTANT_WRONG_HEAD = -1000 ;// # 包头不存在 15 | 16 | RESOURCE_VITALITY_ERROR = 1002 ;// # 体力不足 17 | RESOURCE_GOLD_ERROR = 1003 ;//# 金币不足 18 | RESOURCE_RMB_ERROR = 1004 ;// # 钻石不足 19 | 20 | GUILD_EXIT_CHAIRMAN_ERROR = 1022 ;// # 您必须先转移会长 21 | 22 | UNKNOWN_ERROR = -9999 ;//未知错误 23 | } 24 | 25 | 26 | //服务器类型 27 | enum ServerType { 28 | ST_NONE = 0; 29 | ST_LoginServer = 1; 30 | ST_GateServer = 2; 31 | ST_GameServer = 4; 32 | ST_BattleServer = 8; 33 | ST_CenterServer = 16; 34 | ST_SessionServer = 32; 35 | 36 | ST_ALLServer = 63; 37 | } 38 | 39 | //消息主类型 40 | enum ChannelType { 41 | Login = 0; 42 | Heartbeat = 1; 43 | 44 | GameServer = 100; 45 | Shop = 101; 46 | Chat = 102; 47 | Bag = 103; //道具包 48 | Attr = 104; //人物属性 49 | GroupCard = 105; //卡包 50 | Stage = 106; //关卡 51 | Hero = 107; //英雄 52 | Wallet = 108; //钱包 53 | MainQuest = 109; //主线任务 54 | DailyQuest = 110; //每日任务 55 | 56 | BattleServer = 200; 57 | } 58 | -------------------------------------------------------------------------------- /cofig/gameproto/share.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package gameproto; 3 | 4 | 5 | //错误类型 6 | enum ErrorCode { 7 | OK = 0; 8 | Fail = 1; 9 | Error = 2; 10 | ServerFull = 3; 11 | KeyError = 4; 12 | NoFoundTarget = 5; 13 | 14 | //old code 15 | IMPORTANT_WRONG_HEAD = -1000 ;// # 包头不存在 16 | 17 | RESOURCE_VITALITY_ERROR = 1002 ;// # 体力不足 18 | RESOURCE_GOLD_ERROR = 1003 ;//# 金币不足 19 | RESOURCE_RMB_ERROR = 1004 ;// # 钻石不足 20 | 21 | GUILD_EXIT_CHAIRMAN_ERROR = 1022 ;// # 您必须先转移会长 22 | 23 | UNKNOWN_ERROR = -9999 ;//未知错误 24 | } 25 | message C2S_TestMsg { 26 | uint32 id = 1; 27 | } 28 | message S2C_TestMsg { 29 | uint32 id = 1; 30 | } 31 | message S2C_ConfirmInfo{ 32 | int32 msgHead = 1; 33 | int32 code = 2; 34 | } -------------------------------------------------------------------------------- /src/GAServer/app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | . "GAServer/config" 5 | "GAServer/log" 6 | "GAServer/module" 7 | "GAServer/service" 8 | "GAServer/util" 9 | "os" 10 | "os/signal" 11 | ) 12 | 13 | type MakeServiceFunc func() service.IService 14 | 15 | var ( 16 | serviceTypeMap map[string]MakeServiceFunc 17 | services []service.IService 18 | modules []module.IModule 19 | ) 20 | 21 | func init() { 22 | serviceTypeMap = make(map[string]MakeServiceFunc) 23 | } 24 | 25 | func RegisterService(serviceType string, f MakeServiceFunc) { 26 | serviceTypeMap[serviceType] = f 27 | } 28 | 29 | func Run(conf *ServiceConfig, ms ...module.IModule) { 30 | SetGlobleConfig(conf) 31 | 32 | //init log 33 | if conf.LogConf.LogLevel != "" { 34 | err := log.NewLogGroup(conf.LogConf.LogLevel, conf.LogConf.LogPath, true, conf.LogConf.LogFlag) 35 | if err != nil { 36 | panic(err) 37 | } 38 | //log.Export(logger) 39 | defer log.Close() 40 | } 41 | 42 | defer util.PrintPanicStack() 43 | 44 | log.Info("log started.") 45 | modules = ms 46 | for _, m := range modules { 47 | if !m.OnInit() { 48 | log.Fatal("%v module.OnInit fail", m) 49 | } 50 | } 51 | for _, m := range modules { 52 | m.Run() 53 | } 54 | //cluster.InitCluster() 55 | //生成服务对象 56 | for _, sc := range conf.Services { 57 | makefunc := serviceTypeMap[sc.ServiceType] 58 | if makefunc != nil { 59 | ser := makefunc() 60 | log.Info("生成服务:", sc.ServiceName) 61 | ser.Init(sc.RemoteAddr, sc.ServiceName, sc.ServiceType) 62 | services = append(services, ser) 63 | } else { 64 | log.Fatal("未注册的服务类型:", sc) 65 | } 66 | } 67 | 68 | //init 69 | for _, ser := range services { 70 | log.Println("init服务:", ser.GetName()) 71 | ser.OnInit() 72 | } 73 | 74 | //start 75 | for _, ser := range services { 76 | log.Println("start服务:", ser.GetName()) 77 | service.StartService(ser) 78 | } 79 | 80 | // close 81 | c := make(chan os.Signal, 1) 82 | signal.Notify(c, os.Interrupt, os.Kill) 83 | sig := <-c 84 | log.Println("closing down (signal: %v)", sig) 85 | OnDestory() 86 | } 87 | 88 | func OnDestory() { 89 | for _, ser := range services { 90 | log.Println("destory服务:", ser.GetName()) 91 | ser.OnDestory() 92 | } 93 | for _, m := range modules { 94 | m.OnDestroy() 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/GAServer/config/serviceConfig.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type ServiceNodeConfig struct { 4 | ServiceName string `json:"serviceName"` //服务名 (gameserver) 5 | ServiceType string `json:"serviceType"` //服务类型 (gameserver1) 6 | RemoteAddr string `json:"remoteAddr"` //远程地址 (127.0.0.1:80 or "",空字符表示本地启动) 7 | Conf map[string]interface{} `json:"conf"` //单体配置 8 | } 9 | type LogConfig struct { 10 | LogLevel string `json:"level"` 11 | LogPath string `json:"path"` 12 | LogFlag int `json:"flag"` 13 | } 14 | 15 | type ServiceConfig struct { 16 | Services map[string]*ServiceNodeConfig `json:"local"` 17 | RemoteAddrs map[string]string `json:"remote"` 18 | LogConf *LogConfig `json:"log"` 19 | } 20 | 21 | var globleConfig ServiceConfig 22 | 23 | func SetGlobleConfig(conf *ServiceConfig) { 24 | globleConfig = *conf 25 | } 26 | 27 | func GetGlobleConfig() *ServiceConfig { 28 | return &globleConfig 29 | } 30 | 31 | func GetServiceConfig(ser string, key string) interface{} { 32 | return globleConfig.Services[ser].Conf[key] 33 | } 34 | 35 | func GetServiceConfigString(ser string, key string) string { 36 | return GetServiceConfig(ser, key).(string) 37 | } 38 | 39 | func GetServiceConfigInt(ser string, key string) int { 40 | f := GetServiceConfig(ser, key).(float64) 41 | return int(f) 42 | } 43 | 44 | //GetServiceAddress 获取服务地址,先去remote找,没有就到本地找 45 | func GetServiceAddress(serviceName string) string { 46 | if globleConfig.RemoteAddrs != nil { 47 | return globleConfig.RemoteAddrs[serviceName] 48 | } else { 49 | return globleConfig.Services[serviceName].RemoteAddr 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/binary-tree/bst.go: -------------------------------------------------------------------------------- 1 | package bst 2 | 3 | import () 4 | 5 | type Node struct { 6 | Value int 7 | Parent *Node 8 | Left *Node 9 | Right *Node 10 | } 11 | 12 | func NewNode(i int) *Node { 13 | return &Node{Value: i} 14 | } 15 | 16 | func (n *Node) Compare(m *Node) int { 17 | if n.Value < m.Value { 18 | return -1 19 | } else if n.Value > m.Value { 20 | return 1 21 | } else { 22 | return 0 23 | } 24 | } 25 | 26 | type Tree struct { 27 | Head *Node 28 | Size int 29 | } 30 | 31 | func NewTree(n *Node) *Tree { 32 | if n == nil { 33 | return &Tree{} 34 | } 35 | return &Tree{Head: n, Size: 1} 36 | } 37 | 38 | func (t *Tree) Insert(i int) { 39 | n := &Node{Value: i} 40 | if t.Head == nil { 41 | t.Head = n 42 | t.Size++ 43 | return 44 | } 45 | 46 | h := t.Head 47 | 48 | for { 49 | if n.Compare(h) == -1 { 50 | if h.Left == nil { 51 | h.Left = n 52 | n.Parent = h 53 | break 54 | } else { 55 | h = h.Left 56 | } 57 | } else { 58 | if h.Right == nil { 59 | h.Right = n 60 | n.Parent = h 61 | break 62 | } else { 63 | h = h.Right 64 | } 65 | } 66 | } 67 | t.Size++ 68 | } 69 | 70 | func (t *Tree) Search(i int) *Node { 71 | h := t.Head 72 | n := &Node{Value: i} 73 | 74 | for h != nil { 75 | switch h.Compare(n) { 76 | case -1: 77 | h = h.Right 78 | case 1: 79 | h = h.Left 80 | case 0: 81 | return h 82 | default: 83 | panic("Node not found") 84 | } 85 | } 86 | panic("Node not found") 87 | } 88 | 89 | // returns true if a node with value i was found 90 | // and deleted and returns false otherwise 91 | func (t *Tree) Delete(i int) bool { 92 | var parent *Node 93 | 94 | h := t.Head 95 | n := &Node{Value: i} 96 | for h != nil { 97 | switch n.Compare(h) { 98 | case -1: 99 | parent = h 100 | h = h.Left 101 | case 1: 102 | parent = h 103 | h = h.Right 104 | case 0: 105 | if h.Left != nil { 106 | right := h.Right 107 | h.Value = h.Left.Value 108 | h.Left = h.Left.Left 109 | h.Right = h.Left.Right 110 | 111 | if right != nil { 112 | subTree := &Tree{Head: h} 113 | IterOnTree(right, func(n *Node) { 114 | subTree.Insert(n.Value) 115 | }) 116 | } 117 | t.Size-- 118 | return true 119 | } 120 | 121 | if h.Right != nil { 122 | h.Value = h.Right.Value 123 | h.Left = h.Right.Left 124 | h.Right = h.Right.Right 125 | 126 | t.Size-- 127 | return true 128 | } 129 | 130 | if parent == nil { 131 | t.Head = nil 132 | t.Size-- 133 | return true 134 | } 135 | 136 | if parent.Left == n { 137 | parent.Left = nil 138 | } else { 139 | parent.Right = nil 140 | } 141 | t.Size-- 142 | return true 143 | } 144 | } 145 | return false 146 | } 147 | 148 | func IterOnTree(n *Node, f func(*Node)) bool { 149 | if n == nil { 150 | return true 151 | } 152 | if !IterOnTree(n.Left, f) { 153 | return false 154 | } 155 | 156 | f(n) 157 | 158 | return IterOnTree(n.Right, f) 159 | } 160 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/binary-tree/bst_test.go: -------------------------------------------------------------------------------- 1 | package bst 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestTree(t *testing.T) { 9 | n := NewNode(1) 10 | m := NewNode(2) 11 | 12 | // Test compare 13 | if n.Compare(m) != -1 || m.Compare(n) != 1 || n.Compare(n) != 0 { 14 | fmt.Println(n.Compare(m)) 15 | t.Error() 16 | } 17 | 18 | tree := NewTree(n) 19 | 20 | tree.Insert(4) 21 | tree.Insert(2) 22 | tree.Insert(5) 23 | tree.Insert(3) 24 | tree.Insert(6) 25 | 26 | if tree.Size != 6 { 27 | fmt.Println(tree.Size) 28 | t.Error() 29 | } 30 | 31 | five := tree.Search(5) 32 | 33 | if five.Value != 5 || 34 | five.Parent.Value != 4 || 35 | five.Right.Value != 6 || 36 | five.Left != nil { 37 | fmt.Println(*tree.Search(5)) 38 | t.Error() 39 | } 40 | 41 | tree.Delete(5) 42 | 43 | if tree.Size != 5 { 44 | t.Error() 45 | } 46 | 47 | four := *tree.Search(4) 48 | if four.Right.Value != 6 || 49 | four.Left.Value != 2 || 50 | four.Parent.Value != 1 { 51 | fmt.Println(*tree.Search(4)) 52 | t.Error() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/graph/README.md: -------------------------------------------------------------------------------- 1 | # graph-go [![Build Status](https://travis-ci.org/arnauddri/graph-go.svg?branch=master)](https://travis-ci.org/arnauddri/graph-go) [![Coverage Status](https://img.shields.io/coveralls/arnauddri/graph-go.svg)](https://coveralls.io/r/arnauddri/graph-go?branch=master) 2 | 3 | An implementation of several graph algorithms in Go 4 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/graph/directed_graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type DirGraph struct { 4 | graph 5 | } 6 | 7 | func NewDirected() *DirGraph { 8 | return &DirGraph{ 9 | graph{ 10 | edgesCount: 0, 11 | edges: make(map[VertexId]map[VertexId]int), 12 | isDirected: true, 13 | }, 14 | } 15 | } 16 | 17 | func (g *graph) GetPredecessors(vertex VertexId) VerticesIterable { 18 | iterator := func() <-chan VertexId { 19 | ch := make(chan VertexId) 20 | go func() { 21 | if connected, ok := g.edges[vertex]; ok { 22 | for VertexId, _ := range connected { 23 | if g.IsEdge(VertexId, vertex) { 24 | ch <- VertexId 25 | } 26 | } 27 | } 28 | close(ch) 29 | }() 30 | return ch 31 | } 32 | 33 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 34 | } 35 | 36 | func (g *graph) GetSuccessors(vertex VertexId) VerticesIterable { 37 | iterator := func() <-chan VertexId { 38 | ch := make(chan VertexId) 39 | go func() { 40 | if connected, ok := g.edges[vertex]; ok { 41 | for VertexId, _ := range connected { 42 | if g.IsEdge(vertex, VertexId) { 43 | ch <- VertexId 44 | } 45 | } 46 | } 47 | close(ch) 48 | }() 49 | return ch 50 | } 51 | 52 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 53 | } 54 | 55 | func (g *DirGraph) Reverse() *DirGraph { 56 | r := NewDirected() 57 | 58 | vertices := g.VerticesIter() 59 | for vertex := range vertices { 60 | r.AddVertex(vertex) 61 | } 62 | 63 | edges := g.EdgesIter() 64 | for edge := range edges { 65 | r.AddEdge(edge.To, edge.From, 1) 66 | } 67 | 68 | return r 69 | } 70 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/graph/graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type VertexId uint 8 | 9 | type Vertices []VertexId 10 | 11 | type Edge struct { 12 | From VertexId 13 | To VertexId 14 | } 15 | 16 | type graph struct { 17 | edges map[VertexId]map[VertexId]int 18 | edgesCount int 19 | isDirected bool 20 | } 21 | 22 | type EdgesIterable interface { 23 | EdgesIter() <-chan Edge 24 | } 25 | 26 | type VerticesIterable interface { 27 | VerticesIter() <-chan VertexId 28 | } 29 | 30 | func (g *graph) EdgesIter() <-chan Edge { 31 | ch := make(chan Edge) 32 | go func() { 33 | for from, connectedVertices := range g.edges { 34 | for to, _ := range connectedVertices { 35 | if g.isDirected { 36 | ch <- Edge{from, to} 37 | } else { 38 | if from < to { 39 | ch <- Edge{from, to} 40 | } 41 | } 42 | } 43 | } 44 | close(ch) 45 | }() 46 | return ch 47 | } 48 | 49 | func (g *graph) VerticesIter() <-chan VertexId { 50 | ch := make(chan VertexId) 51 | go func() { 52 | for vertex, _ := range g.edges { 53 | ch <- vertex 54 | } 55 | close(ch) 56 | }() 57 | return ch 58 | } 59 | 60 | func (g *graph) CheckVertex(vertex VertexId) bool { 61 | _, exists := g.edges[vertex] 62 | 63 | return exists 64 | } 65 | 66 | func (g *graph) TouchVertex(vertex VertexId) { 67 | if _, ok := g.edges[vertex]; !ok { 68 | g.edges[vertex] = make(map[VertexId]int) 69 | } 70 | } 71 | 72 | func (g *graph) AddVertex(vertex VertexId) error { 73 | i, _ := g.edges[vertex] 74 | if i != nil { 75 | return errors.New("Vertex already exists") 76 | } 77 | 78 | g.edges[vertex] = make(map[VertexId]int) 79 | 80 | return nil 81 | } 82 | 83 | func (g *graph) RemoveVertex(vertex VertexId) error { 84 | if !g.IsVertex(vertex) { 85 | return errors.New("Unknown vertex") 86 | } 87 | 88 | delete(g.edges, vertex) 89 | 90 | for _, connectedVertices := range g.edges { 91 | delete(connectedVertices, vertex) 92 | } 93 | 94 | return nil 95 | } 96 | 97 | func (g *graph) IsVertex(vertex VertexId) (exist bool) { 98 | _, exist = g.edges[vertex] 99 | 100 | return 101 | } 102 | 103 | func (g *graph) VerticesCount() int { 104 | return len(g.edges) 105 | } 106 | 107 | func (g *graph) AddEdge(from, to VertexId, weight int) error { 108 | if from == to { 109 | return errors.New("Cannot add self loop") 110 | } 111 | 112 | if !g.CheckVertex(from) || !g.CheckVertex(to) { 113 | return errors.New("Vertices don't exist") 114 | } 115 | 116 | i, _ := g.edges[from][to] 117 | j, _ := g.edges[to][from] 118 | 119 | if i > 0 || j > 0 { 120 | return errors.New("Edge already defined") 121 | } 122 | 123 | g.TouchVertex(from) 124 | g.TouchVertex(to) 125 | 126 | g.edges[from][to] = weight 127 | 128 | if !g.isDirected { 129 | g.edges[to][from] = weight 130 | } 131 | 132 | g.edgesCount++ 133 | 134 | return nil 135 | } 136 | 137 | func (g *graph) RemoveEdge(from, to VertexId) error { 138 | i, _ := g.edges[from][to] 139 | j, _ := g.edges[to][from] 140 | 141 | if i == -1 || j == -1 { 142 | return errors.New("Edge doesn't exist") 143 | } 144 | 145 | g.edges[from][to] = -1 146 | 147 | if !g.isDirected { 148 | g.edges[to][from] = -1 149 | } 150 | 151 | g.edgesCount-- 152 | 153 | return nil 154 | } 155 | 156 | func (g *graph) IsEdge(from, to VertexId) bool { 157 | connected, ok := g.edges[from] 158 | 159 | if !ok { 160 | return false 161 | } 162 | 163 | weight := connected[to] 164 | return weight > 0 165 | } 166 | 167 | func (g *graph) Order() int { 168 | return len(g.edges) 169 | } 170 | 171 | func (g *graph) EdgesCount() int { 172 | return g.edgesCount 173 | } 174 | 175 | func (g *graph) GetEdge(from, to VertexId) int { 176 | return g.edges[from][to] 177 | } 178 | 179 | func (g *graph) GetNeighbours(vertex VertexId) VerticesIterable { 180 | iterator := func() <-chan VertexId { 181 | ch := make(chan VertexId) 182 | go func() { 183 | if connected, ok := g.edges[vertex]; ok { 184 | for VertexId, _ := range connected { 185 | ch <- VertexId 186 | } 187 | } 188 | close(ch) 189 | }() 190 | return ch 191 | } 192 | 193 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 194 | } 195 | 196 | type vertexIterableHelper struct { 197 | iterFunc func() <-chan VertexId 198 | } 199 | 200 | func (helper *vertexIterableHelper) VerticesIter() <-chan VertexId { 201 | return helper.iterFunc() 202 | } 203 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/graph/graph_test.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestUndirectedGraph(t *testing.T) { 9 | g := NewUndirected() 10 | 11 | for i := 0; i < 10; i++ { 12 | v := VertexId(i) 13 | g.AddVertex(v) 14 | } 15 | 16 | if len(g.edges) != 10 { 17 | fmt.Println(g) 18 | t.Error() 19 | } 20 | 21 | for i := 0; i < 10; i++ { 22 | g.AddEdge(VertexId(i), VertexId(i%2), 1) 23 | } 24 | 25 | if g.IsEdge(0, 8) == false || g.IsEdge(0, 9) == true || g.CheckVertex(2) != true { 26 | fmt.Println(g) 27 | t.Error() 28 | } 29 | 30 | // AddEdge should fail for already existing Edge 31 | err := g.AddEdge(0, 2, 1) 32 | if err == nil { 33 | fmt.Println(g) 34 | t.Error() 35 | } 36 | 37 | // AddVertex should fail for already existing vertex 38 | err = g.AddVertex(0) 39 | if err == nil { 40 | fmt.Println(g) 41 | t.Error() 42 | } 43 | 44 | g.RemoveVertex(VertexId(9)) 45 | 46 | if g.IsVertex(VertexId(9)) { 47 | fmt.Println(g.edges[9] == nil) 48 | t.Error() 49 | } 50 | 51 | // RemoveVertex should fail for unknown vertex 52 | err = g.RemoveVertex(VertexId(9)) 53 | 54 | if err == nil { 55 | fmt.Println(g.edges[9] == nil) 56 | t.Error() 57 | } 58 | 59 | g.RemoveEdge(0, 8) 60 | 61 | if g.IsEdge(VertexId(0), VertexId(8)) == true || g.edgesCount != 7 { 62 | fmt.Println(g.IsEdge(VertexId(0), VertexId(8)), g.edgesCount) 63 | t.Error() 64 | } 65 | 66 | // RemoveEdge should fail for unknown egde 67 | err = g.RemoveEdge(0, 8) 68 | 69 | if err == nil { 70 | fmt.Println(g) 71 | t.Error() 72 | } 73 | 74 | c := g.EdgesIter() 75 | 76 | countEdge := 0 77 | for _ = range c { 78 | countEdge++ 79 | } 80 | 81 | if g.EdgesCount() != countEdge { 82 | t.Error() 83 | } 84 | 85 | d := g.VerticesIter() 86 | verticesCount := g.Order() 87 | countVertices := 0 88 | 89 | for _ = range d { 90 | countVertices++ 91 | } 92 | 93 | if countVertices != verticesCount { 94 | fmt.Println(countVertices, g.edges) 95 | t.Error() 96 | } 97 | 98 | g.TouchVertex(9) 99 | if _, ok := g.edges[9]; !ok { 100 | t.Error() 101 | } 102 | } 103 | 104 | func TestDirectedGraph(t *testing.T) { 105 | g := NewDirected() 106 | 107 | for i := 0; i < 10; i++ { 108 | g.AddVertex(VertexId(i)) 109 | } 110 | 111 | if len(g.edges) != 10 { 112 | fmt.Println(g) 113 | t.Error() 114 | } 115 | 116 | for i := 0; i < 10; i++ { 117 | g.AddEdge(VertexId(i), VertexId(i%2), 1) 118 | } 119 | 120 | r := g.Reverse() 121 | if !r.IsEdge(1, 7) || r.IsEdge(8, 0) { 122 | fmt.Println(r.edges) 123 | t.Error() 124 | } 125 | 126 | successors := r.GetSuccessors(1).VerticesIter() 127 | for successor := range successors { 128 | if successor != 3 && 129 | successor != 5 && 130 | successor != 7 && 131 | successor != 9 { 132 | t.Error() 133 | } 134 | } 135 | 136 | predecessors := g.GetPredecessors(1).VerticesIter() 137 | for predecessor := range predecessors { 138 | if predecessor != 3 && 139 | predecessor != 5 && 140 | predecessor != 7 && 141 | predecessor != 9 { 142 | t.Error() 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/graph/undirected_graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type UnGraph struct { 4 | graph 5 | } 6 | 7 | func NewUndirected() *UnGraph { 8 | return &UnGraph{ 9 | graph{ 10 | edgesCount: 0, 11 | edges: make(map[VertexId]map[VertexId]int), 12 | isDirected: false, 13 | }, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/hash-tables/ht.go: -------------------------------------------------------------------------------- 1 | // Implementation of a Hash Table with Separate Chaining 2 | // with linked lists using Horner's hash function 3 | // http://en.wikipedia.org/wiki/Hash_table#Separate_chaining_with_linked_lists 4 | package ht 5 | 6 | import ( 7 | "GAServer/data-structures/linked-list" 8 | "errors" 9 | "math" 10 | ) 11 | 12 | type HashTable struct { 13 | Table map[int]*list.List 14 | Size int 15 | Capacity int 16 | } 17 | 18 | type item struct { 19 | key string 20 | value interface{} 21 | } 22 | 23 | func New(cap int) *HashTable { 24 | table := make(map[int]*list.List, cap) 25 | return &HashTable{Table: table, Size: 0, Capacity: cap} 26 | } 27 | 28 | func (ht *HashTable) Get(key string) (interface{}, error) { 29 | index := ht.position(key) 30 | item, err := ht.find(index, key) 31 | 32 | if item == nil { 33 | return "", errors.New("Not Found") 34 | } 35 | 36 | return item.value, err 37 | } 38 | 39 | func (ht *HashTable) Put(key, value string) { 40 | index := ht.position(key) 41 | 42 | if ht.Table[index] == nil { 43 | ht.Table[index] = list.NewList() 44 | } 45 | 46 | item := &item{key: key, value: value} 47 | 48 | a, err := ht.find(index, key) 49 | if err != nil { 50 | // The key doesn't exist in HashTable 51 | ht.Table[index].Append(item) 52 | ht.Size++ 53 | } else { 54 | // The key exists so we overwrite its value 55 | a.value = value 56 | } 57 | } 58 | 59 | func (ht *HashTable) Del(key string) error { 60 | index := ht.position(key) 61 | l := ht.Table[index] 62 | var val *item 63 | 64 | l.Each(func(node list.Node) { 65 | if node.Value.(*item).key == key { 66 | val = node.Value.(*item) 67 | } 68 | }) 69 | 70 | if val == nil { 71 | return nil 72 | } 73 | 74 | ht.Size-- 75 | return l.Remove(val) 76 | } 77 | 78 | func (ht *HashTable) ForEach(f func(*item)) { 79 | for k := range ht.Table { 80 | if ht.Table[k] != nil { 81 | ht.Table[k].Each(func(node list.Node) { 82 | f(node.Value.(*item)) 83 | }) 84 | } 85 | } 86 | } 87 | 88 | func (ht *HashTable) position(s string) int { 89 | return hashCode(s) % ht.Capacity 90 | } 91 | 92 | func (ht *HashTable) find(i int, key string) (*item, error) { 93 | l := ht.Table[i] 94 | var val *item 95 | 96 | l.Each(func(node list.Node) { 97 | if node.Value.(*item).key == key { 98 | val = node.Value.(*item) 99 | } 100 | }) 101 | 102 | if val == nil { 103 | return nil, errors.New("Not Found") 104 | } 105 | 106 | return val, nil 107 | } 108 | 109 | // Horner's Method to hash string of length L (O(L)) 110 | func hashCode(s string) int { 111 | hash := int32(0) 112 | for i := 0; i < len(s); i++ { 113 | hash = int32(hash<<5-hash) + int32(s[i]) 114 | hash &= hash 115 | } 116 | return int(math.Abs(float64(hash))) 117 | } 118 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/hash-tables/ht_test.go: -------------------------------------------------------------------------------- 1 | package ht 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestHt(t *testing.T) { 9 | ht := New(1000) 10 | ht.Put("foo", "bar") 11 | ht.Put("fiz", "buzz") 12 | ht.Put("bruce", "wayne") 13 | ht.Put("peter", "parker") 14 | ht.Put("clark", "kent") 15 | 16 | // Test simple get 17 | val, err := ht.Get("foo") 18 | if err != nil || val != "bar" || ht.Size != 5 { 19 | fmt.Println(val, err) 20 | t.Error() 21 | } 22 | 23 | ht.Put("peter", "bob") 24 | // Test "peter" has been updated 25 | val, err = ht.Get("peter") 26 | if err != nil && val == "bob" || ht.Size != 5 { 27 | fmt.Println(val, err) 28 | t.Error() 29 | } 30 | 31 | // Test delete 32 | ht.Del("peter") 33 | val, err = ht.Get("peter") 34 | if val != "" || err == nil || ht.Size != 4 { 35 | t.Error() 36 | } 37 | 38 | counter := 0 39 | f := func(a *item) { 40 | counter++ 41 | } 42 | 43 | ht.ForEach(f) 44 | 45 | if counter != 4 { 46 | t.Error() 47 | } 48 | } 49 | 50 | func TestHash(t *testing.T) { 51 | test := "Hello World!" 52 | 53 | if hashCode(test) != 969099747 { 54 | fmt.Println(hashCode(test)) 55 | t.Error() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/heap/heap.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Item interface { 8 | Less(than Item) bool 9 | } 10 | 11 | type Heap struct { 12 | sync.Mutex 13 | data []Item 14 | min bool 15 | } 16 | 17 | func New() *Heap { 18 | return &Heap{ 19 | data: make([]Item, 0), 20 | } 21 | } 22 | 23 | func NewMin() *Heap { 24 | return &Heap{ 25 | data: make([]Item, 0), 26 | min: true, 27 | } 28 | } 29 | 30 | func NewMax() *Heap { 31 | return &Heap{ 32 | data: make([]Item, 0), 33 | min: false, 34 | } 35 | } 36 | 37 | func (h *Heap) isEmpty() bool { 38 | return len(h.data) == 0 39 | } 40 | 41 | func (h *Heap) Len() int { 42 | return len(h.data) 43 | } 44 | 45 | func (h *Heap) Get(n int) Item { 46 | return h.data[n] 47 | } 48 | 49 | func (h *Heap) Insert(n Item) { 50 | h.Lock() 51 | defer h.Unlock() 52 | 53 | h.data = append(h.data, n) 54 | h.siftUp() 55 | 56 | return 57 | } 58 | 59 | func (h *Heap) Extract() (el Item) { 60 | h.Lock() 61 | defer h.Unlock() 62 | if h.Len() == 0 { 63 | return 64 | } 65 | 66 | el = h.data[0] 67 | last := h.data[h.Len()-1] 68 | if h.Len() == 1 { 69 | h.data = nil 70 | return 71 | } 72 | 73 | h.data = append([]Item{last}, h.data[1:h.Len()-1]...) 74 | h.siftDown() 75 | 76 | return 77 | } 78 | 79 | func (h *Heap) siftUp() { 80 | for i, parent := h.Len()-1, h.Len()-1; i > 0; i = parent { 81 | parent = i >> 1 82 | if h.Less(h.Get(i), h.Get(parent)) { 83 | h.data[parent], h.data[i] = h.data[i], h.data[parent] 84 | } else { 85 | break 86 | } 87 | } 88 | } 89 | 90 | func (h *Heap) siftDown() { 91 | for i, child := 0, 1; i < h.Len() && i<<1+1 < h.Len(); i = child { 92 | child = i<<1 + 1 93 | 94 | if child+1 <= h.Len()-1 && h.Less(h.Get(child+1), h.Get(child)) { 95 | child++ 96 | } 97 | 98 | if h.Less(h.Get(i), h.Get(child)) { 99 | break 100 | } 101 | 102 | h.data[i], h.data[child] = h.data[child], h.data[i] 103 | } 104 | } 105 | 106 | func (h *Heap) Less(a, b Item) bool { 107 | if h.min { 108 | return a.Less(b) 109 | } else { 110 | return b.Less(a) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/heap/heap_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMinHeap(t *testing.T) { 9 | h := NewMin() 10 | 11 | h.Insert(Int(8)) 12 | h.Insert(Int(7)) 13 | h.Insert(Int(6)) 14 | h.Insert(Int(3)) 15 | h.Insert(Int(1)) 16 | h.Insert(Int(0)) 17 | h.Insert(Int(2)) 18 | h.Insert(Int(4)) 19 | h.Insert(Int(9)) 20 | h.Insert(Int(5)) 21 | 22 | sorted := make([]Int, 0) 23 | for h.Len() > 0 { 24 | sorted = append(sorted, h.Extract().(Int)) 25 | } 26 | 27 | for i := 0; i < len(sorted)-2; i++ { 28 | if sorted[i] > sorted[i+1] { 29 | fmt.Println(sorted) 30 | t.Error() 31 | } 32 | } 33 | } 34 | 35 | func TestMaxHeap(t *testing.T) { 36 | h := NewMax() 37 | 38 | h.Insert(Int(8)) 39 | h.Insert(Int(7)) 40 | h.Insert(Int(6)) 41 | h.Insert(Int(3)) 42 | h.Insert(Int(1)) 43 | h.Insert(Int(0)) 44 | h.Insert(Int(2)) 45 | h.Insert(Int(4)) 46 | h.Insert(Int(9)) 47 | h.Insert(Int(5)) 48 | 49 | sorted := make([]Int, 0) 50 | for h.Len() > 0 { 51 | sorted = append(sorted, h.Extract().(Int)) 52 | } 53 | 54 | for i := 0; i < len(sorted)-2; i++ { 55 | if sorted[i] < sorted[i+1] { 56 | fmt.Println(sorted) 57 | t.Error() 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/heap/util.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | type Int int 4 | 5 | func (x Int) Less(than Item) bool { 6 | return x < than.(Int) 7 | } 8 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/linked-list/linked_list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type List struct { 8 | Length int 9 | Head *Node 10 | Tail *Node 11 | } 12 | 13 | func NewList() *List { 14 | l := new(List) 15 | l.Length = 0 16 | return l 17 | } 18 | 19 | type Node struct { 20 | Value interface{} 21 | Prev *Node 22 | Next *Node 23 | } 24 | 25 | func NewNode(value interface{}) *Node { 26 | return &Node{Value: value} 27 | } 28 | 29 | func (l *List) Len() int { 30 | return l.Length 31 | } 32 | 33 | func (l *List) IsEmpty() bool { 34 | return l.Length == 0 35 | } 36 | 37 | func (l *List) Prepend(value interface{}) { 38 | node := NewNode(value) 39 | if l.Len() == 0 { 40 | l.Head = node 41 | l.Tail = l.Head 42 | } else { 43 | formerHead := l.Head 44 | formerHead.Prev = node 45 | 46 | node.Next = formerHead 47 | l.Head = node 48 | } 49 | 50 | l.Length++ 51 | } 52 | 53 | func (l *List) Append(value interface{}) { 54 | node := NewNode(value) 55 | 56 | if l.Len() == 0 { 57 | l.Head = node 58 | l.Tail = l.Head 59 | } else { 60 | formerTail := l.Tail 61 | formerTail.Next = node 62 | 63 | node.Prev = formerTail 64 | l.Tail = node 65 | } 66 | 67 | l.Length++ 68 | } 69 | 70 | func (l *List) Add(value interface{}, index int) error { 71 | if index > l.Len() { 72 | return errors.New("Index out of range") 73 | } 74 | 75 | node := NewNode(value) 76 | 77 | if l.Len() == 0 || index == 0 { 78 | l.Prepend(value) 79 | return nil 80 | } 81 | 82 | if l.Len()-1 == index { 83 | l.Append(value) 84 | return nil 85 | } 86 | 87 | nextNode, _ := l.Get(index) 88 | prevNode := nextNode.Prev 89 | 90 | prevNode.Next = node 91 | node.Prev = prevNode 92 | 93 | nextNode.Prev = node 94 | node.Next = nextNode 95 | 96 | l.Length++ 97 | 98 | return nil 99 | } 100 | 101 | func (l *List) Remove(value interface{}) error { 102 | if l.Len() == 0 { 103 | return errors.New("Empty list") 104 | } 105 | 106 | if l.Head.Value == value { 107 | l.Head = l.Head.Next 108 | l.Length-- 109 | return nil 110 | } 111 | 112 | found := 0 113 | for n := l.Head; n != nil; n = n.Next { 114 | 115 | if *n.Value.(*Node) == value && found == 0 { 116 | n.Next.Prev, n.Prev.Next = n.Prev, n.Next 117 | l.Length-- 118 | found++ 119 | } 120 | } 121 | 122 | if found == 0 { 123 | return errors.New("Node not found") 124 | } 125 | 126 | return nil 127 | } 128 | 129 | func (l *List) Get(index int) (*Node, error) { 130 | if index > l.Len() { 131 | return nil, errors.New("Index out of range") 132 | } 133 | 134 | node := l.Head 135 | for i := 0; i < index; i++ { 136 | node = node.Next 137 | } 138 | 139 | return node, nil 140 | } 141 | 142 | func (l *List) Find(node *Node) (int, error) { 143 | if l.Len() == 0 { 144 | return 0, errors.New("Empty list") 145 | } 146 | 147 | index := 0 148 | found := -1 149 | l.Map(func(n *Node) { 150 | index++ 151 | if n.Value == node.Value && found == -1 { 152 | found = index 153 | } 154 | }) 155 | 156 | if found == -1 { 157 | return 0, errors.New("Item not found") 158 | } 159 | 160 | return found, nil 161 | } 162 | 163 | func (l *List) Clear() { 164 | l.Length = 0 165 | l.Head = nil 166 | l.Tail = nil 167 | } 168 | 169 | func (l *List) Concat(k *List) { 170 | l.Tail.Next, k.Head.Prev = k.Head, l.Tail 171 | l.Tail = k.Tail 172 | l.Length += k.Length 173 | } 174 | 175 | func (list *List) Map(f func(node *Node)) { 176 | for node := list.Head; node != nil; node = node.Next { 177 | n := node.Value.(*Node) 178 | f(n) 179 | } 180 | } 181 | 182 | func (list *List) Each(f func(node Node)) { 183 | for node := list.Head; node != nil; node = node.Next { 184 | f(*node) 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/linked-list/linked_list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestLinkedList(t *testing.T) { 9 | // Test Prepend/Get 10 | l := NewList() 11 | 12 | l.Prepend(NewNode(1)) 13 | l.Prepend(NewNode(2)) 14 | l.Prepend(NewNode(3)) 15 | 16 | zero := *slice(l.Get(0))[0].(*Node).Value.(*Node) 17 | one := *slice(l.Get(1))[0].(*Node).Value.(*Node) 18 | two := *slice(l.Get(2))[0].(*Node).Value.(*Node) 19 | 20 | if zero != *NewNode(3) || 21 | one != *NewNode(2) || 22 | two != *NewNode(1) { 23 | 24 | fmt.Println(*one.Value.(*Node), *NewNode(2)) 25 | fmt.Println(zero.Value) 26 | fmt.Println(one.Value) 27 | fmt.Println(two.Value) 28 | t.Error() 29 | } 30 | 31 | // Test Append 32 | k := NewList() 33 | 34 | k.Append(NewNode(1)) 35 | k.Append(NewNode(2)) 36 | k.Append(NewNode(3)) 37 | 38 | zero = *slice(k.Get(0))[0].(*Node).Value.(*Node) 39 | one = *slice(k.Get(1))[0].(*Node).Value.(*Node) 40 | two = *slice(k.Get(2))[0].(*Node).Value.(*Node) 41 | 42 | if zero != *NewNode(1) || 43 | one != *NewNode(2) || 44 | two != *NewNode(3) { 45 | 46 | fmt.Println(zero.Value) 47 | fmt.Println(one.Value) 48 | fmt.Println(two.Value) 49 | t.Error() 50 | } 51 | 52 | // Test Add 53 | k.Add(NewNode(8), 1) 54 | 55 | zero = *slice(k.Get(0))[0].(*Node).Value.(*Node) 56 | one = *slice(k.Get(1))[0].(*Node).Value.(*Node) 57 | two = *slice(k.Get(2))[0].(*Node).Value.(*Node) 58 | 59 | if zero != *NewNode(1) || 60 | one != *NewNode(8) || 61 | two != *NewNode(2) { 62 | 63 | fmt.Println(zero.Value) 64 | fmt.Println(one.Value) 65 | fmt.Println(two.Value) 66 | 67 | t.Error() 68 | } 69 | 70 | // Test Concat 71 | l.Concat(k) 72 | if l.Len() != 7 { 73 | t.Error() 74 | } 75 | 76 | // Test Each 77 | counter := 0 78 | f := func(node *Node) { 79 | counter += node.Value.(int) 80 | } 81 | 82 | l.Map(f) 83 | if counter != 20 { 84 | t.Error() 85 | } 86 | 87 | // Test Find 88 | index, _ := l.Find(NewNode(1)) 89 | if index != 3 { 90 | fmt.Println(index) 91 | t.Error() 92 | } 93 | 94 | // Test Remove 95 | l.Remove(*NewNode(8)) 96 | 97 | counter = 0 98 | l.Map(func(n *Node) { 99 | counter += n.Value.(int) 100 | }) 101 | 102 | if counter != 12 { 103 | t.Error() 104 | } 105 | 106 | // Test Clear 107 | l.Clear() 108 | if l.Len() != 0 { 109 | t.Error() 110 | } 111 | 112 | } 113 | 114 | func slice(args ...interface{}) []interface{} { 115 | return args 116 | } 117 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/list/list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //not safe list 8 | type List struct { 9 | data []interface{} 10 | } 11 | 12 | func New(data ...interface{}) *List { 13 | l := &List{} 14 | l.Append(data...) 15 | return l 16 | } 17 | 18 | //添加一个 19 | func (l *List) Add(v interface{}) { 20 | l.data = append(l.data, v) 21 | } 22 | 23 | //附加一组 24 | func (l *List) Append(v ...interface{}) { 25 | l.data = append(l.data, v...) 26 | } 27 | 28 | //插入 29 | func (l *List) Insert(index int, o interface{}) int { 30 | 31 | if index > len(l.data) { 32 | index = len(l.data) 33 | } 34 | if index < 0 { 35 | index = 0 36 | } 37 | var R []interface{} 38 | R = append(R, l.data[index:]...) 39 | l.data = append(l.data[:index], o) 40 | l.data = append(l.data, R...) 41 | return index 42 | } 43 | 44 | //合并 45 | func (l *List) Concat(k *List) { 46 | l.data = append(l.data, k.RawList()...) 47 | } 48 | 49 | //深拷贝 50 | func (l *List) DeepCopy(k *List) { 51 | l.data = append(l.data[0:0], k.RawList()...) 52 | } 53 | 54 | //按序号移除一个节点 55 | func (l *List) Remove(index int) interface{} { 56 | if index < 0 || index >= len(l.data) { 57 | return nil 58 | } 59 | v := l.data[index] 60 | l.data = append(l.data[:index], l.data[index+1:]...) 61 | return v 62 | } 63 | 64 | type RuleFunc func(interface{}) bool 65 | 66 | //移除一个节点 67 | func (l *List) RemoveRule(rule RuleFunc) interface{} { 68 | for index := 0; index < len(l.data); index++ { 69 | v := l.data[index] 70 | if rule(v) { 71 | l.data = append(l.data[:index], l.data[index+1:]...) 72 | return v 73 | } 74 | } 75 | return nil 76 | } 77 | 78 | //移除所有符合条件节点 79 | func (l *List) RemoveAllRule(rule RuleFunc) int { 80 | var i, c int 81 | le := len(l.data) 82 | for { 83 | if i+c >= le { 84 | break 85 | } 86 | v := l.data[i] 87 | if rule(v) { 88 | l.data = append(l.data[:i], l.data[i+1:]...) 89 | c++ 90 | } else { 91 | i++ 92 | } 93 | } 94 | 95 | return c 96 | } 97 | 98 | //所有节点执行f函数 99 | func (l *List) Each(f func(o interface{})) { 100 | for _, v := range l.data { 101 | f(v) 102 | } 103 | } 104 | 105 | //按规则查找一个 106 | func (l *List) Find(rule RuleFunc) interface{} { 107 | for _, v := range l.data { 108 | if rule(v) { 109 | return v 110 | } 111 | } 112 | return nil 113 | } 114 | 115 | //按规则查找所有 116 | func (l *List) FindAll(rule RuleFunc) []interface{} { 117 | var tempL []interface{} 118 | for _, v := range l.data { 119 | if rule(v) { 120 | tempL = append(tempL, v) 121 | } 122 | } 123 | return tempL 124 | } 125 | 126 | //原始列表 127 | func (l *List) RawList() []interface{} { 128 | return l.data 129 | } 130 | 131 | //清理 132 | func (l *List) Clear() { 133 | l.data = nil 134 | } 135 | 136 | func (l *List) String() string { 137 | return fmt.Sprintf("%v", l.data) 138 | } 139 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/list/list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestList(t *testing.T) { 9 | l := New(1, 2, 3, 4, 5) 10 | l.Add(6) 11 | l.Append(7, 8) 12 | l2 := New(9, 10) 13 | l.Concat(l2) 14 | fmt.Println(l) 15 | fmt.Println(l.Find(func(o interface{}) bool { 16 | return o.(int) == 7 17 | })) 18 | l.Add(7) 19 | fmt.Println(l.FindAll(func(o interface{}) bool { 20 | return o.(int) == 7 21 | })) 22 | fmt.Println(l.RemoveRule(func(o interface{}) bool { 23 | return o.(int) == 7 24 | })) 25 | fmt.Println(l) 26 | l.Insert(5, 99) 27 | fmt.Println(l) 28 | 29 | fmt.Println("remove:", l.Remove(5), l) 30 | fmt.Println(l.RemoveRule(func(o interface{}) bool { 31 | return o.(int) == 7 32 | })) 33 | fmt.Println("rule:", l) 34 | l.Insert(0, 99) 35 | l.Insert(5, 99) 36 | l.Insert(5, 99) 37 | l.Insert(999, 99) 38 | fmt.Println(l) 39 | fmt.Println(l.RemoveAllRule(func(o interface{}) bool { 40 | return o.(int) == 99 41 | })) 42 | fmt.Println("ruleall:", l) 43 | l.Each(func(o interface{}) { 44 | fmt.Println(o.(int) * 2) 45 | }) 46 | fmt.Println(l) 47 | l3 := New(88, 88, 99, 99) 48 | l.DeepCopy(l3) 49 | fmt.Println("dc", l) 50 | l.Clear() 51 | fmt.Println(l) 52 | } 53 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/matrix/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magicsea/ga_server/0f1814d5eb01d240c6fdd9261d5e8375f60eb188/src/GAServer/data-structures/matrix/README.md -------------------------------------------------------------------------------- /src/GAServer/data-structures/matrix/matrix.go: -------------------------------------------------------------------------------- 1 | // Package Matrix provides some methods to use with Matrix 2 | package matrix 3 | 4 | import ( 5 | "errors" 6 | ) 7 | 8 | //type Matrix interface { 9 | //CountRows() int 10 | //CountCols() int 11 | //GetElm(i int, j int) float64 12 | //trace() float64 13 | 14 | //SetElm(i int, j int, v float64) 15 | //add(*Matrix) error 16 | //substract(*Matrix) error 17 | //scale(float64) 18 | 19 | //copy() []float64 20 | //diagonalCopy() []float64 21 | //} 22 | 23 | type Matrix struct { 24 | // Number of rows 25 | rows int 26 | // Number of columns 27 | cols int 28 | // Matrix stored as a flat array: Aij = Elements[i*step + j] 29 | Elements []float64 30 | // Offset between rows 31 | step int 32 | } 33 | 34 | func MakeMatrix(Elements []float64, rows, cols int) *Matrix { 35 | A := new(Matrix) 36 | A.rows = rows 37 | A.cols = cols 38 | A.step = cols 39 | A.Elements = Elements 40 | 41 | return A 42 | } 43 | func (A *Matrix) CountRows() int { 44 | return A.rows 45 | } 46 | 47 | func (A *Matrix) CountCols() int { 48 | return A.cols 49 | } 50 | 51 | func (A *Matrix) GetElm(i int, j int) float64 { 52 | return A.Elements[i*A.step+j] 53 | } 54 | 55 | func (A *Matrix) SetElm(i int, j int, v float64) { 56 | A.Elements[i*A.step+j] = v 57 | } 58 | 59 | func (A *Matrix) diagonalCopy() []float64 { 60 | diag := make([]float64, A.cols) 61 | for i := 0; i < len(diag); i++ { 62 | diag[i] = A.GetElm(i, i) 63 | } 64 | return diag 65 | } 66 | 67 | func (A *Matrix) copy() *Matrix { 68 | B := new(Matrix) 69 | B.rows = A.rows 70 | B.cols = A.cols 71 | B.step = A.step 72 | 73 | B.Elements = make([]float64, A.cols*A.rows) 74 | 75 | for i := 0; i < A.rows; i++ { 76 | for j := 0; j < A.cols; j++ { 77 | B.Elements[i*A.step+j] = A.GetElm(i, j) 78 | } 79 | } 80 | return B 81 | } 82 | 83 | func (A *Matrix) trace() float64 { 84 | var tr float64 = 0 85 | for i := 0; i < A.cols; i++ { 86 | tr += A.GetElm(i, i) 87 | } 88 | return tr 89 | } 90 | 91 | func (A *Matrix) add(B *Matrix) error { 92 | if A.cols != B.cols && A.rows != B.rows { 93 | return errors.New("Wrong input sizes") 94 | } 95 | for i := 0; i < A.rows; i++ { 96 | for j := 0; j < A.cols; j++ { 97 | A.SetElm(i, j, A.GetElm(i, j)+B.GetElm(i, j)) 98 | } 99 | } 100 | 101 | return nil 102 | } 103 | 104 | func (A *Matrix) substract(B *Matrix) error { 105 | if A.cols != B.cols && A.rows != B.rows { 106 | return errors.New("Wrong input sizes") 107 | } 108 | for i := 0; i < A.rows; i++ { 109 | for j := 0; j < A.cols; j++ { 110 | A.SetElm(i, j, A.GetElm(i, j)-B.GetElm(i, j)) 111 | } 112 | } 113 | 114 | return nil 115 | } 116 | 117 | func (A *Matrix) scale(a float64) { 118 | for i := 0; i < A.rows; i++ { 119 | for j := 0; j < A.cols; j++ { 120 | A.SetElm(i, j, a*A.GetElm(i, j)) 121 | } 122 | } 123 | } 124 | 125 | func Add(A *Matrix, B *Matrix) *Matrix { 126 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 127 | 128 | for i := 0; i < A.rows; i++ { 129 | for j := 0; j < A.cols; j++ { 130 | result.SetElm(i, j, A.GetElm(i, j)+B.GetElm(i, j)) 131 | } 132 | } 133 | 134 | return result 135 | } 136 | 137 | func Substract(A *Matrix, B *Matrix) *Matrix { 138 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 139 | 140 | for i := 0; i < A.rows; i++ { 141 | for j := 0; j < A.cols; j++ { 142 | result.SetElm(i, j, A.GetElm(i, j)-B.GetElm(i, j)) 143 | } 144 | } 145 | 146 | return result 147 | } 148 | 149 | func Multiply(A *Matrix, B *Matrix) *Matrix { 150 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 151 | 152 | for i := 0; i < A.rows; i++ { 153 | for j := 0; j < A.cols; j++ { 154 | sum := float64(0) 155 | for k := 0; k < A.cols; k++ { 156 | sum += A.GetElm(i, k) * B.GetElm(k, j) 157 | } 158 | result.SetElm(i, j, sum) 159 | } 160 | } 161 | 162 | return result 163 | } 164 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/matrix/matrix_test.go: -------------------------------------------------------------------------------- 1 | package matrix 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMakeMatrix(t *testing.T) { 8 | a := []float64{1, 2, 3, 4, 5, 6} 9 | A := MakeMatrix(a, 3, 2) 10 | 11 | if A.cols != 2 || 12 | A.rows != 3 || 13 | !FloatArrayEquals(A.Elements, a) { 14 | t.Error() 15 | } 16 | } 17 | 18 | func TestCount(t *testing.T) { 19 | a := []float64{1, 2, 3, 4, 5, 6} 20 | A := MakeMatrix(a, 3, 2) 21 | 22 | if A.CountRows() != 3 { 23 | t.Error() 24 | } 25 | if A.CountCols() != 2 { 26 | t.Error() 27 | } 28 | } 29 | 30 | func TestGetElm(t *testing.T) { 31 | a := []float64{1, 2, 3, 4, 5, 6} 32 | A := MakeMatrix(a, 3, 2) 33 | 34 | for i := 0; i < 3; i++ { 35 | if A.GetElm(0, i) != float64(i+1) { 36 | t.Error() 37 | } 38 | } 39 | } 40 | 41 | func TestSetElm(t *testing.T) { 42 | a := []float64{1, 2, 3, 4, 5, 6} 43 | A := MakeMatrix(a, 3, 2) 44 | 45 | A.SetElm(0, 0, 10) 46 | 47 | if A.GetElm(0, 0) != 10 { 48 | t.Error() 49 | } 50 | } 51 | 52 | func TestTrace(t *testing.T) { 53 | a := []float64{1, 2, 3, 4} 54 | A := MakeMatrix(a, 2, 2) 55 | 56 | if A.trace() != 5 { 57 | t.Error() 58 | } 59 | } 60 | 61 | func TestAdd(t *testing.T) { 62 | a := []float64{1, 1, 1, 1} 63 | A := MakeMatrix(a, 2, 2) 64 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 65 | 66 | A.add(A) 67 | if !FloatArrayEquals(A.Elements, B.Elements) { 68 | t.Error() 69 | } 70 | } 71 | 72 | func TestSubstract(t *testing.T) { 73 | a := []float64{1, 1, 1, 1} 74 | A := MakeMatrix(a, 2, 2) 75 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 76 | 77 | B.substract(A) 78 | if !FloatArrayEquals(A.Elements, B.Elements) { 79 | t.Error() 80 | } 81 | } 82 | 83 | func TestScale(t *testing.T) { 84 | a := []float64{1, 1, 1, 1} 85 | A := MakeMatrix(a, 2, 2) 86 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 87 | 88 | A.scale(2) 89 | 90 | if !FloatArrayEquals(A.Elements, B.Elements) { 91 | t.Error() 92 | } 93 | } 94 | 95 | func FloatArrayEquals(a []float64, b []float64) bool { 96 | if len(a) != len(b) { 97 | return false 98 | } 99 | for i, v := range a { 100 | if v != b[i] { 101 | return false 102 | } 103 | } 104 | return true 105 | } 106 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/priority-queue/priority_queue.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "GAServer/data-structures/heap" 5 | "GAServer/data-structures/queue" 6 | ) 7 | 8 | type Item struct { 9 | Value interface{} 10 | Priority int 11 | } 12 | 13 | func NewItem(value interface{}, priority int) (i *Item) { 14 | return &Item{ 15 | Value: value, 16 | Priority: priority, 17 | } 18 | } 19 | 20 | func (x Item) Less(than heap.Item) bool { 21 | return x.Priority < than.(Item).Priority 22 | } 23 | 24 | type PQ struct { 25 | data heap.Heap 26 | } 27 | 28 | func NewMax() (q *PQ) { 29 | return &PQ{ 30 | data: *heap.NewMax(), 31 | } 32 | } 33 | 34 | func NewMin() (q *PQ) { 35 | return &PQ{ 36 | data: *heap.NewMin(), 37 | } 38 | } 39 | 40 | func (pq *PQ) Len() int { 41 | return pq.data.Len() 42 | } 43 | 44 | func (pq *PQ) Insert(el Item) { 45 | pq.data.Insert(heap.Item(el)) 46 | } 47 | 48 | func (pq *PQ) Extract() (el Item) { 49 | return pq.data.Extract().(Item) 50 | } 51 | 52 | func (pq *PQ) ChangePriority(val interface{}, priority int) { 53 | var storage = queue.New() 54 | 55 | popped := pq.Extract() 56 | 57 | for val != popped.Value { 58 | if pq.Len() == 0 { 59 | panic("Item not found") 60 | } 61 | 62 | storage.Push(popped) 63 | popped = pq.Extract() 64 | } 65 | 66 | popped.Priority = priority 67 | pq.data.Insert(popped) 68 | 69 | for storage.Len() > 0 { 70 | pq.data.Insert(storage.Shift().(heap.Item)) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/priority-queue/priority_queue_test.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMaxPriorityQueue(t *testing.T) { 9 | h := NewMax() 10 | 11 | h.Insert(*NewItem(8, 10)) 12 | h.Insert(*NewItem(7, 11)) 13 | h.Insert(*NewItem(6, 12)) 14 | h.Insert(*NewItem(3, 13)) 15 | h.Insert(*NewItem(1, 14)) 16 | h.Insert(*NewItem(0, 15)) 17 | h.Insert(*NewItem(2, 16)) 18 | h.Insert(*NewItem(4, 17)) 19 | h.Insert(*NewItem(9, 18)) 20 | h.Insert(*NewItem(5, 19)) 21 | 22 | sorted := make([]Item, 0) 23 | for h.Len() > 0 { 24 | sorted = append(sorted, h.Extract()) 25 | } 26 | 27 | for i := 0; i < len(sorted)-2; i++ { 28 | if sorted[i].Priority < sorted[i+1].Priority { 29 | fmt.Println(sorted) 30 | t.Error() 31 | } 32 | } 33 | } 34 | 35 | func TestMinPriorityQueue(t *testing.T) { 36 | h := NewMin() 37 | 38 | h.Insert(*NewItem(8, 10)) 39 | h.Insert(*NewItem(7, 11)) 40 | h.Insert(*NewItem(6, 12)) 41 | h.Insert(*NewItem(3, 13)) 42 | h.Insert(*NewItem(1, 14)) 43 | h.Insert(*NewItem(0, 15)) 44 | h.Insert(*NewItem(2, 16)) 45 | h.Insert(*NewItem(4, 17)) 46 | h.Insert(*NewItem(9, 18)) 47 | h.Insert(*NewItem(5, 19)) 48 | 49 | sorted := make([]Item, 0) 50 | for h.Len() > 0 { 51 | sorted = append(sorted, h.Extract()) 52 | } 53 | 54 | for i := 0; i < len(sorted)-2; i++ { 55 | if sorted[i].Priority > sorted[i+1].Priority { 56 | fmt.Println(sorted) 57 | t.Error() 58 | } 59 | } 60 | } 61 | 62 | func TestChangePriority(t *testing.T) { 63 | h := NewMax() 64 | 65 | h.Insert(*NewItem(8, 10)) 66 | h.Insert(*NewItem(7, 11)) 67 | h.Insert(*NewItem(6, 12)) 68 | h.Insert(*NewItem(3, 13)) 69 | h.Insert(*NewItem(1, 14)) 70 | h.Insert(*NewItem(0, 15)) 71 | h.Insert(*NewItem(2, 16)) 72 | h.Insert(*NewItem(4, 17)) 73 | h.Insert(*NewItem(9, 18)) 74 | h.Insert(*NewItem(5, 19)) 75 | 76 | h.ChangePriority(8, 66) 77 | popped := h.Extract() 78 | 79 | if popped.Value != 8 { 80 | t.Error() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/queue/queue.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import "sync" 4 | 5 | type Queue struct { 6 | queue []interface{} 7 | len int 8 | lock *sync.Mutex 9 | } 10 | 11 | func New() *Queue { 12 | queue := &Queue{} 13 | queue.queue = make([]interface{}, 0) 14 | queue.len = 0 15 | queue.lock = new(sync.Mutex) 16 | 17 | return queue 18 | } 19 | 20 | func (q *Queue) Len() int { 21 | //q.lock.Lock() 22 | //defer q.lock.Unlock() 23 | 24 | return q.len 25 | } 26 | 27 | func (q *Queue) isEmpty() bool { 28 | q.lock.Lock() 29 | defer q.lock.Unlock() 30 | 31 | return q.len == 0 32 | } 33 | 34 | func (q *Queue) Pop() (el interface{}) { 35 | //q.lock.Lock() 36 | //defer q.lock.Unlock() 37 | 38 | el, q.queue = q.queue[0], q.queue[1:] 39 | q.len-- 40 | return 41 | } 42 | 43 | type RuleFunc func(interface{}) bool 44 | 45 | func (q *Queue) PopRule(rule RuleFunc) (el interface{}) { 46 | //q.lock.Lock() 47 | //defer q.lock.Unlock() 48 | for index := 0; index < q.len; index++ { 49 | if rule(q.queue[index]) { 50 | el = q.queue[index] 51 | q.queue = append(q.queue[:index], q.queue[index+1:]...) 52 | q.len-- 53 | break 54 | } 55 | } 56 | 57 | return 58 | } 59 | 60 | func (q *Queue) Push(el interface{}) { 61 | //q.lock.Lock() 62 | //defer q.lock.Unlock() 63 | 64 | q.queue = append(q.queue, el) 65 | q.len++ 66 | 67 | return 68 | } 69 | 70 | func (q *Queue) Peek() interface{} { 71 | q.lock.Lock() 72 | defer q.lock.Unlock() 73 | 74 | return q.queue[0] 75 | } 76 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/queue/queue_test.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | q := New() 10 | 11 | if !q.isEmpty() || 12 | q.len != 0 || 13 | q.Len() != 0 { 14 | t.Error() 15 | } 16 | 17 | q.Push(1) 18 | q.Push(2) 19 | q.Push(3) 20 | 21 | if q.queue[0] != 1 || 22 | q.queue[1] != 2 || 23 | q.queue[2] != 3 { 24 | fmt.Println(q.queue) 25 | t.Error() 26 | } 27 | 28 | if q.Len() != 3 { 29 | t.Error() 30 | } 31 | 32 | a := q.Pop() 33 | 34 | if a != 1 || q.Len() != 2 { 35 | t.Error() 36 | } 37 | 38 | b := q.Peek() 39 | 40 | if b != 2 { 41 | t.Error() 42 | } 43 | 44 | q2 := New() 45 | q2.Push(0) 46 | q2.Push(1) 47 | q2.Push(2) 48 | q2.Push(3) 49 | 50 | f := func(o interface{}) bool { 51 | return o.(int) == 3 52 | } 53 | q2.PopRule(f) 54 | fmt.Println(q2.queue) 55 | } 56 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "sync" 4 | 5 | type Stack struct { 6 | stack []interface{} 7 | len int 8 | lock sync.Mutex 9 | } 10 | 11 | func New() *Stack { 12 | s := &Stack{} 13 | s.stack = make([]interface{}, 0) 14 | s.len = 0 15 | 16 | return s 17 | } 18 | 19 | func (s *Stack) Len() int { 20 | s.lock.Lock() 21 | defer s.lock.Unlock() 22 | 23 | return s.len 24 | } 25 | 26 | func (s *Stack) isEmpty() bool { 27 | s.lock.Lock() 28 | defer s.lock.Unlock() 29 | 30 | return s.len == 0 31 | } 32 | 33 | func (s *Stack) Pop() (el interface{}) { 34 | s.lock.Lock() 35 | defer s.lock.Unlock() 36 | 37 | el, s.stack = s.stack[0], s.stack[1:] 38 | s.len-- 39 | return 40 | } 41 | 42 | func (s *Stack) Push(el interface{}) { 43 | s.lock.Lock() 44 | defer s.lock.Unlock() 45 | 46 | prepend := make([]interface{}, 1) 47 | prepend[0] = el 48 | s.stack = append(prepend, s.stack...) 49 | s.len++ 50 | } 51 | 52 | func (s *Stack) Peek() interface{} { 53 | s.lock.Lock() 54 | defer s.lock.Unlock() 55 | 56 | return s.stack[0] 57 | } 58 | -------------------------------------------------------------------------------- /src/GAServer/data-structures/stack/stack_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | s := New() 10 | 11 | if !s.isEmpty() || 12 | s.len != 0 || 13 | s.Len() != 0 { 14 | t.Error() 15 | } 16 | 17 | s.Push(1) 18 | s.Push(2) 19 | s.Push(3) 20 | 21 | if s.stack[0] != 3 || 22 | s.stack[1] != 2 || 23 | s.stack[2] != 1 { 24 | fmt.Println(s.stack) 25 | t.Error() 26 | } 27 | 28 | if s.Len() != 3 { 29 | t.Error() 30 | } 31 | 32 | a := s.Pop() 33 | 34 | if a != 3 || s.Len() != 2 { 35 | t.Error() 36 | } 37 | 38 | b := s.Peek() 39 | 40 | if b != 2 { 41 | t.Error() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/GAServer/db/dbclient.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | 5 | //"fmt" 6 | 7 | "github.com/astaxie/beego/orm" 8 | _ "github.com/go-sql-driver/mysql" 9 | ) 10 | 11 | type DBClient struct { 12 | ormDB orm.Ormer 13 | } 14 | 15 | func init() { 16 | orm.RegisterDriver("mysql", orm.DRMySQL) 17 | 18 | //orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8") 19 | } 20 | 21 | func RegDBModule(models ...interface{}) { 22 | orm.RegisterModel(models...) 23 | } 24 | 25 | //Start 注册和连接db dataSource连接信息 dbName数据库别名(不一定是数据库名) 26 | func ConnectDB(dataSource string, dbName string) (*DBClient, error) { 27 | err := orm.RegisterDataBase(dbName, "mysql", dataSource) 28 | if err != nil { 29 | return nil, err 30 | } 31 | o := orm.NewOrm() 32 | err2 := o.Using(dbName) 33 | if err2 != nil { 34 | return nil, err2 35 | } 36 | return &DBClient{o}, nil 37 | } 38 | 39 | //Insert 插入数据 40 | func (client *DBClient) Insert(obj interface{}) (int64, error) { 41 | //fmt.Println("####", client) 42 | //fmt.Println(client.ormDB, " ", obj) 43 | return client.ormDB.Insert(obj) 44 | } 45 | 46 | //Update 更新数据,cols更新列,默认所有 47 | func (client *DBClient) Update(md interface{}, cols ...string) (int64, error) { 48 | return client.ormDB.Update(md, cols...) 49 | } 50 | 51 | //InsertOrUpdate 52 | func (client *DBClient) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) { 53 | return client.ormDB.InsertOrUpdate(md, colConflitAndArgs...) 54 | } 55 | 56 | //Delete 删除数据,condCols删除条件,默认Id字段 57 | func (client *DBClient) Delete(md interface{}, condCols ...string) (int64, error) { 58 | return client.ormDB.Delete(md, condCols...) 59 | } 60 | 61 | //Read 有Cols用Cols做条件,没有,默认使用Id字段 62 | //norow没有结果 63 | func (client *DBClient) Read(md interface{}, cols ...string) (norow bool, e error) { 64 | e = client.ormDB.Read(md, cols...) 65 | norow = IsNoRow(e) 66 | return 67 | } 68 | 69 | //读取或者创建一行 70 | func (client *DBClient) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) { 71 | return client.ormDB.ReadOrCreate(md, col1, cols...) 72 | } 73 | 74 | //批量插入 75 | func (client *DBClient) InsertMulti(bulk int, mds interface{}) (int64, error) { 76 | return client.ormDB.InsertMulti(bulk, mds) 77 | } 78 | 79 | //raw1 80 | func (client *DBClient) Raw(query string, args ...interface{}) orm.RawSeter { 81 | return client.ormDB.Raw(query, args) 82 | } 83 | 84 | //报错解析 85 | func IsNoRow(e error) bool { 86 | return e == orm.ErrNoRows 87 | } 88 | 89 | //事物相关 90 | func (client *DBClient) Begin() error { 91 | return client.ormDB.Begin() 92 | } 93 | 94 | func (client *DBClient) Rollback() error { 95 | return client.ormDB.Rollback() 96 | } 97 | 98 | func (client *DBClient) Commit() error { 99 | return client.ormDB.Commit() 100 | } 101 | -------------------------------------------------------------------------------- /src/GAServer/db/dbclient_test.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "testing" 5 | 6 | "fmt" 7 | 8 | "github.com/astaxie/beego/orm" 9 | ) 10 | 11 | type User struct { 12 | Id int 13 | Name string 14 | Profile *Profile `orm:"rel(one)"` // OneToOne relation 15 | Post []*Post `orm:"reverse(many)"` // 设置一对多的反向关系 16 | } 17 | 18 | type Profile struct { 19 | Id int 20 | Age int16 21 | User *User `orm:"reverse(one)"` // 设置一对一反向关系(可选) 22 | } 23 | 24 | type Post struct { 25 | Id int 26 | Title string 27 | User *User `orm:"rel(fk)"` //设置一对多关系 28 | Tags []*Tag `orm:"rel(m2m)"` 29 | } 30 | 31 | type Tag struct { 32 | Id int 33 | Name string 34 | Posts []*Post `orm:"reverse(many)"` 35 | } 36 | 37 | //主键`orm:"pk"` 38 | //唯一`orm:"unique"` 39 | //忽略`orm:"-"` 40 | //允许空`orm:"null"` 41 | //varchar大小`orm:"size(60)" 42 | //默认`orm:"default(1)"` 43 | type Player struct { 44 | Id int `orm:"column(uid)",auto` 45 | Name string `orm:"column(username)"` 46 | Cgid int 47 | Lv int 48 | Exp int 49 | Exptime int64 50 | } 51 | 52 | func TestDB_rui_normal(t *testing.T) { 53 | orm.RegisterModel(new(Player)) 54 | //连接数据库 55 | client, err := ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/tcg_new", "default") 56 | if err != nil { 57 | t.Error(err) 58 | return 59 | } 60 | //增加记录 61 | /* 62 | sql := fmt.Sprintf("insert into player values(1, ?, 2, 3, 4, 342423423)") 63 | _, err1 := client.Raw(sql, []string{"a"}).Exec() 64 | if err1 != nil { 65 | t.Error(err1) 66 | return 67 | } 68 | for i := 2; i <= 10; i++ { 69 | sql = fmt.Sprintf("insert into player values(?, \"ufo\", 2, ?, 4, 342423423)") 70 | _, err1 = client.Raw(sql, []int{i, i + 1}).Exec() 71 | if err1 != nil { 72 | t.Error(err1) 73 | return 74 | } 75 | } 76 | */ 77 | //查询 78 | 79 | p := new(Player) 80 | sql1 := fmt.Sprintf("select * from player where uid = ?") 81 | err = client.Raw(sql1, []int{1}).QueryRow(&p) 82 | if err != nil { 83 | t.Error(err) 84 | } 85 | fmt.Printf("select uid:%d, name :%s, Cgid :%d, \nlv :%d, exp :%d, exptime:%u", p.Id, p.Name, p.Cgid, p.Lv, p.Exp, p.Exptime) 86 | fmt.Printf("\nplayer uid is 1 %v\n", p) 87 | ps := make([]Player, 6) 88 | //var Player []ps 89 | sql1 = fmt.Sprintf("select * from player where uid >= ?") 90 | num, errr := client.Raw(sql1, 5).QueryRows(&ps) 91 | if errr != nil { 92 | t.Error(errr) 93 | return 94 | } else { 95 | fmt.Printf("共查询到 %d 个玩家\n", num) 96 | for index, _ := range ps { 97 | fmt.Printf("\n第 %d 玩家信息为:%v", index+1, ps[index]) 98 | } 99 | fmt.Printf("\n") 100 | } 101 | 102 | //删除某些记录 103 | /* 104 | sql = fmt.Sprintf("delete from player WHERE uid = ?;") 105 | fmt.Println(sql) 106 | _, err3 := client.Raw(sql, []int{1}).Exec() 107 | if err3 != nil { 108 | t.Error(err3) 109 | return 110 | } 111 | */ 112 | //修改记录 113 | sqlUpdate := fmt.Sprintf("update player set lv = ?") 114 | _, err = client.Raw(sqlUpdate, []int{111}).Exec() 115 | if err != nil { 116 | t.Error(err) 117 | return 118 | } 119 | 120 | } 121 | 122 | func TestDB_ruiy(t *testing.T) { 123 | //数据库 表注册 124 | orm.RegisterModel(new(Player)) 125 | //连接数据库 126 | client, err := ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/tcg_new", "default") 127 | if err != nil { 128 | t.Error(err) 129 | return 130 | } 131 | p0 := new(Player) 132 | client.Delete(p0) 133 | //增加记录 134 | /* 135 | var p1 *Player = &Player{Id: 1, Name: "a", Cgid: 1, Lv: 2, Exp: 12, Exptime: time.Now().Unix()} 136 | var p2 *Player = &Player{Id: 2, Name: "b", Cgid: 2, Lv: 3, Exp: 13, Exptime: time.Now().Unix()} 137 | //插入数据 138 | fmt.Println(client.Insert(p1)) 139 | fmt.Println(client.Insert(p2)) 140 | players := []Player{ 141 | {Id: 3, Name: "c", Cgid: 3, Lv: 4, Exp: 14, Exptime: time.Now().Unix()}, 142 | {Id: 4, Name: "d", Cgid: 4, Lv: 5, Exp: 15, Exptime: time.Now().Unix()}, 143 | {Id: 5, Name: "e", Cgid: 5, Lv: 6, Exp: 16, Exptime: time.Now().Unix()}, 144 | } 145 | //批量插入 146 | client.InsertMulti(3, players) 147 | */ 148 | //删除记录 149 | /* 150 | p3 := new(Player) 151 | p3.Id = 4 152 | client.Delete(p3) 153 | */ 154 | 155 | //修改记录 156 | /* 157 | player1 := new(Player) 158 | player1.Id = 2 159 | player1.Name = "change name" 160 | client.Update(player1, "Name") 161 | err2 := client.Read(player1) 162 | if err2 != nil { 163 | t.Error(err2) 164 | return 165 | } 166 | fmt.Println("\n update end select is :", player1) 167 | */ 168 | //查询记录 169 | /* 170 | player := new(Player) 171 | player.Id = 1 172 | err1 := client.Read(player) 173 | if err1 != nil { 174 | t.Error(err1) 175 | return 176 | } 177 | fmt.Println("\nselect data is :", player) 178 | */ 179 | 180 | } 181 | 182 | func TestDB(t *testing.T) { 183 | orm.RegisterModel(new(Player)) 184 | client, err := ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/test", "default") 185 | if err != nil { 186 | t.Error(err) 187 | return 188 | } 189 | p := Player{Id: 6000, Name: "www", Exp: 1} 190 | client.Insert(&p) 191 | if err := client.Read(&p, "Exp"); err != nil { 192 | t.Error(err) 193 | return 194 | } 195 | p.Name = "yyyy" 196 | client.Update(&p, "Name") 197 | //client.Delete(&p, "Exp") 198 | t.Log("insert ok :", p) 199 | } 200 | 201 | func Test1(t *testing.T) { 202 | /* 203 | data := "[600003, 510000, 520000, 709999]" 204 | if len(data) > 0 { 205 | t := strings.Split(data, "[") 206 | te := strings.Split(t[1], "]") 207 | tem := strings.Split(te[0], ",") 208 | temp := map[int64]int8{} 209 | for k, v := range tem { 210 | var id int64 211 | if k == 0 { 212 | id = int64(GDataManager.String2Int32(v)) 213 | } else { 214 | id = int64(GDataManager.String2Int32(v[1:])) 215 | } 216 | temp[id] = 1 217 | } 218 | fmt.Printf("_________a___:%v\n", tem) 219 | fmt.Printf("_________b___:%v \n", temp) 220 | } 221 | */ 222 | /* 223 | fmt.Printf("now time is :%v\n", time.Now().Unix()) 224 | local := "[12354, 45006,503200]" 225 | tt := strings.Split(local, "[") 226 | te := strings.Split(tt[1], "]") 227 | tem := strings.Split(te[0], ",") 228 | fmt.Printf("data is :%v\n\n", tem) 229 | for _, v := range tem { 230 | //result, _ := strconv.Atoi(v) 231 | //fmt.Printf("test data is :%s\n", v) 232 | //fmt.Printf("test string2int :%d\n\n", result) 233 | r := []rune(v) 234 | onelocal := "" 235 | for i := 0; i < len(r); i++ { 236 | cc, _ := strconv.Atoi(string(r[i])) 237 | if cc > 0 || (cc == 0 && i > 0) { 238 | onelocal = onelocal + string(r[i]) 239 | } 240 | } 241 | ccc, _ := strconv.Atoi(onelocal) 242 | fmt.Printf("\nwang get :%d\n", ccc) 243 | } 244 | */ 245 | 246 | } 247 | 248 | /* 249 | func main() { 250 | o := orm.NewOrm() 251 | o.Using("default") // 默认使用 default,你可以指定为其他数据库 252 | 253 | profile := new(Profile) 254 | profile.Age = 30 255 | 256 | user := new(User) 257 | user.Profile = profile 258 | user.Name = "slene" 259 | 260 | fmt.Println(o.Insert(profile)) 261 | fmt.Println(o.Insert(user)) 262 | 263 | } 264 | */ 265 | -------------------------------------------------------------------------------- /src/GAServer/example/messages/build.bat: -------------------------------------------------------------------------------- 1 | protoc -I=. -I=%GOPATH%\src --gogoslick_out=plugins=grpc:. protos.proto 2 | -------------------------------------------------------------------------------- /src/GAServer/example/messages/protos.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package messages; 3 | import "github.com/AsynkronIT/protoactor-go/actor/protos.proto"; 4 | 5 | message Connect { 6 | actor.PID Sender = 1; 7 | } 8 | 9 | message Connected { 10 | string Message = 1; 11 | } 12 | 13 | message SayRequest { 14 | string UserName = 1; 15 | string Message = 2; 16 | } 17 | 18 | message SayResponse { 19 | string UserName = 1; 20 | string Message = 2; 21 | } 22 | 23 | message NickRequest { 24 | string OldUserName = 1; 25 | string NewUserName = 2; 26 | } 27 | 28 | message NickResponse { 29 | string OldUserName = 1; 30 | string NewUserName = 2; 31 | } -------------------------------------------------------------------------------- /src/GAServer/example/service/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "GAServer/example/messages" 5 | . "GAServer/service" 6 | "fmt" 7 | 8 | "github.com/AsynkronIT/goconsole" 9 | "github.com/AsynkronIT/protoactor-go/actor" 10 | ) 11 | 12 | type MyServer struct { 13 | BaseServer 14 | } 15 | 16 | func (s *MyServer) OnReceive(context actor.Context) { 17 | switch msg := context.Message().(type) { 18 | case *messages.SayRequest: 19 | fmt.Println("OnREC:", msg.UserName, msg.Message) 20 | } 21 | } 22 | func (s *MyServer) OnInit() { 23 | 24 | } 25 | func (s *MyServer) OnStart() { 26 | 27 | } 28 | 29 | func main() { 30 | s := &MyServer{} 31 | s.Init("127.0.0.1:8090", "server") 32 | console.ReadLine() 33 | } 34 | -------------------------------------------------------------------------------- /src/GAServer/gateframework/agent.go: -------------------------------------------------------------------------------- 1 | package gateframework 2 | 3 | import ( 4 | "GAServer/log" 5 | "GAServer/network" 6 | "gameproto/msgs" 7 | "net" 8 | "reflect" 9 | 10 | "github.com/AsynkronIT/protoactor-go/actor" 11 | ) 12 | 13 | type Agent interface { 14 | WriteMsg(msg []byte) 15 | LocalAddr() net.Addr 16 | RemoteAddr() net.Addr 17 | Close() 18 | Destroy() 19 | UserData() interface{} 20 | SetUserData(data interface{}) 21 | SetDead() 22 | } 23 | 24 | type GFAgent struct { 25 | conn network.Conn 26 | gate *Gate 27 | agentActor *actor.PID 28 | userData interface{} 29 | dead bool 30 | } 31 | 32 | func (a *GFAgent) SetDead() { 33 | a.dead = true 34 | } 35 | 36 | func (a *GFAgent) Run() { 37 | for { 38 | data, err := a.conn.ReadMsg() 39 | //log.Info("agent.read msg:", len(data)) 40 | if err != nil { 41 | log.Debug("read message: %v", err) 42 | break 43 | } 44 | 45 | if a.gate.Processor != nil { 46 | msg, err := a.gate.Processor.Unmarshal(data) 47 | if err != nil { 48 | log.Debug("unmarshal message error: %v", err) 49 | break 50 | } 51 | err = a.gate.Processor.Route(msg, a) 52 | if err != nil { 53 | log.Debug("route message error: %v", err) 54 | break 55 | } 56 | 57 | } else { 58 | //todo:not safe 59 | a.agentActor.Tell(&msgs.ReceviceClientMsg{data}) 60 | //if err != nil { 61 | // log.Error("ReceviceClientMsg message error: %v", err) 62 | // break 63 | //} 64 | } 65 | } 66 | } 67 | 68 | func (a *GFAgent) OnClose() { 69 | //todo:not safe 70 | if a.agentActor != nil && !a.dead { 71 | a.agentActor.Tell(&msgs.ClientDisconnect{}) 72 | } 73 | 74 | } 75 | 76 | func (a *GFAgent) WriteMsg(data []byte) { 77 | err := a.conn.WriteMsg(data) 78 | if err != nil { 79 | log.Error("write message %v error: %v", reflect.TypeOf(data), err) 80 | } 81 | 82 | } 83 | 84 | func (a *GFAgent) LocalAddr() net.Addr { 85 | return a.conn.LocalAddr() 86 | } 87 | 88 | func (a *GFAgent) RemoteAddr() net.Addr { 89 | return a.conn.RemoteAddr() 90 | } 91 | 92 | func (a *GFAgent) Close() { 93 | a.conn.Close() 94 | } 95 | 96 | func (a *GFAgent) Destroy() { 97 | a.conn.Destroy() 98 | 99 | } 100 | 101 | func (a *GFAgent) UserData() interface{} { 102 | return a.userData 103 | } 104 | 105 | func (a *GFAgent) SetUserData(data interface{}) { 106 | a.userData = data 107 | } 108 | -------------------------------------------------------------------------------- /src/GAServer/gateframework/gate.go: -------------------------------------------------------------------------------- 1 | package gateframework 2 | 3 | import ( 4 | "GAServer/network" 5 | _ "net" 6 | _ "reflect" 7 | "time" 8 | 9 | "github.com/AsynkronIT/protoactor-go/actor" 10 | ) 11 | 12 | type IGateService interface { 13 | GetAgentActor(Agent) *actor.PID 14 | } 15 | 16 | type Gate struct { 17 | MaxConnNum int 18 | PendingWriteNum int 19 | MaxMsgLen uint32 20 | Processor network.Processor 21 | //AgentChanRPC *chanrpc.Server 22 | 23 | // websocket 24 | WSAddr string 25 | HTTPTimeout time.Duration 26 | CertFile string 27 | KeyFile string 28 | 29 | // tcp 30 | TCPAddr string 31 | LenMsgLen int 32 | LittleEndian bool 33 | 34 | //实例 35 | wsServer *network.WSServer 36 | tcpServer *network.TCPServer 37 | } 38 | 39 | func (gate *Gate) Run(gs IGateService) { 40 | 41 | var wsServer *network.WSServer 42 | if gate.WSAddr != "" { 43 | wsServer = new(network.WSServer) 44 | wsServer.Addr = gate.WSAddr 45 | wsServer.MaxConnNum = gate.MaxConnNum 46 | wsServer.PendingWriteNum = gate.PendingWriteNum 47 | wsServer.MaxMsgLen = gate.MaxMsgLen 48 | wsServer.HTTPTimeout = gate.HTTPTimeout 49 | wsServer.CertFile = gate.CertFile 50 | wsServer.KeyFile = gate.KeyFile 51 | wsServer.NewAgent = func(conn *network.WSConn) network.Agent { 52 | a := &GFAgent{conn: conn, gate: gate} 53 | //if gate.AgentChanRPC != nil { 54 | // gate.AgentChanRPC.Go("NewAgent", a) 55 | //} 56 | return a 57 | } 58 | } 59 | 60 | var tcpServer *network.TCPServer 61 | if gate.TCPAddr != "" { 62 | tcpServer = new(network.TCPServer) 63 | tcpServer.Addr = gate.TCPAddr 64 | tcpServer.MaxConnNum = gate.MaxConnNum 65 | tcpServer.PendingWriteNum = gate.PendingWriteNum 66 | tcpServer.LenMsgLen = gate.LenMsgLen 67 | tcpServer.MaxMsgLen = gate.MaxMsgLen 68 | tcpServer.LittleEndian = gate.LittleEndian 69 | tcpServer.NewAgent = func(conn *network.TCPConn) network.Agent { 70 | a := &GFAgent{conn: conn, gate: gate} 71 | //ab := NewAgentActor(a, pid) 72 | //gs.Pid.Tell(new(messages.NewChild)) //请求一个actor 73 | //a.agentActor = <-gs.actorchan 74 | //a.agentActor.bindAgent = a 75 | a.agentActor = gs.GetAgentActor(a) 76 | return a 77 | } 78 | } 79 | 80 | if wsServer != nil { 81 | wsServer.Start() 82 | } 83 | if tcpServer != nil { 84 | tcpServer.Start() 85 | } 86 | 87 | gate.tcpServer = tcpServer 88 | gate.wsServer = wsServer 89 | } 90 | 91 | func (gate *Gate) OnDestroy() { 92 | if gate.wsServer != nil { 93 | gate.wsServer.Close() 94 | } 95 | if gate.tcpServer != nil { 96 | gate.tcpServer.Close() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/GAServer/log/example_test.go: -------------------------------------------------------------------------------- 1 | package log_test 2 | 3 | import ( 4 | "GAServer/log" 5 | "testing" 6 | ) 7 | 8 | func TestLog(t *testing.T) { 9 | name := "Leaf" 10 | log.NewLogGroup("debug", "ss", true, 0) 11 | 12 | log.Debug("My name is %v", name) 13 | log.Info("My name is %v", name) 14 | log.Error("My name is %v", name) 15 | //log.Fatal("My name is %v", name) 16 | 17 | /* 18 | logger, err := log.New("release", "", l.LstdFlags) 19 | if err != nil { 20 | return 21 | } 22 | defer logger.Close() 23 | 24 | logger.Debug("will not print") 25 | logger.Info("My name is %v", name) 26 | */ 27 | //log.Export(logger) 28 | 29 | //log.Debug("will not print") 30 | //log.Info("My name is %v", name) 31 | } 32 | -------------------------------------------------------------------------------- /src/GAServer/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "os" 8 | "path" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | // levels 14 | const ( 15 | debugLevel = 0 16 | infoLevel = 1 17 | errorLevel = 2 18 | fatalLevel = 3 19 | ) 20 | 21 | const ( 22 | printDebugLevel = "[DEBUG] " 23 | printInfoLevel = "[INFO] " 24 | printErrorLevel = "[ERROR] " 25 | printFatalLevel = "[FATAL] " 26 | ) 27 | 28 | type Logger struct { 29 | level int 30 | baseLogger *log.Logger 31 | baseFile *os.File 32 | } 33 | 34 | func New(strLevel string, pathhead string, pathname string, flag int) (*Logger, error) { 35 | // level 36 | var level int 37 | switch strings.ToLower(strLevel) { 38 | case "debug": 39 | level = debugLevel 40 | case "info": 41 | level = infoLevel 42 | case "error": 43 | level = errorLevel 44 | case "fatal": 45 | level = fatalLevel 46 | default: 47 | return nil, errors.New("unknown level: " + strLevel) 48 | } 49 | 50 | // logger 51 | var baseLogger *log.Logger 52 | var baseFile *os.File 53 | if pathname != "" { 54 | now := time.Now() 55 | 56 | filename := fmt.Sprintf("%v%d%02d%02d.log", pathhead, 57 | now.Year(), 58 | now.Month(), 59 | now.Day()) 60 | 61 | file, err := os.OpenFile(path.Join(pathname, filename), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) //Create(path.Join(pathname, filename)) 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | baseLogger = log.New(file, "", flag) 67 | baseFile = file 68 | } else { 69 | baseLogger = log.New(os.Stdout, "", flag) 70 | } 71 | 72 | // new 73 | logger := new(Logger) 74 | logger.level = level 75 | logger.baseLogger = baseLogger 76 | logger.baseFile = baseFile 77 | 78 | return logger, nil 79 | } 80 | 81 | // It's dangerous to call the method on logging 82 | func (logger *Logger) Close() { 83 | if logger.baseFile != nil { 84 | logger.baseFile.Close() 85 | } 86 | 87 | logger.baseLogger = nil 88 | logger.baseFile = nil 89 | } 90 | 91 | func (logger *Logger) doPrintf(level int, printLevel string, format string, a ...interface{}) { 92 | if level < logger.level { 93 | return 94 | } 95 | if logger.baseLogger == nil { 96 | panic("logger closed") 97 | } 98 | 99 | format = printLevel + format 100 | logger.baseLogger.Output(4, fmt.Sprintf(format, a...)) 101 | 102 | if level == fatalLevel { 103 | os.Exit(1) 104 | } 105 | } 106 | 107 | func (logger *Logger) Debug(format string, a ...interface{}) { 108 | logger.doPrintf(debugLevel, printDebugLevel, format, a...) 109 | } 110 | 111 | func (logger *Logger) Info(format string, a ...interface{}) { 112 | logger.doPrintf(infoLevel, printInfoLevel, format, a...) 113 | } 114 | 115 | func (logger *Logger) Error(format string, a ...interface{}) { 116 | logger.doPrintf(errorLevel, printErrorLevel, format, a...) 117 | } 118 | 119 | func (logger *Logger) Fatal(format string, a ...interface{}) { 120 | logger.doPrintf(fatalLevel, printFatalLevel, format, a...) 121 | } 122 | 123 | /* 124 | var gLogger, _ = New("debug", "", "", log.LstdFlags) 125 | 126 | // It's dangerous to call the method on logging 127 | func Export(logger *Logger) { 128 | if logger != nil { 129 | gLogger = logger 130 | } 131 | } 132 | 133 | 134 | func Debug(format string, a ...interface{}) { 135 | gLogger.doPrintf(debugLevel, printDebugLevel, format, a...) 136 | } 137 | 138 | func Info(format string, a ...interface{}) { 139 | gLogger.doPrintf(infoLevel, printInfoLevel, format, a...) 140 | } 141 | 142 | func Println(format string, a ...interface{}) { 143 | str := fmt.Sprint(a) 144 | gLogger.doPrintf(infoLevel, printInfoLevel, format+str) 145 | 146 | } 147 | 148 | func Error(format string, a ...interface{}) { 149 | gLogger.doPrintf(errorLevel, printErrorLevel, format, a...) 150 | } 151 | 152 | func Fatal(format string, a ...interface{}) { 153 | gLogger.doPrintf(fatalLevel, printFatalLevel, format, a...) 154 | } 155 | 156 | func Close() { 157 | gLogger.Close() 158 | } 159 | */ 160 | -------------------------------------------------------------------------------- /src/GAServer/log/loggroup.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import "log" 4 | 5 | type LogGroup struct { 6 | loggers []*Logger 7 | } 8 | 9 | var gGroup *LogGroup 10 | 11 | //var gLogger *Logger 12 | 13 | func init() { 14 | gLogger, _ := New("debug", "", "", log.LstdFlags) 15 | gGroup = new(LogGroup) 16 | gGroup.loggers = append(gGroup.loggers, gLogger) 17 | } 18 | func NewLogGroup(strLevel string, pathname string, isStdout bool, flag int) error { 19 | 20 | if pathname != "" { 21 | debug, err := New("debug", "debug_", pathname, flag) 22 | if err != nil { 23 | return err 24 | } 25 | info, err := New("info", "info_", pathname, flag) 26 | if err != nil { 27 | return err 28 | } 29 | erro, err := New("error", "error_", pathname, flag) 30 | if err != nil { 31 | return err 32 | } 33 | fatal, err := New("fatal", "fatal_", pathname, flag) 34 | if err != nil { 35 | return err 36 | } 37 | gGroup = &LogGroup{[]*Logger{debug, info, erro, fatal}} 38 | } else { 39 | gGroup = &LogGroup{} 40 | } 41 | 42 | if isStdout { 43 | gLogger, _ := New(strLevel, "", "", log.LstdFlags) 44 | gGroup.loggers = append(gGroup.loggers, gLogger) 45 | } 46 | return nil 47 | } 48 | 49 | func Debug(format string, a ...interface{}) { 50 | for _, v := range gGroup.loggers { 51 | v.Debug(format, a...) 52 | } 53 | } 54 | 55 | func Info(format string, a ...interface{}) { 56 | for _, v := range gGroup.loggers { 57 | v.Info(format, a...) 58 | } 59 | } 60 | 61 | func Println(format string, a ...interface{}) { 62 | //str := fmt.Sprint(a) 63 | for _, v := range gGroup.loggers { 64 | v.Info(format, a...) 65 | } 66 | 67 | } 68 | 69 | func Error(format string, a ...interface{}) { 70 | //fmt.Println("Error ", len(gGroup.loggers), gGroup.loggers) 71 | for _, v := range gGroup.loggers { 72 | v.Error(format, a...) 73 | } 74 | } 75 | 76 | func Fatal(format string, a ...interface{}) { 77 | for _, v := range gGroup.loggers { 78 | v.Fatal(format, a...) 79 | } 80 | } 81 | 82 | func Close() { 83 | for _, v := range gGroup.loggers { 84 | v.Close() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/GAServer/module/module.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | type IModule interface { 4 | OnInit() bool 5 | OnDestroy() 6 | Run() 7 | } 8 | -------------------------------------------------------------------------------- /src/GAServer/network/agent.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type Agent interface { 4 | Run() 5 | OnClose() 6 | } 7 | -------------------------------------------------------------------------------- /src/GAServer/network/conn.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | type Conn interface { 8 | ReadMsg() ([]byte, error) 9 | WriteMsg(args ...[]byte) error 10 | LocalAddr() net.Addr 11 | RemoteAddr() net.Addr 12 | Close() 13 | Destroy() 14 | } 15 | -------------------------------------------------------------------------------- /src/GAServer/network/processor.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type Processor interface { 4 | // must goroutine safe 5 | Route(msg interface{}, userData interface{}) error 6 | // must goroutine safe 7 | Unmarshal(data []byte) (interface{}, error) 8 | // must goroutine safe 9 | Marshal(msg interface{}) ([][]byte, error) 10 | } 11 | -------------------------------------------------------------------------------- /src/GAServer/network/tcp_client.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "sync" 7 | "time" 8 | 9 | "GAServer/log" 10 | ) 11 | 12 | type TCPClient struct { 13 | sync.Mutex 14 | Addr string 15 | ConnNum int 16 | ConnectInterval time.Duration 17 | PendingWriteNum int 18 | AutoReconnect bool 19 | NewAgent func(*TCPConn) Agent 20 | conns ConnSet 21 | wg sync.WaitGroup 22 | closeFlag bool 23 | 24 | // msg parser 25 | LenMsgLen int 26 | MinMsgLen uint32 27 | MaxMsgLen uint32 28 | LittleEndian bool 29 | msgParser *MsgParser 30 | } 31 | 32 | func (client *TCPClient) Start() { 33 | fmt.Println("TCPClient init... ", client.ConnNum) 34 | client.init() 35 | fmt.Println("will conn ", client.ConnNum) 36 | for i := 0; i < client.ConnNum; i++ { 37 | client.wg.Add(1) 38 | go client.connect() 39 | } 40 | } 41 | 42 | func (client *TCPClient) init() { 43 | client.Lock() 44 | defer client.Unlock() 45 | 46 | if client.ConnNum <= 0 { 47 | client.ConnNum = 1 48 | log.Info("invalid ConnNum, reset to %v", client.ConnNum) 49 | } 50 | if client.ConnectInterval <= 0 { 51 | client.ConnectInterval = 3 * time.Second 52 | log.Info("invalid ConnectInterval, reset to %v", client.ConnectInterval) 53 | } 54 | if client.PendingWriteNum <= 0 { 55 | client.PendingWriteNum = 100 56 | log.Info("invalid PendingWriteNum, reset to %v", client.PendingWriteNum) 57 | } 58 | if client.NewAgent == nil { 59 | log.Fatal("NewAgent must not be nil") 60 | } 61 | if client.conns != nil { 62 | log.Fatal("client is running") 63 | } 64 | 65 | client.conns = make(ConnSet) 66 | client.closeFlag = false 67 | 68 | // msg parser 69 | msgParser := NewMsgParser() 70 | msgParser.SetMsgLen(client.LenMsgLen, client.MinMsgLen, client.MaxMsgLen) 71 | msgParser.SetByteOrder(client.LittleEndian) 72 | client.msgParser = msgParser 73 | } 74 | 75 | func (client *TCPClient) dial() net.Conn { 76 | for { 77 | conn, err := net.Dial("tcp", client.Addr) 78 | if err == nil || client.closeFlag { 79 | return conn 80 | } 81 | 82 | log.Info("connect to %v error: %v", client.Addr, err) 83 | time.Sleep(client.ConnectInterval) 84 | continue 85 | } 86 | } 87 | 88 | func (client *TCPClient) connect() { 89 | defer client.wg.Done() 90 | fmt.Println("tcp connect...") 91 | reconnect: 92 | conn := client.dial() 93 | if conn == nil { 94 | fmt.Println("tcp dial fail") 95 | return 96 | } 97 | 98 | client.Lock() 99 | if client.closeFlag { 100 | client.Unlock() 101 | conn.Close() 102 | fmt.Println("tcp will close") 103 | return 104 | } 105 | client.conns[conn] = struct{}{} 106 | client.Unlock() 107 | fmt.Println("tcp connected") 108 | tcpConn := newTCPConn(conn, client.PendingWriteNum, client.msgParser) 109 | agent := client.NewAgent(tcpConn) 110 | agent.Run() 111 | 112 | // cleanup 113 | tcpConn.Close() 114 | client.Lock() 115 | delete(client.conns, conn) 116 | client.Unlock() 117 | agent.OnClose() 118 | 119 | if client.AutoReconnect { 120 | time.Sleep(client.ConnectInterval) 121 | goto reconnect 122 | } 123 | } 124 | 125 | func (client *TCPClient) Close() { 126 | client.Lock() 127 | client.closeFlag = true 128 | for conn := range client.conns { 129 | conn.Close() 130 | } 131 | client.conns = nil 132 | client.Unlock() 133 | 134 | client.wg.Wait() 135 | } 136 | -------------------------------------------------------------------------------- /src/GAServer/network/tcp_conn.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "GAServer/log" 5 | "net" 6 | "sync" 7 | ) 8 | 9 | type ConnSet map[net.Conn]struct{} 10 | 11 | type TCPConn struct { 12 | sync.Mutex 13 | conn net.Conn 14 | writeChan chan []byte 15 | closeFlag bool 16 | msgParser *MsgParser 17 | } 18 | 19 | func newTCPConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser) *TCPConn { 20 | tcpConn := new(TCPConn) 21 | tcpConn.conn = conn 22 | tcpConn.writeChan = make(chan []byte, pendingWriteNum) 23 | tcpConn.msgParser = msgParser 24 | 25 | go func() { 26 | for b := range tcpConn.writeChan { 27 | if b == nil { 28 | break 29 | } 30 | 31 | _, err := conn.Write(b) 32 | if err != nil { 33 | break 34 | } 35 | } 36 | 37 | conn.Close() 38 | tcpConn.Lock() 39 | tcpConn.closeFlag = true 40 | tcpConn.Unlock() 41 | }() 42 | 43 | return tcpConn 44 | } 45 | 46 | func (tcpConn *TCPConn) doDestroy() { 47 | tcpConn.conn.(*net.TCPConn).SetLinger(0) 48 | tcpConn.conn.Close() 49 | 50 | if !tcpConn.closeFlag { 51 | close(tcpConn.writeChan) 52 | tcpConn.closeFlag = true 53 | } 54 | } 55 | 56 | func (tcpConn *TCPConn) Destroy() { 57 | tcpConn.Lock() 58 | defer tcpConn.Unlock() 59 | 60 | tcpConn.doDestroy() 61 | } 62 | 63 | func (tcpConn *TCPConn) Close() { 64 | tcpConn.Lock() 65 | defer tcpConn.Unlock() 66 | if tcpConn.closeFlag { 67 | return 68 | } 69 | 70 | tcpConn.doWrite(nil) 71 | tcpConn.closeFlag = true 72 | } 73 | 74 | func (tcpConn *TCPConn) doWrite(b []byte) { 75 | if len(tcpConn.writeChan) == cap(tcpConn.writeChan) { 76 | log.Debug("close conn: channel full") 77 | tcpConn.doDestroy() 78 | return 79 | } 80 | 81 | tcpConn.writeChan <- b 82 | } 83 | 84 | // b must not be modified by the others goroutines 85 | func (tcpConn *TCPConn) Write(b []byte) { 86 | tcpConn.Lock() 87 | defer tcpConn.Unlock() 88 | if tcpConn.closeFlag || b == nil { 89 | return 90 | } 91 | 92 | tcpConn.doWrite(b) 93 | } 94 | 95 | func (tcpConn *TCPConn) Read(b []byte) (int, error) { 96 | return tcpConn.conn.Read(b) 97 | } 98 | 99 | func (tcpConn *TCPConn) LocalAddr() net.Addr { 100 | return tcpConn.conn.LocalAddr() 101 | } 102 | 103 | func (tcpConn *TCPConn) RemoteAddr() net.Addr { 104 | return tcpConn.conn.RemoteAddr() 105 | } 106 | 107 | func (tcpConn *TCPConn) ReadMsg() ([]byte, error) { 108 | return tcpConn.msgParser.Read(tcpConn) 109 | } 110 | 111 | func (tcpConn *TCPConn) WriteMsg(args ...[]byte) error { 112 | return tcpConn.msgParser.Write(tcpConn, args...) 113 | } 114 | -------------------------------------------------------------------------------- /src/GAServer/network/tcp_msg.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "io" 7 | "math" 8 | ) 9 | 10 | // -------------- 11 | // | len | data | 12 | // -------------- 13 | type MsgParser struct { 14 | lenMsgLen int 15 | minMsgLen uint32 16 | maxMsgLen uint32 17 | littleEndian bool 18 | } 19 | 20 | func NewMsgParser() *MsgParser { 21 | p := new(MsgParser) 22 | p.lenMsgLen = 2 23 | p.minMsgLen = 1 24 | p.maxMsgLen = 4096 25 | p.littleEndian = false 26 | 27 | return p 28 | } 29 | 30 | // It's dangerous to call the method on reading or writing 31 | func (p *MsgParser) SetMsgLen(lenMsgLen int, minMsgLen uint32, maxMsgLen uint32) { 32 | if lenMsgLen == 1 || lenMsgLen == 2 || lenMsgLen == 4 { 33 | p.lenMsgLen = lenMsgLen 34 | } 35 | if minMsgLen != 0 { 36 | p.minMsgLen = minMsgLen 37 | } 38 | if maxMsgLen != 0 { 39 | p.maxMsgLen = maxMsgLen 40 | } 41 | 42 | var max uint32 43 | switch p.lenMsgLen { 44 | case 1: 45 | max = math.MaxUint8 46 | case 2: 47 | max = math.MaxUint16 48 | case 4: 49 | max = math.MaxUint32 50 | } 51 | if p.minMsgLen > max { 52 | p.minMsgLen = max 53 | } 54 | if p.maxMsgLen > max { 55 | p.maxMsgLen = max 56 | } 57 | } 58 | 59 | // It's dangerous to call the method on reading or writing 60 | func (p *MsgParser) SetByteOrder(littleEndian bool) { 61 | p.littleEndian = littleEndian 62 | } 63 | 64 | // goroutine safe 65 | func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) { 66 | var b [4]byte 67 | bufMsgLen := b[:p.lenMsgLen] 68 | 69 | // read len 70 | if _, err := io.ReadFull(conn, bufMsgLen); err != nil { 71 | return nil, err 72 | } 73 | 74 | // parse len 75 | var msgLen uint32 76 | switch p.lenMsgLen { 77 | case 1: 78 | msgLen = uint32(bufMsgLen[0]) 79 | case 2: 80 | if p.littleEndian { 81 | msgLen = uint32(binary.LittleEndian.Uint16(bufMsgLen)) 82 | } else { 83 | msgLen = uint32(binary.BigEndian.Uint16(bufMsgLen)) 84 | } 85 | case 4: 86 | if p.littleEndian { 87 | msgLen = binary.LittleEndian.Uint32(bufMsgLen) 88 | } else { 89 | msgLen = binary.BigEndian.Uint32(bufMsgLen) 90 | } 91 | } 92 | 93 | // check len 94 | if msgLen > p.maxMsgLen { 95 | return nil, errors.New("message too long") 96 | } else if msgLen < p.minMsgLen { 97 | return nil, errors.New("message too short") 98 | } 99 | 100 | // data 101 | msgData := make([]byte, msgLen) 102 | if _, err := io.ReadFull(conn, msgData); err != nil { 103 | return nil, err 104 | } 105 | 106 | return msgData, nil 107 | } 108 | 109 | // goroutine safe 110 | func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error { 111 | // get len 112 | var msgLen uint32 113 | for i := 0; i < len(args); i++ { 114 | msgLen += uint32(len(args[i])) 115 | } 116 | 117 | // check len 118 | if msgLen > p.maxMsgLen { 119 | return errors.New("message too long") 120 | } else if msgLen < p.minMsgLen { 121 | return errors.New("message too short") 122 | } 123 | 124 | msg := make([]byte, uint32(p.lenMsgLen)+msgLen) 125 | 126 | // write len 127 | switch p.lenMsgLen { 128 | case 1: 129 | msg[0] = byte(msgLen) 130 | case 2: 131 | if p.littleEndian { 132 | binary.LittleEndian.PutUint16(msg, uint16(msgLen)) 133 | } else { 134 | binary.BigEndian.PutUint16(msg, uint16(msgLen)) 135 | } 136 | case 4: 137 | if p.littleEndian { 138 | binary.LittleEndian.PutUint32(msg, msgLen) 139 | } else { 140 | binary.BigEndian.PutUint32(msg, msgLen) 141 | } 142 | } 143 | 144 | // write data 145 | l := p.lenMsgLen 146 | for i := 0; i < len(args); i++ { 147 | copy(msg[l:], args[i]) 148 | l += len(args[i]) 149 | } 150 | 151 | conn.Write(msg) 152 | 153 | return nil 154 | } 155 | -------------------------------------------------------------------------------- /src/GAServer/network/tcp_server.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "GAServer/log" 5 | "fmt" 6 | "net" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | type TCPServer struct { 12 | Addr string 13 | MaxConnNum int 14 | PendingWriteNum int 15 | NewAgent func(*TCPConn) Agent 16 | ln net.Listener 17 | conns ConnSet 18 | mutexConns sync.Mutex 19 | wgLn sync.WaitGroup 20 | wgConns sync.WaitGroup 21 | 22 | // msg parser 23 | LenMsgLen int 24 | MinMsgLen uint32 25 | MaxMsgLen uint32 26 | LittleEndian bool 27 | msgParser *MsgParser 28 | } 29 | 30 | func (server *TCPServer) Start() { 31 | server.init() 32 | go server.run() 33 | } 34 | 35 | func (server *TCPServer) init() { 36 | ln, err := net.Listen("tcp", server.Addr) 37 | if err != nil { 38 | log.Fatal("%v", err) 39 | } 40 | 41 | if server.MaxConnNum <= 0 { 42 | server.MaxConnNum = 100 43 | log.Info("invalid MaxConnNum, reset to %v", server.MaxConnNum) 44 | } 45 | if server.PendingWriteNum <= 0 { 46 | server.PendingWriteNum = 100 47 | log.Info("invalid PendingWriteNum, reset to %v", server.PendingWriteNum) 48 | } 49 | if server.NewAgent == nil { 50 | log.Fatal("NewAgent must not be nil") 51 | } 52 | 53 | server.ln = ln 54 | server.conns = make(ConnSet) 55 | 56 | // msg parser 57 | msgParser := NewMsgParser() 58 | msgParser.SetMsgLen(server.LenMsgLen, server.MinMsgLen, server.MaxMsgLen) 59 | msgParser.SetByteOrder(server.LittleEndian) 60 | server.msgParser = msgParser 61 | } 62 | 63 | func (server *TCPServer) run() { 64 | server.wgLn.Add(1) 65 | defer server.wgLn.Done() 66 | 67 | var tempDelay time.Duration 68 | for { 69 | conn, err := server.ln.Accept() 70 | if err != nil { 71 | if ne, ok := err.(net.Error); ok && ne.Temporary() { 72 | if tempDelay == 0 { 73 | tempDelay = 5 * time.Millisecond 74 | } else { 75 | tempDelay *= 2 76 | } 77 | if max := 1 * time.Second; tempDelay > max { 78 | tempDelay = max 79 | } 80 | log.Info("accept error: %v; retrying in %v", err, tempDelay) 81 | time.Sleep(tempDelay) 82 | continue 83 | } 84 | return 85 | } 86 | tempDelay = 0 87 | 88 | server.mutexConns.Lock() 89 | if len(server.conns) >= server.MaxConnNum { 90 | server.mutexConns.Unlock() 91 | conn.Close() 92 | log.Debug("too many connections") 93 | continue 94 | } 95 | server.conns[conn] = struct{}{} 96 | server.mutexConns.Unlock() 97 | 98 | server.wgConns.Add(1) 99 | 100 | tcpConn := newTCPConn(conn, server.PendingWriteNum, server.msgParser) 101 | fmt.Println("new conn from ", tcpConn.RemoteAddr()) 102 | agent := server.NewAgent(tcpConn) 103 | go func() { 104 | agent.Run() 105 | 106 | // cleanup 107 | tcpConn.Close() 108 | server.mutexConns.Lock() 109 | delete(server.conns, conn) 110 | server.mutexConns.Unlock() 111 | agent.OnClose() 112 | 113 | server.wgConns.Done() 114 | }() 115 | } 116 | } 117 | 118 | func (server *TCPServer) Close() { 119 | server.ln.Close() 120 | server.wgLn.Wait() 121 | 122 | server.mutexConns.Lock() 123 | for conn := range server.conns { 124 | conn.Close() 125 | } 126 | server.conns = nil 127 | server.mutexConns.Unlock() 128 | server.wgConns.Wait() 129 | } 130 | -------------------------------------------------------------------------------- /src/GAServer/network/ws_client.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "GAServer/log" 5 | "sync" 6 | "time" 7 | 8 | "github.com/gorilla/websocket" 9 | ) 10 | 11 | type WSClient struct { 12 | sync.Mutex 13 | Addr string 14 | ConnNum int 15 | ConnectInterval time.Duration 16 | PendingWriteNum int 17 | MaxMsgLen uint32 18 | HandshakeTimeout time.Duration 19 | AutoReconnect bool 20 | NewAgent func(*WSConn) Agent 21 | dialer websocket.Dialer 22 | conns WebsocketConnSet 23 | wg sync.WaitGroup 24 | closeFlag bool 25 | } 26 | 27 | func (client *WSClient) Start() { 28 | client.init() 29 | 30 | for i := 0; i < client.ConnNum; i++ { 31 | client.wg.Add(1) 32 | go client.connect() 33 | } 34 | } 35 | 36 | func (client *WSClient) init() { 37 | client.Lock() 38 | defer client.Unlock() 39 | 40 | if client.ConnNum <= 0 { 41 | client.ConnNum = 1 42 | log.Info("invalid ConnNum, reset to %v", client.ConnNum) 43 | } 44 | if client.ConnectInterval <= 0 { 45 | client.ConnectInterval = 3 * time.Second 46 | log.Info("invalid ConnectInterval, reset to %v", client.ConnectInterval) 47 | } 48 | if client.PendingWriteNum <= 0 { 49 | client.PendingWriteNum = 100 50 | log.Info("invalid PendingWriteNum, reset to %v", client.PendingWriteNum) 51 | } 52 | if client.MaxMsgLen <= 0 { 53 | client.MaxMsgLen = 4096 54 | log.Info("invalid MaxMsgLen, reset to %v", client.MaxMsgLen) 55 | } 56 | if client.HandshakeTimeout <= 0 { 57 | client.HandshakeTimeout = 10 * time.Second 58 | log.Info("invalid HandshakeTimeout, reset to %v", client.HandshakeTimeout) 59 | } 60 | if client.NewAgent == nil { 61 | log.Fatal("NewAgent must not be nil") 62 | } 63 | if client.conns != nil { 64 | log.Fatal("client is running") 65 | } 66 | 67 | client.conns = make(WebsocketConnSet) 68 | client.closeFlag = false 69 | client.dialer = websocket.Dialer{ 70 | HandshakeTimeout: client.HandshakeTimeout, 71 | } 72 | } 73 | 74 | func (client *WSClient) dial() *websocket.Conn { 75 | for { 76 | conn, _, err := client.dialer.Dial(client.Addr, nil) 77 | if err == nil || client.closeFlag { 78 | return conn 79 | } 80 | 81 | log.Info("connect to %v error: %v", client.Addr, err) 82 | time.Sleep(client.ConnectInterval) 83 | continue 84 | } 85 | } 86 | 87 | func (client *WSClient) connect() { 88 | defer client.wg.Done() 89 | 90 | reconnect: 91 | conn := client.dial() 92 | if conn == nil { 93 | return 94 | } 95 | conn.SetReadLimit(int64(client.MaxMsgLen)) 96 | 97 | client.Lock() 98 | if client.closeFlag { 99 | client.Unlock() 100 | conn.Close() 101 | return 102 | } 103 | client.conns[conn] = struct{}{} 104 | client.Unlock() 105 | 106 | wsConn := newWSConn(conn, client.PendingWriteNum, client.MaxMsgLen) 107 | agent := client.NewAgent(wsConn) 108 | agent.Run() 109 | 110 | // cleanup 111 | wsConn.Close() 112 | client.Lock() 113 | delete(client.conns, conn) 114 | client.Unlock() 115 | agent.OnClose() 116 | 117 | if client.AutoReconnect { 118 | time.Sleep(client.ConnectInterval) 119 | goto reconnect 120 | } 121 | } 122 | 123 | func (client *WSClient) Close() { 124 | client.Lock() 125 | client.closeFlag = true 126 | for conn := range client.conns { 127 | conn.Close() 128 | } 129 | client.conns = nil 130 | client.Unlock() 131 | 132 | client.wg.Wait() 133 | } 134 | -------------------------------------------------------------------------------- /src/GAServer/network/ws_conn.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "GAServer/log" 5 | "errors" 6 | "net" 7 | "sync" 8 | 9 | "github.com/gorilla/websocket" 10 | ) 11 | 12 | type WebsocketConnSet map[*websocket.Conn]struct{} 13 | 14 | type WSConn struct { 15 | sync.Mutex 16 | conn *websocket.Conn 17 | writeChan chan []byte 18 | maxMsgLen uint32 19 | closeFlag bool 20 | } 21 | 22 | func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32) *WSConn { 23 | wsConn := new(WSConn) 24 | wsConn.conn = conn 25 | wsConn.writeChan = make(chan []byte, pendingWriteNum) 26 | wsConn.maxMsgLen = maxMsgLen 27 | 28 | go func() { 29 | for b := range wsConn.writeChan { 30 | if b == nil { 31 | break 32 | } 33 | 34 | err := conn.WriteMessage(websocket.BinaryMessage, b) 35 | if err != nil { 36 | break 37 | } 38 | } 39 | 40 | conn.Close() 41 | wsConn.Lock() 42 | wsConn.closeFlag = true 43 | wsConn.Unlock() 44 | }() 45 | 46 | return wsConn 47 | } 48 | 49 | func (wsConn *WSConn) doDestroy() { 50 | wsConn.conn.UnderlyingConn().(*net.TCPConn).SetLinger(0) 51 | wsConn.conn.Close() 52 | 53 | if !wsConn.closeFlag { 54 | close(wsConn.writeChan) 55 | wsConn.closeFlag = true 56 | } 57 | } 58 | 59 | func (wsConn *WSConn) Destroy() { 60 | wsConn.Lock() 61 | defer wsConn.Unlock() 62 | 63 | wsConn.doDestroy() 64 | } 65 | 66 | func (wsConn *WSConn) Close() { 67 | wsConn.Lock() 68 | defer wsConn.Unlock() 69 | if wsConn.closeFlag { 70 | return 71 | } 72 | 73 | wsConn.doWrite(nil) 74 | wsConn.closeFlag = true 75 | } 76 | 77 | func (wsConn *WSConn) doWrite(b []byte) { 78 | if len(wsConn.writeChan) == cap(wsConn.writeChan) { 79 | log.Debug("close conn: channel full") 80 | wsConn.doDestroy() 81 | return 82 | } 83 | 84 | wsConn.writeChan <- b 85 | } 86 | 87 | func (wsConn *WSConn) LocalAddr() net.Addr { 88 | return wsConn.conn.LocalAddr() 89 | } 90 | 91 | func (wsConn *WSConn) RemoteAddr() net.Addr { 92 | return wsConn.conn.RemoteAddr() 93 | } 94 | 95 | // goroutine not safe 96 | func (wsConn *WSConn) ReadMsg() ([]byte, error) { 97 | _, b, err := wsConn.conn.ReadMessage() 98 | return b, err 99 | } 100 | 101 | // args must not be modified by the others goroutines 102 | func (wsConn *WSConn) WriteMsg(args ...[]byte) error { 103 | wsConn.Lock() 104 | defer wsConn.Unlock() 105 | if wsConn.closeFlag { 106 | return nil 107 | } 108 | 109 | // get len 110 | var msgLen uint32 111 | for i := 0; i < len(args); i++ { 112 | msgLen += uint32(len(args[i])) 113 | } 114 | 115 | // check len 116 | if msgLen > wsConn.maxMsgLen { 117 | return errors.New("message too long") 118 | } else if msgLen < 1 { 119 | return errors.New("message too short") 120 | } 121 | 122 | // don't copy 123 | if len(args) == 1 { 124 | wsConn.doWrite(args[0]) 125 | return nil 126 | } 127 | 128 | // merge the args 129 | msg := make([]byte, msgLen) 130 | l := 0 131 | for i := 0; i < len(args); i++ { 132 | copy(msg[l:], args[i]) 133 | l += len(args[i]) 134 | } 135 | 136 | wsConn.doWrite(msg) 137 | 138 | return nil 139 | } 140 | -------------------------------------------------------------------------------- /src/GAServer/network/ws_server.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "GAServer/log" 5 | "crypto/tls" 6 | "net" 7 | "net/http" 8 | "sync" 9 | "time" 10 | 11 | "github.com/gorilla/websocket" 12 | ) 13 | 14 | type WSServer struct { 15 | Addr string 16 | MaxConnNum int 17 | PendingWriteNum int 18 | MaxMsgLen uint32 19 | HTTPTimeout time.Duration 20 | CertFile string 21 | KeyFile string 22 | NewAgent func(*WSConn) Agent 23 | ln net.Listener 24 | handler *WSHandler 25 | } 26 | 27 | type WSHandler struct { 28 | maxConnNum int 29 | pendingWriteNum int 30 | maxMsgLen uint32 31 | newAgent func(*WSConn) Agent 32 | upgrader websocket.Upgrader 33 | conns WebsocketConnSet 34 | mutexConns sync.Mutex 35 | wg sync.WaitGroup 36 | } 37 | 38 | func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 39 | if r.Method != "GET" { 40 | http.Error(w, "Method not allowed", 405) 41 | return 42 | } 43 | conn, err := handler.upgrader.Upgrade(w, r, nil) 44 | if err != nil { 45 | log.Debug("upgrade error: %v", err) 46 | return 47 | } 48 | conn.SetReadLimit(int64(handler.maxMsgLen)) 49 | 50 | handler.wg.Add(1) 51 | defer handler.wg.Done() 52 | 53 | handler.mutexConns.Lock() 54 | if handler.conns == nil { 55 | handler.mutexConns.Unlock() 56 | conn.Close() 57 | return 58 | } 59 | if len(handler.conns) >= handler.maxConnNum { 60 | handler.mutexConns.Unlock() 61 | conn.Close() 62 | log.Debug("too many connections") 63 | return 64 | } 65 | handler.conns[conn] = struct{}{} 66 | handler.mutexConns.Unlock() 67 | 68 | wsConn := newWSConn(conn, handler.pendingWriteNum, handler.maxMsgLen) 69 | agent := handler.newAgent(wsConn) 70 | agent.Run() 71 | 72 | // cleanup 73 | wsConn.Close() 74 | handler.mutexConns.Lock() 75 | delete(handler.conns, conn) 76 | handler.mutexConns.Unlock() 77 | agent.OnClose() 78 | } 79 | 80 | func (server *WSServer) Start() { 81 | ln, err := net.Listen("tcp", server.Addr) 82 | if err != nil { 83 | log.Fatal("%v", err) 84 | } 85 | 86 | if server.MaxConnNum <= 0 { 87 | server.MaxConnNum = 100 88 | log.Info("invalid MaxConnNum, reset to %v", server.MaxConnNum) 89 | } 90 | if server.PendingWriteNum <= 0 { 91 | server.PendingWriteNum = 100 92 | log.Info("invalid PendingWriteNum, reset to %v", server.PendingWriteNum) 93 | } 94 | if server.MaxMsgLen <= 0 { 95 | server.MaxMsgLen = 4096 96 | log.Info("invalid MaxMsgLen, reset to %v", server.MaxMsgLen) 97 | } 98 | if server.HTTPTimeout <= 0 { 99 | server.HTTPTimeout = 10 * time.Second 100 | log.Info("invalid HTTPTimeout, reset to %v", server.HTTPTimeout) 101 | } 102 | if server.NewAgent == nil { 103 | log.Fatal("NewAgent must not be nil") 104 | } 105 | 106 | if server.CertFile != "" || server.KeyFile != "" { 107 | config := &tls.Config{} 108 | config.NextProtos = []string{"http/1.1"} 109 | 110 | var err error 111 | config.Certificates = make([]tls.Certificate, 1) 112 | config.Certificates[0], err = tls.LoadX509KeyPair(server.CertFile, server.KeyFile) 113 | if err != nil { 114 | log.Fatal("%v", err) 115 | } 116 | 117 | ln = tls.NewListener(ln, config) 118 | } 119 | 120 | server.ln = ln 121 | server.handler = &WSHandler{ 122 | maxConnNum: server.MaxConnNum, 123 | pendingWriteNum: server.PendingWriteNum, 124 | maxMsgLen: server.MaxMsgLen, 125 | newAgent: server.NewAgent, 126 | conns: make(WebsocketConnSet), 127 | upgrader: websocket.Upgrader{ 128 | HandshakeTimeout: server.HTTPTimeout, 129 | CheckOrigin: func(_ *http.Request) bool { return true }, 130 | }, 131 | } 132 | 133 | httpServer := &http.Server{ 134 | Addr: server.Addr, 135 | Handler: server.handler, 136 | ReadTimeout: server.HTTPTimeout, 137 | WriteTimeout: server.HTTPTimeout, 138 | MaxHeaderBytes: 1024, 139 | } 140 | 141 | go httpServer.Serve(ln) 142 | } 143 | 144 | func (server *WSServer) Close() { 145 | server.ln.Close() 146 | 147 | server.handler.mutexConns.Lock() 148 | for conn := range server.handler.conns { 149 | conn.Close() 150 | } 151 | server.handler.conns = nil 152 | server.handler.mutexConns.Unlock() 153 | 154 | server.handler.wg.Wait() 155 | } 156 | -------------------------------------------------------------------------------- /src/GAServer/service/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | **服务类型,可作为独立进程或线程使用 3 | ** 4 | */ 5 | package service 6 | 7 | import ( 8 | "fmt" 9 | 10 | "reflect" 11 | 12 | "GAServer/log" 13 | 14 | "github.com/AsynkronIT/protoactor-go/actor" 15 | "github.com/AsynkronIT/protoactor-go/remote" 16 | ) 17 | 18 | type Context actor.Context 19 | 20 | type IService interface { 21 | IServiceData 22 | //Receive(context actor.Context) 23 | OnReceive(context Context) 24 | OnInit() 25 | OnStart(as *ActorService) 26 | OnDestory() 27 | } 28 | 29 | //interface 30 | //func (s *BaseServer) OnReceive(context Context) {} 31 | //func (s *BaseServer) OnInit() {} 32 | //func (s *BaseServer) OnStart() {} 33 | 34 | type MessageFunc func(context Context) 35 | 36 | //服务的代理 37 | type ActorService struct { 38 | serviceIns IService 39 | rounter map[reflect.Type]MessageFunc 40 | } 41 | 42 | func (s *ActorService) Receive(context actor.Context) { 43 | //switch msg := context.Message().(type) { 44 | //case *hello: 45 | // fmt.Printf("Hello %v\n", msg.Who) 46 | //} 47 | switch msg := context.Message().(type) { 48 | case *actor.Started: 49 | fmt.Println("Started, initialize actor here") 50 | case *actor.Stopping: 51 | fmt.Println("Stopping, actor is about shut down") 52 | case *actor.Stopped: 53 | fmt.Println("Stopped, actor and its children are stopped") 54 | case *actor.Restarting: 55 | fmt.Println("Restarting, actor is about restart") 56 | default: 57 | log.Debug("recv defalult:", msg) 58 | s.serviceIns.OnReceive(context.(Context)) 59 | fun := s.rounter[reflect.TypeOf(msg)] 60 | if fun != nil { 61 | fun(context.(Context)) 62 | } 63 | } 64 | } 65 | 66 | func (s *ActorService) RegisterMsg(t reflect.Type, f MessageFunc) { 67 | s.rounter[t] = f 68 | } 69 | 70 | func StartService(s IService) { 71 | ac := &ActorService{s, make(map[reflect.Type]MessageFunc)} 72 | props := actor.FromInstance(ac) 73 | if s.GetAddress() != "" { 74 | remote.Start(s.GetAddress()) 75 | } 76 | pid, err := actor.SpawnNamed(props, s.GetName()) 77 | if err == nil { 78 | s.SetPID(pid) 79 | s.OnStart(ac) 80 | } else { 81 | log.Error("#############actor.SpawnNamed error:%v", err) 82 | } 83 | 84 | } 85 | 86 | func DestoryService(s *ActorService) { 87 | s.serviceIns.OnDestory() 88 | } 89 | -------------------------------------------------------------------------------- /src/GAServer/service/serviceData.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/AsynkronIT/protoactor-go/actor" 5 | _ "github.com/AsynkronIT/protoactor-go/remote" 6 | ) 7 | 8 | type IServiceData interface { 9 | Init(addr string, name string, typename string) 10 | GetName() string 11 | GetType() string 12 | GetAddress() string 13 | SetPID(pid *actor.PID) 14 | GetPID() *actor.PID 15 | } 16 | 17 | type ServiceData struct { 18 | Address string 19 | Name string 20 | TypeName string 21 | Pid *actor.PID 22 | } 23 | 24 | func (s *ServiceData) Init(addr string, name string, typename string) { 25 | s.Address = addr 26 | s.Name = name 27 | s.TypeName = typename 28 | } 29 | 30 | func (s *ServiceData) GetType() string { 31 | return s.TypeName 32 | } 33 | func (s *ServiceData) GetName() string { 34 | return s.Name 35 | } 36 | func (s *ServiceData) GetAddress() string { 37 | return s.Address 38 | } 39 | func (s *ServiceData) SetPID(pid *actor.PID) { 40 | s.Pid = pid 41 | } 42 | func (s *ServiceData) GetPID() *actor.PID { 43 | return s.Pid 44 | } 45 | func (s *ServiceData) OnDestory() { 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/GAServer/service/service_test.go: -------------------------------------------------------------------------------- 1 | package service_test 2 | 3 | import ( 4 | . "GAServer/service" 5 | "fmt" 6 | "testing" 7 | "time" 8 | 9 | //"github.com/AsynkronIT/goconsole" 10 | "github.com/AsynkronIT/protoactor-go/actor" 11 | ) 12 | 13 | type hello struct { 14 | Who string 15 | } 16 | 17 | func Example(t *testing.T) { 18 | fmt.Println("service_test Example pass") 19 | props := actor.FromInstance(&BaseServer{}) 20 | pid := actor.Spawn(props) 21 | pid.Tell(&hello{Who: "Roger"}) 22 | time.Sleep(1) 23 | fmt.Println("service_test Example pass") 24 | pid.GracefulStop() 25 | } 26 | -------------------------------------------------------------------------------- /src/GAServer/util/deepcopy.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | // reference: https://github.com/mohae/deepcopy 4 | import ( 5 | "reflect" 6 | ) 7 | 8 | func deepCopy(dst, src reflect.Value) { 9 | switch src.Kind() { 10 | case reflect.Interface: 11 | value := src.Elem() 12 | if !value.IsValid() { 13 | return 14 | } 15 | newValue := reflect.New(value.Type()).Elem() 16 | deepCopy(newValue, value) 17 | dst.Set(newValue) 18 | case reflect.Ptr: 19 | value := src.Elem() 20 | if !value.IsValid() { 21 | return 22 | } 23 | dst.Set(reflect.New(value.Type())) 24 | deepCopy(dst.Elem(), value) 25 | case reflect.Map: 26 | dst.Set(reflect.MakeMap(src.Type())) 27 | keys := src.MapKeys() 28 | for _, key := range keys { 29 | value := src.MapIndex(key) 30 | newValue := reflect.New(value.Type()).Elem() 31 | deepCopy(newValue, value) 32 | dst.SetMapIndex(key, newValue) 33 | } 34 | case reflect.Slice: 35 | dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap())) 36 | for i := 0; i < src.Len(); i++ { 37 | deepCopy(dst.Index(i), src.Index(i)) 38 | } 39 | case reflect.Struct: 40 | typeSrc := src.Type() 41 | for i := 0; i < src.NumField(); i++ { 42 | value := src.Field(i) 43 | tag := typeSrc.Field(i).Tag 44 | if value.CanSet() && tag.Get("deepcopy") != "-" { 45 | deepCopy(dst.Field(i), value) 46 | } 47 | } 48 | default: 49 | dst.Set(src) 50 | } 51 | } 52 | 53 | func DeepCopy(dst, src interface{}) { 54 | typeDst := reflect.TypeOf(dst) 55 | typeSrc := reflect.TypeOf(src) 56 | if typeDst != typeSrc { 57 | panic("DeepCopy: " + typeDst.String() + " != " + typeSrc.String()) 58 | } 59 | if typeSrc.Kind() != reflect.Ptr { 60 | panic("DeepCopy: pass arguments by address") 61 | } 62 | 63 | valueDst := reflect.ValueOf(dst).Elem() 64 | valueSrc := reflect.ValueOf(src).Elem() 65 | if !valueDst.IsValid() || !valueSrc.IsValid() { 66 | panic("DeepCopy: invalid arguments") 67 | } 68 | 69 | deepCopy(valueDst, valueSrc) 70 | } 71 | 72 | func DeepClone(v interface{}) interface{} { 73 | dst := reflect.New(reflect.TypeOf(v)).Elem() 74 | deepCopy(dst, reflect.ValueOf(v)) 75 | return dst.Interface() 76 | } 77 | -------------------------------------------------------------------------------- /src/GAServer/util/example_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "GAServer/util" 5 | "fmt" 6 | ) 7 | 8 | func ExampleMap() { 9 | m := new(util.Map) 10 | 11 | fmt.Println(m.Get("key")) 12 | m.Set("key", "value") 13 | fmt.Println(m.Get("key")) 14 | m.Del("key") 15 | fmt.Println(m.Get("key")) 16 | 17 | m.Set(1, "1") 18 | m.Set(2, 2) 19 | m.Set("3", 3) 20 | 21 | fmt.Println(m.Len()) 22 | 23 | // Output: 24 | // 25 | // value 26 | // 27 | // 3 28 | } 29 | 30 | func ExampleRandGroup() { 31 | i := util.RandGroup(0, 0, 50, 50) 32 | switch i { 33 | case 2, 3: 34 | fmt.Println("ok") 35 | } 36 | 37 | // Output: 38 | // ok 39 | } 40 | 41 | func ExampleRandInterval() { 42 | v := util.RandInterval(-1, 1) 43 | switch v { 44 | case -1, 0, 1: 45 | fmt.Println("ok") 46 | } 47 | 48 | // Output: 49 | // ok 50 | } 51 | 52 | func ExampleRandIntervalN() { 53 | r := util.RandIntervalN(-1, 0, 2) 54 | if r[0] == -1 && r[1] == 0 || 55 | r[0] == 0 && r[1] == -1 { 56 | fmt.Println("ok") 57 | } 58 | 59 | // Output: 60 | // ok 61 | } 62 | 63 | func ExampleDeepCopy() { 64 | src := []int{1, 2, 3} 65 | 66 | var dst []int 67 | util.DeepCopy(&dst, &src) 68 | 69 | for _, v := range dst { 70 | fmt.Println(v) 71 | } 72 | 73 | // Output: 74 | // 1 75 | // 2 76 | // 3 77 | } 78 | 79 | func ExampleDeepClone() { 80 | src := []int{1, 2, 3} 81 | 82 | dst := util.DeepClone(src).([]int) 83 | 84 | for _, v := range dst { 85 | fmt.Println(v) 86 | } 87 | 88 | // Output: 89 | // 1 90 | // 2 91 | // 3 92 | } 93 | -------------------------------------------------------------------------------- /src/GAServer/util/map.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Map struct { 8 | sync.RWMutex 9 | m map[interface{}]interface{} 10 | } 11 | 12 | func (m *Map) init() { 13 | if m.m == nil { 14 | m.m = make(map[interface{}]interface{}) 15 | } 16 | } 17 | 18 | func (m *Map) UnsafeGet(key interface{}) interface{} { 19 | if m.m == nil { 20 | return nil 21 | } else { 22 | return m.m[key] 23 | } 24 | } 25 | 26 | func (m *Map) Get(key interface{}) interface{} { 27 | m.RLock() 28 | defer m.RUnlock() 29 | return m.UnsafeGet(key) 30 | } 31 | 32 | func (m *Map) UnsafeSet(key interface{}, value interface{}) { 33 | m.init() 34 | m.m[key] = value 35 | } 36 | 37 | func (m *Map) Set(key interface{}, value interface{}) { 38 | m.Lock() 39 | defer m.Unlock() 40 | m.UnsafeSet(key, value) 41 | } 42 | 43 | func (m *Map) TestAndSet(key interface{}, value interface{}) interface{} { 44 | m.Lock() 45 | defer m.Unlock() 46 | 47 | m.init() 48 | 49 | if v, ok := m.m[key]; ok { 50 | return v 51 | } else { 52 | m.m[key] = value 53 | return nil 54 | } 55 | } 56 | 57 | func (m *Map) UnsafeDel(key interface{}) { 58 | m.init() 59 | delete(m.m, key) 60 | } 61 | 62 | func (m *Map) Del(key interface{}) { 63 | m.Lock() 64 | defer m.Unlock() 65 | m.UnsafeDel(key) 66 | } 67 | 68 | func (m *Map) UnsafeLen() int { 69 | if m.m == nil { 70 | return 0 71 | } else { 72 | return len(m.m) 73 | } 74 | } 75 | 76 | func (m *Map) Len() int { 77 | m.RLock() 78 | defer m.RUnlock() 79 | return m.UnsafeLen() 80 | } 81 | 82 | func (m *Map) UnsafeRange(f func(interface{}, interface{})) { 83 | if m.m == nil { 84 | return 85 | } 86 | for k, v := range m.m { 87 | f(k, v) 88 | } 89 | } 90 | 91 | func (m *Map) RLockRange(f func(interface{}, interface{})) { 92 | m.RLock() 93 | defer m.RUnlock() 94 | m.UnsafeRange(f) 95 | } 96 | 97 | func (m *Map) LockRange(f func(interface{}, interface{})) { 98 | m.Lock() 99 | defer m.Unlock() 100 | m.UnsafeRange(f) 101 | } 102 | -------------------------------------------------------------------------------- /src/GAServer/util/rand.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | func init() { 9 | rand.Seed(time.Now().UnixNano()) 10 | } 11 | 12 | func RandGroup(p ...uint32) int { 13 | if p == nil { 14 | panic("args not found") 15 | } 16 | 17 | r := make([]uint32, len(p)) 18 | for i := 0; i < len(p); i++ { 19 | if i == 0 { 20 | r[0] = p[0] 21 | } else { 22 | r[i] = r[i-1] + p[i] 23 | } 24 | } 25 | 26 | rl := r[len(r)-1] 27 | if rl == 0 { 28 | return 0 29 | } 30 | 31 | rn := uint32(rand.Int63n(int64(rl))) 32 | for i := 0; i < len(r); i++ { 33 | if rn < r[i] { 34 | return i 35 | } 36 | } 37 | 38 | panic("bug") 39 | } 40 | 41 | func RandInterval(b1, b2 int32) int32 { 42 | if b1 == b2 { 43 | return b1 44 | } 45 | 46 | min, max := int64(b1), int64(b2) 47 | if min > max { 48 | min, max = max, min 49 | } 50 | return int32(rand.Int63n(max-min+1) + min) 51 | } 52 | 53 | func RandIntervalN(b1, b2 int32, n uint32) []int32 { 54 | if b1 == b2 { 55 | return []int32{b1} 56 | } 57 | 58 | min, max := int64(b1), int64(b2) 59 | if min > max { 60 | min, max = max, min 61 | } 62 | l := max - min + 1 63 | if int64(n) > l { 64 | n = uint32(l) 65 | } 66 | 67 | r := make([]int32, n) 68 | m := make(map[int32]int32) 69 | for i := uint32(0); i < n; i++ { 70 | v := int32(rand.Int63n(l) + min) 71 | 72 | if mv, ok := m[v]; ok { 73 | r[i] = mv 74 | } else { 75 | r[i] = v 76 | } 77 | 78 | lv := int32(l - 1 + min) 79 | if v != lv { 80 | if mv, ok := m[lv]; ok { 81 | m[v] = mv 82 | } else { 83 | m[v] = lv 84 | } 85 | } 86 | 87 | l-- 88 | } 89 | 90 | return r 91 | } 92 | -------------------------------------------------------------------------------- /src/GAServer/util/semaphore.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | type Semaphore chan struct{} 4 | 5 | func MakeSemaphore(n int) Semaphore { 6 | return make(Semaphore, n) 7 | } 8 | 9 | func (s Semaphore) Acquire() { 10 | s <- struct{}{} 11 | } 12 | 13 | func (s Semaphore) Release() { 14 | <-s 15 | } 16 | -------------------------------------------------------------------------------- /src/GAServer/util/stack.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "runtime" 5 | 6 | "GAServer/log" 7 | "bytes" 8 | "fmt" 9 | //"github.com/davecgh/go-spew/spew" 10 | ) 11 | 12 | // 产生panic时的调用栈打印 13 | func PrintPanicStack(extras ...interface{}) { 14 | var buff bytes.Buffer 15 | var haveErr = false 16 | if x := recover(); x != nil { 17 | haveErr = true 18 | buff.WriteString(fmt.Sprintf("dump:%v\n", x)) 19 | //log.Error("dump:%v", x) 20 | i := 0 21 | funcName, file, line, ok := runtime.Caller(i) 22 | for ok { 23 | buff.WriteString(fmt.Sprintf("frame %v:[func:%v,file:%v,line:%v]\n", i, runtime.FuncForPC(funcName).Name(), file, line)) 24 | //log.Error("frame %v:[func:%v,file:%v,line:%v]\n", i, runtime.FuncForPC(funcName).Name(), file, line) 25 | i++ 26 | funcName, file, line, ok = runtime.Caller(i) 27 | } 28 | 29 | //for k := range extras { 30 | // buff.WriteString(fmt.Sprintf("EXRAS#%v DATA:%v\n", k, spew.Sdump(extras[k]))) 31 | //} 32 | } 33 | if haveErr { 34 | log.Error(buff.String()) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/GAServer/util/tools.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "time" 4 | 5 | type TimeTaskFunc func() 6 | 7 | func StartLoopTask(t time.Duration, fun TimeTaskFunc) *time.Ticker { 8 | timeTicker := time.NewTicker(t) 9 | go func() { 10 | for { 11 | select { 12 | case <-timeTicker.C: 13 | fun() 14 | } 15 | } 16 | }() 17 | return timeTicker 18 | } 19 | -------------------------------------------------------------------------------- /src/Robot/agent/agent.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "GAServer/network" 5 | // "io/ioutil" 6 | "log" 7 | // "net/http" 8 | 9 | // "GAServer/network/protobuf" 10 | 11 | // "github.com/gogo/protobuf/proto" 12 | ) 13 | 14 | func newAgent(conn *network.TCPConn) network.Agent { 15 | Client := new(Agent) 16 | Client.conn = conn 17 | return Client 18 | } 19 | 20 | type Agent struct { 21 | conn *network.TCPConn 22 | msgHandle func(channel byte, msgId byte, data []byte) 23 | errorFun func(reason string) 24 | closeFun func() 25 | } 26 | 27 | func (a *Agent) Run() { 28 | log.Println("Agent.run") 29 | for { 30 | data, err := a.conn.ReadMsg() 31 | if err != nil { 32 | log.Println("read message error: ", err) 33 | a.errorFun(err.Error()) 34 | break 35 | } 36 | 37 | a.msgHandle(data[0], data[0], data[3:]) 38 | } 39 | } 40 | 41 | func (a *Agent) OnClose() { 42 | a.closeFun() 43 | } 44 | 45 | func (a *Agent) WriteMsg(channel byte, msgId byte, msg []byte) { 46 | 47 | data := []byte{msgId, 0, 0} 48 | data = append(data, msg...) 49 | err := a.conn.WriteMsg(data) 50 | if err != nil { 51 | log.Println("write message error:", err) 52 | } 53 | } 54 | 55 | //func (a *Agent) LocalAddr() net.Addr { 56 | //return a.conn.LocalAddr() 57 | //} 58 | 59 | //func (a *Agent) RemoteAddr() net.Addr { 60 | // return a.conn.RemoteAddr() 61 | //} 62 | 63 | func (a *Agent) Close() { 64 | a.conn.Close() 65 | } 66 | 67 | func (a *Agent) Destroy() { 68 | a.conn.Destroy() 69 | } 70 | -------------------------------------------------------------------------------- /src/Robot/agent/robot.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "GAServer/network" 5 | "fmt" 6 | "gameproto" 7 | _ "gameproto/msgs" 8 | "io/ioutil" 9 | "log" 10 | "net/http" 11 | "sync" 12 | "time" 13 | 14 | "github.com/gogo/protobuf/proto" 15 | ) 16 | 17 | type Robot struct { 18 | account string 19 | pwd string 20 | 21 | gateAddr string 22 | uid uint64 23 | key string 24 | 25 | client *network.TCPClient 26 | agent *Agent 27 | wg sync.WaitGroup 28 | taskCounter int 29 | taskCount int 30 | actionTime time.Duration 31 | result chan string 32 | } 33 | 34 | func NewRobot(account, pwd string, actionTime time.Duration) *Robot { 35 | return &Robot{account: account, pwd: pwd, actionTime: actionTime, result: make(chan string, 1)} 36 | } 37 | 38 | func (robot *Robot) Start(taskCount int) string { 39 | robot.taskCount = taskCount 40 | if !robot.Login() { 41 | return "Login fail" 42 | } 43 | //robot.wg.Add(1) 44 | robot.ConnectGate() 45 | //robot.wg.Wait() 46 | r := <-robot.result 47 | return r 48 | } 49 | 50 | func (robot *Robot) Login() bool { 51 | fmt.Println("login...") 52 | 53 | response, err := http.Get(fmt.Sprintf("http://127.0.0.1:9900/login?a=%s&p=111", robot.account)) 54 | if err != nil { 55 | log.Println("login http.get fail:", err) 56 | return false 57 | } 58 | defer response.Body.Close() 59 | body, _ := ioutil.ReadAll(response.Body) 60 | result := gameproto.UserLoginResult{} 61 | umErr := proto.Unmarshal(body, &result) 62 | fmt.Println("err:", umErr, " result:", result) 63 | robot.uid = uint64(result.Uid) 64 | robot.key = result.Key 65 | robot.gateAddr = result.GateAddr 66 | return result.GetResult() == int32(gameproto.OK) 67 | } 68 | 69 | func (robot *Robot) newAgent(conn *network.TCPConn) network.Agent { 70 | robot.agent = new(Agent) 71 | robot.agent.conn = conn 72 | robot.agent.msgHandle = robot.OnMsgRecv 73 | robot.agent.errorFun = robot.OnErr 74 | robot.agent.closeFun = robot.OnDisconnected 75 | robot.OnConnected() 76 | return robot.agent 77 | } 78 | 79 | func (robot *Robot) ConnectGate() { 80 | fmt.Println("ConnectGate...") 81 | robot.client = new(network.TCPClient) 82 | robot.client.Addr = robot.gateAddr 83 | robot.client.NewAgent = robot.newAgent 84 | robot.client.LittleEndian = true 85 | //robot.client.AutoReconnect = true 86 | robot.client.Start() 87 | 88 | } 89 | 90 | func (robot *Robot) OnConnected() { 91 | fmt.Println("OnConnected...") 92 | robot.SendMsg(0, &gameproto.PlatformUser{PlatformUid: int32(robot.uid), Key: robot.key}) 93 | } 94 | 95 | func (robot *Robot) OnDisconnected() { 96 | fmt.Println("OnDisconnected...") 97 | robot.result <- "close" 98 | } 99 | 100 | func (robot *Robot) EnterGame() { 101 | fmt.Println("EnterGame...") 102 | 103 | robot.SendMsg(byte(gameproto.C2S_Test), &gameproto.C2S_TestMsg{1}) 104 | //robot.SendMsg(messages.Chat, byte(messages.C2S_PrivateChat), &messages.C2S_PrivateChatMsg{"玩家11", "hello"}) 105 | //robot.SendMsg(messages.Chat, byte(messages.C2S_WorldChat), &messages.C2S_WorldChatMsg{"world"}) 106 | } 107 | 108 | func (robot *Robot) OnErr(err string) { 109 | robot.result <- err 110 | //robot.Finish(err) 111 | //robot.SendMsg(messages.Shop, byte(messages.C2S_ShopBuy), &messages.C2S_ShopBuyMsg{1}) 112 | } 113 | func (robot *Robot) OnMsgRecv(channel byte, msgId byte, data []byte) { 114 | //c := gameproto.ChannelType(channel) 115 | //fmt.Println("OnMsgRecv:", c, " msg:", msgId, " data:", len(data)) 116 | 117 | tmsgId := gameproto.GS2C_CMD(msgId) 118 | switch tmsgId { 119 | case gameproto.S2C_CONFIRM: 120 | msg := gameproto.S2C_ConfirmInfo{} 121 | proto.Unmarshal(data, &msg) 122 | //fmt.Println("S2C_CONFIRM:", msg) 123 | case gameproto.S2C_LOGIN_END: 124 | msg := gameproto.LoginReturn{} 125 | proto.Unmarshal(data, &msg) 126 | fmt.Println("login result:", msg) 127 | if msg.ErrCode == int32(gameproto.OK) { 128 | robot.EnterGame() 129 | } 130 | case gameproto.S2C_Test: 131 | msg := gameproto.S2C_TestMsg{} 132 | proto.Unmarshal(data, &msg) 133 | //fmt.Println("S2C_Test result:", msg) 134 | 135 | if robot.taskCounter > robot.taskCount { 136 | robot.Finish("OK") 137 | } 138 | if robot.actionTime > 0 { 139 | time.Sleep(robot.actionTime) 140 | } 141 | 142 | robot.taskCounter++ 143 | //time.Sleep(time.Second) 144 | robot.SendMsg(byte(gameproto.C2S_Test), &gameproto.C2S_TestMsg{Id: 1}) 145 | } 146 | 147 | /* 148 | if c == messages.Login { 149 | msg := messages.CheckLoginResult{} 150 | proto.Unmarshal(data, &msg) 151 | fmt.Println("login result:", msg) 152 | if msg.Result == messages.OK { 153 | robot.EnterGame() 154 | } 155 | } else if c == messages.Shop { 156 | tmsgId := messages.ShopMsgType(msgId) 157 | switch tmsgId { 158 | case messages.S2C_ShopBuy: 159 | msg := messages.S2C_ShopBuyMsg{} 160 | proto.Unmarshal(data, &msg) 161 | //fmt.Println("shop result:", msg) 162 | if robot.taskCounter > robot.taskCount { 163 | robot.Finish("OK") 164 | } 165 | if robot.actionTime > 0 { 166 | time.Sleep(robot.actionTime) 167 | } 168 | 169 | robot.taskCounter++ 170 | robot.SendMsg(messages.Shop, byte(messages.C2S_ShopBuy), &messages.C2S_ShopBuyMsg{1}) 171 | } 172 | } else if c == messages.Chat { 173 | tmsgId := messages.ChatMsgType(msgId) 174 | switch tmsgId { 175 | case messages.S2C_PrivateChat: 176 | msg := messages.S2C_PrivateChatMsg{} 177 | proto.Unmarshal(data, &msg) 178 | fmt.Println("chat back result:", msg) 179 | case messages.S2C_PrivateOtherChat: 180 | msg := messages.S2C_PrivateOtherChatMsg{} 181 | proto.Unmarshal(data, &msg) 182 | fmt.Println("otherchat:", msg) 183 | case messages.S2C_WorldChat: 184 | msg := messages.S2C_WorldChatMsg{} 185 | proto.Unmarshal(data, &msg) 186 | fmt.Println("worldchat :", msg) 187 | } 188 | } 189 | */ 190 | } 191 | 192 | func (robot *Robot) SendMsg(msgId byte, pb proto.Message) { 193 | data, err := proto.Marshal(pb) 194 | if err != nil { 195 | fmt.Println("###EncodeMsg error:", err) 196 | return 197 | } 198 | robot.agent.WriteMsg(byte(0), msgId, data) 199 | } 200 | 201 | func (robot *Robot) Finish(result string) { 202 | //robot.result = result 203 | robot.client.AutoReconnect = false 204 | robot.agent.Close() 205 | //robot.wg.Done() 206 | robot.result <- result 207 | } 208 | -------------------------------------------------------------------------------- /src/Robot/robotMachine/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | . "Robot/agent" 5 | "fmt" 6 | _ "sync" 7 | "time" 8 | ) 9 | 10 | //var wg sync.WaitGroup 11 | 12 | func main() { 13 | var actionTime time.Duration = time.Millisecond * 0 14 | var robotCount = 500 15 | var taskCount = 1000 16 | var finishCount = 0 17 | var errorCount = 0 18 | ch := make(chan string, 100) 19 | 20 | fmt.Println("start...count:", robotCount) 21 | now := time.Now().UnixNano() 22 | //wg.Add(robotCount) 23 | for i := 0; i < robotCount; i++ { 24 | go Run(i, taskCount, actionTime, ch) 25 | } 26 | for r := range ch { 27 | if r == "OK" { 28 | finishCount++ 29 | } else { 30 | errorCount++ 31 | } 32 | 33 | fmt.Println("r:", r, " finish:", finishCount, "/", errorCount, "/", robotCount) 34 | if finishCount+errorCount == robotCount { 35 | break 36 | } 37 | } 38 | //wg.Wait() 39 | use := time.Now().UnixNano() - now 40 | ms := use / int64(time.Millisecond) 41 | qps := float32(taskCount*finishCount) / float32(ms) * 1000 42 | fmt.Println("end. robotCount=", robotCount, "time=ms", ms, "all_qps=", qps) 43 | } 44 | 45 | func Run(index, taskCount int, actionTime time.Duration, ch chan string) { 46 | now := time.Now().UnixNano() 47 | acc := fmt.Sprintf("magicsea_%d", index) 48 | r := NewRobot(acc, "111", actionTime) 49 | result := r.Start(taskCount) 50 | use := time.Now().UnixNano() - now 51 | ms := use / int64(time.Millisecond) 52 | qps := float32(taskCount) / float32(ms) * 1000 53 | fmt.Println("task over=>", index, " result:", result, taskCount, " usetime:ms", use/int64(time.Millisecond), " qps:", qps) 54 | ch <- result 55 | //wg.Done() 56 | } 57 | -------------------------------------------------------------------------------- /src/Robot/robotTest/agent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "GAServer/network" 5 | // "io/ioutil" 6 | "log" 7 | // "net/http" 8 | // "GAServer/network/protobuf" 9 | // "github.com/gogo/protobuf/proto" 10 | ) 11 | 12 | func newAgent(conn *network.TCPConn) network.Agent { 13 | Client := new(Agent) 14 | Client.conn = conn 15 | return Client 16 | } 17 | 18 | type Agent struct { 19 | conn *network.TCPConn 20 | msgHandle func(channel byte, msgId byte, data []byte) 21 | } 22 | 23 | func (a *Agent) Run() { 24 | log.Println("Agent.run") 25 | for { 26 | data, err := a.conn.ReadMsg() 27 | if err != nil { 28 | log.Println("read message: ", err) 29 | break 30 | } 31 | 32 | a.msgHandle(0, data[0], data[3:]) 33 | } 34 | } 35 | 36 | func (a *Agent) OnClose() {} 37 | 38 | /* 39 | func (a *Agent) WriteMsg(channel byte, msgId byte, msg []byte) { 40 | 41 | data := []byte{channel, msgId} 42 | data = append(data, msg...) 43 | err := a.conn.WriteMsg(data) 44 | if err != nil { 45 | log.Println("write message error:", err) 46 | } 47 | 48 | } 49 | */ 50 | func (a *Agent) WriteMsg(msgId byte, msg []byte) { 51 | 52 | data := []byte{msgId, 0, 0} 53 | data = append(data, msg...) 54 | err := a.conn.WriteMsg(data) 55 | if err != nil { 56 | log.Println("write message error:", err) 57 | } 58 | 59 | } 60 | 61 | //func (a *Agent) LocalAddr() net.Addr { 62 | //return a.conn.LocalAddr() 63 | //} 64 | 65 | //func (a *Agent) RemoteAddr() net.Addr { 66 | // return a.conn.RemoteAddr() 67 | //} 68 | 69 | func (a *Agent) Close() { 70 | a.conn.Close() 71 | } 72 | 73 | func (a *Agent) Destroy() { 74 | a.conn.Destroy() 75 | } 76 | -------------------------------------------------------------------------------- /src/Robot/robotTest/r_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | type node struct { 9 | i int 10 | } 11 | 12 | func TestMain(T *testing.T) { 13 | c := make(chan *node) 14 | n := &node{1} 15 | go func() { 16 | c <- n 17 | }() 18 | 19 | m := <-c 20 | m.i = 2 21 | fmt.Printf("n=%v,%p m=%v,%p\n", n, n, m, m) 22 | } 23 | -------------------------------------------------------------------------------- /src/Robot/robotTest/robot.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "GAServer/network" 5 | "fmt" 6 | "gameproto" 7 | _ "gameproto/msgs" 8 | "io/ioutil" 9 | "log" 10 | "net/http" 11 | "sync" 12 | "time" 13 | 14 | "github.com/gogo/protobuf/proto" 15 | ) 16 | 17 | type Robot struct { 18 | account string 19 | pwd string 20 | 21 | gateAddr string 22 | uid uint64 23 | key string 24 | 25 | client *network.TCPClient 26 | agent *Agent 27 | wg sync.WaitGroup 28 | } 29 | 30 | func NewRobot(account, pwd string) *Robot { 31 | return &Robot{account: account, pwd: pwd} 32 | } 33 | 34 | func (robot *Robot) Start() { 35 | robot.wg.Add(1) 36 | if !robot.Login() { 37 | log.Fatalln("Login fail") 38 | return 39 | } 40 | robot.ConnectGate() 41 | robot.wg.Wait() 42 | } 43 | 44 | func (robot *Robot) Login() bool { 45 | fmt.Println("login...") 46 | 47 | response, err := http.Get(fmt.Sprintf("http://127.0.0.1:9900/login?a=%s&p=111", robot.account)) 48 | if err != nil { 49 | log.Fatalln("login http.get fail:", err) 50 | return false 51 | } 52 | defer response.Body.Close() 53 | body, _ := ioutil.ReadAll(response.Body) 54 | result := gameproto.UserLoginResult{} 55 | umErr := proto.Unmarshal(body, &result) 56 | fmt.Println("err:", umErr, " result:", result) 57 | robot.uid = uint64(result.Uid) 58 | robot.key = result.Key 59 | robot.gateAddr = result.GateAddr 60 | return result.GetResult() == int32(gameproto.OK) 61 | } 62 | 63 | func (robot *Robot) newAgent(conn *network.TCPConn) network.Agent { 64 | robot.agent = new(Agent) 65 | robot.agent.conn = conn 66 | robot.agent.msgHandle = robot.OnMsgRecv 67 | robot.OnConnected() 68 | return robot.agent 69 | } 70 | 71 | func (robot *Robot) ConnectGate() { 72 | fmt.Println("ConnectGate...") 73 | robot.client = new(network.TCPClient) 74 | robot.client.Addr = robot.gateAddr 75 | robot.client.NewAgent = robot.newAgent 76 | robot.client.LittleEndian = true 77 | robot.client.Start() 78 | 79 | } 80 | 81 | func (robot *Robot) OnConnected() { 82 | fmt.Println("OnConnected...") 83 | 84 | robot.SendMsg(0, &gameproto.PlatformUser{PlatformUid: int32(robot.uid), Key: robot.key}) 85 | } 86 | 87 | func (robot *Robot) EnterGame() { 88 | fmt.Println("EnterGame...") 89 | robot.SendMsg(byte(gameproto.C2S_Test), &gameproto.C2S_TestMsg{Id: 1}) 90 | //robot.SendMsg(gameproto.Chat, byte(gameproto.C2S_PrivateChat), &gameproto.C2S_PrivateChatMsg{"玩家11", "hello"}) 91 | //robot.SendMsg(gameproto.Chat, byte(gameproto.C2S_WorldChat), &gameproto.C2S_WorldChatMsg{"world"}) 92 | } 93 | 94 | func (robot *Robot) OnMsgRecv(channel byte, msgId byte, data []byte) { 95 | c := 0 //gameproto.ChannelType(channel) 96 | fmt.Println("OnMsgRecv:", c, " msg:", msgId, " data:", len(data)) 97 | 98 | tmsgId := gameproto.GS2C_CMD(msgId) 99 | switch tmsgId { 100 | case gameproto.S2C_CONFIRM: 101 | msg := gameproto.S2C_ConfirmInfo{} 102 | proto.Unmarshal(data, &msg) 103 | fmt.Println("S2C_CONFIRM:", msg) 104 | case gameproto.S2C_LOGIN_END: 105 | msg := gameproto.LoginReturn{} 106 | proto.Unmarshal(data, &msg) 107 | fmt.Println("login result:", msg) 108 | if msg.ErrCode == int32(gameproto.OK) { 109 | robot.EnterGame() 110 | } 111 | case gameproto.S2C_Test: 112 | msg := gameproto.S2C_TestMsg{} 113 | proto.Unmarshal(data, &msg) 114 | fmt.Println("shop result:", msg) 115 | time.Sleep(time.Second) 116 | robot.SendMsg(byte(gameproto.C2S_Test), &gameproto.C2S_TestMsg{Id: 1}) 117 | } 118 | 119 | return 120 | /* 121 | if c == gameproto.Login { 122 | msg := gameproto.CheckLoginResult{} 123 | proto.Unmarshal(data, &msg) 124 | fmt.Println("login result:", msg) 125 | if msg.Result == gameproto.OK { 126 | robot.EnterGame() 127 | } 128 | } else if c == gameproto.Shop { 129 | tmsgId := gameproto.GS2C_CMD(msgId) 130 | switch tmsgId { 131 | case gameproto.S2C_SHOP_CARD_INFO: 132 | msg := gameproto.S2C_ShopBuyMsg{} 133 | proto.Unmarshal(data, &msg) 134 | fmt.Println("shop result:", msg) 135 | time.Sleep(time.Second) 136 | robot.SendMsg(byte(gameproto.C2S_SHOP_BUY), &gameproto.C2S_ShopBuyMsg{1}) 137 | } 138 | } else if c == gameproto.Chat { 139 | tmsgId := gameproto.ChatMsgType(msgId) 140 | switch tmsgId { 141 | case gameproto.S2C_PrivateChat: 142 | msg := gameproto.S2C_PrivateChatMsg{} 143 | proto.Unmarshal(data, &msg) 144 | fmt.Println("chat back result:", msg) 145 | case gameproto.S2C_PrivateOtherChat: 146 | msg := gameproto.S2C_PrivateOtherChatMsg{} 147 | proto.Unmarshal(data, &msg) 148 | fmt.Println("otherchat:", msg) 149 | case gameproto.S2C_WorldChat: 150 | msg := gameproto.S2C_WorldChatMsg{} 151 | proto.Unmarshal(data, &msg) 152 | fmt.Println("worldchat :", msg) 153 | } 154 | } 155 | */ 156 | } 157 | 158 | func (robot *Robot) SendMsg(msgId byte, pb proto.Message) { 159 | data, err := proto.Marshal(pb) 160 | if err != nil { 161 | fmt.Println("###EncodeMsg error:", err) 162 | return 163 | } 164 | robot.agent.WriteMsg(msgId, data) 165 | } 166 | 167 | /* 168 | func (robot *Robot) SendMsg(channel gameproto.ChannelType, msgId byte, pb proto.Message) { 169 | data, err := proto.Marshal(pb) 170 | if err != nil { 171 | fmt.Println("###EncodeMsg error:", err) 172 | return 173 | } 174 | robot.agent.WriteMsg(byte(channel), msgId, data) 175 | } 176 | */ 177 | -------------------------------------------------------------------------------- /src/Robot/robotTest/robotTest.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println("start...") 9 | r := NewRobot("magicsea_1", "111") 10 | r.Start() 11 | fmt.Println("end") 12 | } 13 | -------------------------------------------------------------------------------- /src/Server/center/centerserver.go: -------------------------------------------------------------------------------- 1 | package center 2 | 3 | import ( 4 | "GAServer/log" 5 | "GAServer/service" 6 | "gameproto/msgs" 7 | "reflect" 8 | 9 | "github.com/AsynkronIT/protoactor-go/actor" 10 | ) 11 | 12 | type CenterService struct { 13 | service.ServiceData 14 | serviceGroups map[string]*ServiceGroup //所有服务 map[type]group 15 | serviceAll map[string]*ServiceNode //索引服务路径引用 map[addr+id]group 16 | } 17 | 18 | //Service 获取服务对象 19 | func Service() service.IService { 20 | return new(CenterService) 21 | } 22 | 23 | func Type() string { 24 | return "center" 25 | } 26 | 27 | //以下为接口函数 28 | func (s *CenterService) OnReceive(context service.Context) { 29 | log.Debug("center.OnReceive:%v", context.Message()) 30 | 31 | } 32 | 33 | func (s *CenterService) OnInit() { 34 | s.serviceGroups = make(map[string]*ServiceGroup) 35 | s.serviceAll = make(map[string]*ServiceNode) 36 | } 37 | 38 | func (s *CenterService) OnStart(as *service.ActorService) { 39 | //as.RegisterMsg(reflect.TypeOf(&msgs.RemoveService{}), s.OnRemoveService) //解注册服务器 40 | as.RegisterMsg(reflect.TypeOf(&msgs.AddService{}), s.OnAddService) //注册服务器 41 | as.RegisterMsg(reflect.TypeOf(&actor.Terminated{}), s.OnChildServiceTerminated) //被动断开服务器 42 | as.RegisterMsg(reflect.TypeOf(&msgs.UploadService{}), s.OnUpdateService) //更新服务器 43 | as.RegisterMsg(reflect.TypeOf(&msgs.ApplyService{}), s.OnApplyService) //获取一个服务器 44 | as.RegisterMsg(reflect.TypeOf(&msgs.GetTypeServices{}), s.GetTypeServices) //获取一类服务器 45 | } 46 | 47 | //注册服务器 48 | func (s *CenterService) OnAddService(context service.Context) { 49 | log.Println("center.OnAddService:", context.Message()) 50 | msg := context.Message().(*msgs.AddService) 51 | var group *ServiceGroup 52 | if g, ok := s.serviceGroups[msg.ServiceType]; !ok { 53 | group = new(ServiceGroup) 54 | group.services = make(map[string]*ServiceNode) 55 | s.serviceGroups[msg.ServiceType] = group 56 | log.Println("new service Type:", msg.ServiceType) 57 | } else { 58 | group = g 59 | } 60 | 61 | var node = &ServiceNode{pid: msg.Pid, 62 | serviceType: msg.ServiceType, 63 | serviceName: msg.ServiceName, 64 | load: 0, 65 | state: msgs.ServiceStateFree, 66 | values: msg.Values} 67 | 68 | s.serviceAll[node.pid.String()] = node //加入索引 69 | group.AddService(node) //加入group 70 | context.Watch(node.pid) //监控 71 | 72 | context.Tell(context.Sender(), &msgs.SendOK{}) 73 | log.Println("center.OnAddService OK,", msg.ServiceName) 74 | } 75 | 76 | //解注册服务器 77 | func (s *CenterService) __OnRemoveService(context service.Context) { 78 | log.Println("center.OnRemoveService:", context.Message()) 79 | msg := context.Message().(*msgs.RemoveService) 80 | 81 | var group *ServiceGroup 82 | if g, ok := s.serviceGroups[msg.ServiceType]; !ok { 83 | group = g 84 | log.Error("no found service Type:%v", msg.ServiceType) 85 | return 86 | } 87 | 88 | group.RemoveService(msg.ServiceName) 89 | } 90 | 91 | //被动断开服务器 92 | func (s *CenterService) OnChildServiceTerminated(context service.Context) { 93 | log.Println("center.OnChildServiceTerminated:", context.Message()) 94 | 95 | msg := context.Message().(*actor.Terminated) 96 | //context.Unwatch(msg.Who)//需要主动unwatch??? 97 | path := msg.Who.String() 98 | 99 | sv := s.serviceAll[path] 100 | if sv == nil { 101 | log.Error("OnChildServiceTerminated,no found service:%v", path) 102 | return 103 | } 104 | delete(s.serviceAll, path) //移除索引 105 | 106 | var group *ServiceGroup 107 | if g, ok := s.serviceGroups[sv.serviceType]; !ok { 108 | group = g 109 | log.Error("OnChildServiceTerminated,no found service Type:%v", sv.serviceType) 110 | return 111 | } 112 | 113 | group.RemoveService(sv.serviceName) //移除group 114 | } 115 | 116 | //更新服务器 117 | func (s *CenterService) OnUpdateService(context service.Context) { 118 | log.Debug("center.OnUpdateService:%v", context.Message()) 119 | msg := context.Message().(*msgs.UploadService) 120 | 121 | if sv, ok := s.serviceAll[msg.ServiceName]; ok { 122 | sv.load = msg.Load 123 | sv.state = msg.State 124 | } 125 | } 126 | 127 | //获取一个服务器 128 | func (s *CenterService) OnApplyService(context service.Context) { 129 | log.Debug("center.OnApplyService:%v", context.Message()) 130 | msg := context.Message().(*msgs.ApplyService) 131 | var group *ServiceGroup 132 | if g, ok := s.serviceGroups[msg.ServiceType]; !ok { 133 | log.Error("OnApplyService,no found service Type:%v", msg.ServiceType) 134 | context.Sender().Tell(&msgs.ApplyServiceResult{Result: msgs.Error}) 135 | return 136 | } else { 137 | group = g 138 | } 139 | sv := group.GetBestService() 140 | resultMsg := &msgs.ApplyServiceResult{ServiceType: msg.ServiceType} 141 | if sv != nil { 142 | resultMsg.Result = msgs.OK 143 | resultMsg.Pid = sv.pid 144 | resultMsg.ServiceName = sv.serviceName 145 | resultMsg.Values = sv.values 146 | } else { 147 | resultMsg.Result = msgs.Fail 148 | log.Error("OnApplyService have no service:%v", msg.ServiceType) 149 | } 150 | context.Sender().Tell(resultMsg) 151 | } 152 | 153 | //获取一类服务器 154 | func (s *CenterService) GetTypeServices(context service.Context) { 155 | log.Debug("center.GetTypeServices:", context.Message()) 156 | msg := context.Message().(*msgs.GetTypeServices) 157 | var group *ServiceGroup 158 | if g, ok := s.serviceGroups[msg.ServiceType]; !ok { 159 | log.Error("GetTypeServices,no found service Type:%v", msg.ServiceType) 160 | context.Sender().Tell(&msgs.GetTypeServicesResult{}) 161 | return 162 | } else { 163 | group = g 164 | } 165 | 166 | resultMsg := &msgs.GetTypeServicesResult{} 167 | for _, v := range group.services { 168 | resultMsg.Pids = append(resultMsg.Pids, v.pid) 169 | } 170 | context.Sender().Tell(resultMsg) 171 | } 172 | -------------------------------------------------------------------------------- /src/Server/center/serviceNode.go: -------------------------------------------------------------------------------- 1 | package center 2 | 3 | import ( 4 | "gameproto/msgs" 5 | 6 | "github.com/AsynkronIT/protoactor-go/actor" 7 | ) 8 | 9 | //单个服务 10 | type ServiceNode struct { 11 | pid *actor.PID 12 | serviceName string 13 | serviceType string 14 | load uint32 //负载 15 | tmpload uint32 //临时负载(本地增加,防止同时大量请求导致都在一个服的问题) 16 | state msgs.ServiceState 17 | //data map[string]interface{} 18 | values []*msgs.ServiceValue //自定义属性 19 | } 20 | 21 | //更新服务 22 | func (node *ServiceNode) UpdateService(up msgs.UploadService) { 23 | node.load = up.Load 24 | node.state = up.State 25 | node.tmpload = 0 26 | } 27 | func (node *ServiceNode) GetServiceLoad() uint32 { 28 | return node.load + node.tmpload 29 | } 30 | 31 | //----------------------------------------------------------------------------------- 32 | //一组类型服务 33 | type ServiceGroup struct { 34 | services map[string]*ServiceNode 35 | } 36 | 37 | //获取最优服务 38 | func (sg *ServiceGroup) GetBestService() *ServiceNode { 39 | var best *ServiceNode 40 | for _, v := range sg.services { 41 | if best == nil || v.GetServiceLoad() < best.GetServiceLoad() { 42 | best = v 43 | } 44 | } 45 | return best 46 | } 47 | 48 | //添加服务 49 | func (sg *ServiceGroup) AddService(node *ServiceNode) { 50 | sg.services[node.serviceName] = node 51 | } 52 | 53 | //删除服务 54 | func (sg *ServiceGroup) RemoveService(serviceName string) { 55 | delete(sg.services, serviceName) 56 | } 57 | -------------------------------------------------------------------------------- /src/Server/cluster/cluster.go: -------------------------------------------------------------------------------- 1 | package cluster 2 | 3 | import ( 4 | "GAServer/config" 5 | "fmt" 6 | "sync" 7 | 8 | "github.com/AsynkronIT/protoactor-go/actor" 9 | ) 10 | 11 | //全局 12 | var ( 13 | remoteClients map[string]*RemoteClient //配置点 14 | mutex sync.Mutex 15 | ) 16 | 17 | type Clustermgr struct { 18 | } 19 | 20 | func New() *Clustermgr { 21 | return new(Clustermgr) 22 | } 23 | func (mgr *Clustermgr) OnInit() bool { 24 | remoteClients = make(map[string]*RemoteClient) 25 | 26 | if config.GetGlobleConfig().RemoteAddrs != nil { 27 | fmt.Println("remote:", config.GetGlobleConfig().RemoteAddrs) 28 | for serviceName, addr := range config.GetGlobleConfig().RemoteAddrs { 29 | createClient(addr, serviceName) 30 | } 31 | } 32 | return true 33 | } 34 | func (mgr *Clustermgr) Run() { 35 | 36 | } 37 | 38 | func (mgr *Clustermgr) OnDestroy() { 39 | } 40 | 41 | func GetServicePID(serviceName string) *RemoteClient { 42 | //todo:unsafe 频繁请求,可能有竞态,正式环境静态点要标明remote 43 | if client := remoteClients[serviceName]; client != nil { 44 | return client 45 | } else { 46 | addr := config.GetServiceAddress(serviceName) 47 | return createClient(addr, serviceName) 48 | } 49 | 50 | } 51 | 52 | func createClient(addr string, serviceName string) *RemoteClient { 53 | mutex.Lock() 54 | defer mutex.Unlock() 55 | fmt.Println("createClient:", serviceName, addr) 56 | r := &RemoteClient{} 57 | if addr != "" { 58 | r.pid = actor.NewPID(addr, serviceName) 59 | } else { 60 | r.pid = actor.NewLocalPID(serviceName) 61 | } 62 | remoteClients[serviceName] = r 63 | return r 64 | } 65 | 66 | func DisconnectService(serviceName string) { 67 | mutex.Lock() 68 | defer mutex.Unlock() 69 | 70 | if client := remoteClients[serviceName]; client != nil { 71 | delete(remoteClients, serviceName) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Server/cluster/regcenter.go: -------------------------------------------------------------------------------- 1 | package cluster 2 | 3 | import ( 4 | "GAServer/log" 5 | "GAServer/service" 6 | _ "encoding/json" 7 | "gameproto/msgs" 8 | ) 9 | 10 | //注册到center 11 | func RegServerToCenter(s *service.ServiceData, values []*msgs.ServiceValue) bool { 12 | log.Info("%v reg to center...", s.Name) 13 | 14 | msg := msgs.AddService{ 15 | ServiceName: s.Name, 16 | ServiceType: s.TypeName, 17 | Pid: s.GetPID(), 18 | Values: values} 19 | _, err := GetServicePID("center").Ask(&msg) 20 | if err != nil { 21 | log.Error("%v reg to center fail,%v", s.Name, err) 22 | //if err.Error() == "timeout" { 23 | //DisconnectService("center") 24 | //} 25 | //重连 26 | return false 27 | } 28 | log.Info("%v reg to center OK!", s.Name) 29 | return true 30 | } 31 | 32 | func RegServerWork(s *service.ServiceData, values []*msgs.ServiceValue) { 33 | go func() { 34 | for { 35 | if RegServerToCenter(s, values) { 36 | break 37 | } 38 | } 39 | }() 40 | 41 | } 42 | 43 | func UpdateServiceLoad(serviceName string, load uint32, state msgs.ServiceState) { 44 | log.Debug("%v UpdateServiceLoad %v-%v", serviceName, load, state) 45 | 46 | msg := msgs.UploadService{ 47 | ServiceName: serviceName, 48 | Load: load, 49 | State: state} 50 | GetServicePID("center").Tell(&msg) 51 | } 52 | -------------------------------------------------------------------------------- /src/Server/cluster/remoteclient.go: -------------------------------------------------------------------------------- 1 | package cluster 2 | 3 | import ( 4 | "log" 5 | "time" 6 | //"gameproto/msgs" 7 | //"GAServer/app" 8 | 9 | "github.com/AsynkronIT/protoactor-go/actor" 10 | //"github.com/AsynkronIT/protoactor-go/remote" 11 | ) 12 | 13 | type RemoteClient struct { 14 | pid *actor.PID 15 | usage string 16 | } 17 | 18 | //通知一条消息,立刻返回 19 | func (client *RemoteClient) Tell(args interface{}) { 20 | client.pid.Tell(args) 21 | } 22 | 23 | //通知一条消息,阻塞等待结果 24 | func (client *RemoteClient) Ask(args interface{}) (interface{}, error) { 25 | result, err := client.pid.RequestFuture(args, 3*time.Second).Result() 26 | if err != nil { 27 | log.Println("rpc ask fail:", err, " message:", args, " to ", client.usage) 28 | } 29 | return result, err 30 | } 31 | 32 | //通知一条信息,立刻返回,结果会放回recv通道 33 | func (client *RemoteClient) AskCB(args interface{}, respTo *actor.PID) { 34 | client.pid.Request(args, respTo) 35 | } 36 | 37 | func (client *RemoteClient) GetActorPID() *actor.PID { 38 | return client.pid 39 | } 40 | -------------------------------------------------------------------------------- /src/Server/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "GAServer/config" 5 | "encoding/json" 6 | "io/ioutil" 7 | ) 8 | 9 | type Config struct { 10 | Base config.ServiceConfig `json:"config"` 11 | DB map[string]string `json:"db"` 12 | DesignConfig map[string]string `json:"design"` 13 | Ver string `json:"ver"` 14 | } 15 | 16 | var appConfig *Config 17 | 18 | func LoadConfig(confPath string) (*Config, error) { 19 | if data, err := ioutil.ReadFile(confPath); err != nil { 20 | return nil, err 21 | } else { 22 | var conf = &Config{} 23 | err := json.Unmarshal(data, conf) 24 | appConfig = conf 25 | return conf, err 26 | } 27 | 28 | } 29 | 30 | func GetAppConf() *Config { 31 | return appConfig 32 | } 33 | -------------------------------------------------------------------------------- /src/Server/db/dbmgr.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | gdb "GAServer/db" 5 | "GAServer/log" 6 | "Server/config" 7 | ) 8 | 9 | var gameDB *gdb.DBClient 10 | 11 | type DBMgr struct { 12 | } 13 | 14 | func NewMgr() *DBMgr { 15 | return new(DBMgr) 16 | } 17 | func (mgr *DBMgr) OnInit() bool { 18 | //注册表结构 19 | gdb.RegDBModule(new(User)) 20 | //gdb.RegDBModule(new(Player)) 21 | 22 | //初始化连接 23 | if v, ok := config.GetAppConf().DB["game"]; ok { 24 | g, err := gdb.ConnectDB(v, "default") 25 | if err != nil { 26 | log.Error("load gamedb error:%v", err) 27 | return false 28 | } 29 | gameDB = g 30 | log.Info("load gamedb ok!") 31 | } 32 | //Testdb() 33 | return true 34 | } 35 | 36 | func Testdb() { 37 | p := Player{Id: 16, Name: "wwwggg", Exp: 1} 38 | _, err := GetGameDB().Insert(&p) 39 | if err != nil { 40 | log.Error("Insert err:%v", err.Error()) 41 | } 42 | } 43 | 44 | func (mgr *DBMgr) Run() { 45 | 46 | } 47 | 48 | func (mgr *DBMgr) OnDestroy() { 49 | } 50 | 51 | func GetGameDB() *gdb.DBClient { 52 | return gameDB 53 | } 54 | -------------------------------------------------------------------------------- /src/Server/db/gameMD.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | /*************注册数据库表结构**************/ 4 | //user 5 | type User struct { 6 | Id uint64 `orm:"column(uid)",auto` 7 | PlatformId string `orm:"column(platformId)"` 8 | RegisterTime int64 `orm:"column(registerTime)"` 9 | LastLoginTime int64 `orm:"column(lastLoginTime)"` 10 | LastLogoutTime int64 `orm:"column(lastLogoutTime)"` 11 | BlackTime int64 `orm:"column(blackTime)"` 12 | DeviceId string `orm:"column(deviceId)"` 13 | LoginDays int64 `orm:"column(loginDays)"` 14 | //`uid` int(11) NOT NULL AUTO_INCREMENT, 15 | //`platformId` varchar(255) CHARACTER SET utf8 NOT NULL, 16 | //`registerTime` int(15) NOT NULL DEFAULT '0', 17 | //`lastLoginTime` int(15) NOT NULL, 18 | //`lastLogoutTime` int(15) NOT NULL, 19 | //`blackTime` int(15) NOT NULL DEFAULT '0', 20 | //`deviceId` varchar(50) DEFAULT NULL, 21 | //`loginDays` int(5) NOT NULL DEFAULT '0', 22 | } 23 | 24 | //player 25 | type Player struct { 26 | Id uint64 `orm:"column(uid)",auto` 27 | Name string `orm:"column(username)"` 28 | Cgid int `orm:"column(cgId)"` 29 | Lv int `orm:"column(lv)"` 30 | Exp int `orm:"column(exp)"` 31 | Exptime int64 `orm:"column(expTime)"` 32 | } 33 | 34 | //wallet 35 | type Wallet struct { 36 | Id uint64 `orm:"column(uid)",auto` 37 | Rmb int64 `orm:"column(rmb)"` 38 | Gold int64 `orm:"column(gold)"` 39 | Ticket int64 `orm:"column(ticket)"` 40 | } 41 | 42 | //bag 43 | type Bag struct { 44 | Id uint64 `orm:"column(uid)",auto` 45 | ItemId int64 `orm:"column(itemId)"` 46 | ItemNum int64 `orm:"column(itemNum)"` 47 | } 48 | 49 | //ownCard 50 | type OwnCard struct { 51 | Id uint64 `orm:"column(uid)",auto` 52 | Cardid int64 `orm:"column(cardId)"` 53 | Cardnum int64 `orm:"column(cardNum)"` 54 | Gaintime int64 `orm:"column(gainTime)"` 55 | } 56 | 57 | //groupCard 58 | type GroupCard struct { 59 | Id uint64 `orm:"column(uid)",auto` 60 | Cardindex int64 `orm:"column(cardIndex)"` 61 | Jobid int16 `orm:"column(jobId)"` 62 | Cardname string `orm:"column(CardName)"` 63 | Cardlist string `orm:"column(cardList)"` 64 | Equiplist string `orm:"column(equipList)"` 65 | } 66 | 67 | //Hero 68 | type Favor struct { 69 | Id uint64 `orm:"column(uid)",auto` 70 | Heroid int32 `orm:"column(heroId)"` 71 | Lv int16 `orm:"column(lv)"` 72 | Exp int32 `orm:"column(exp)"` 73 | Usecount int32 `orm:"column(useCount)"` 74 | Stairwin int32 `orm:"column(stairWin)"` 75 | Arenawin int32 `orm:"column(arenaWin)"` 76 | Usecard int32 `orm:"column(useCars)"` 77 | Battleindex int32 `orm:"column(battleIndex)"` 78 | Usedcardlist string `orm:"column(usedCarsList)"` 79 | Lasttime int32 `orm:"column(lastTime)"` 80 | } 81 | 82 | //Draw 83 | type Draw struct { 84 | Id uint64 `orm:"column(uid)",auto` 85 | Drawid int32 `orm:"column(drawId)"` 86 | Drawnum string `orm:"column(drawNum)"` 87 | Drawtime int32 `orm:"column(drawTime)"` 88 | Tendrawtime int32 `orm:"column(tenDrawTime)"` 89 | Nextbetterdraw int32 `orm:"column(nextBetterDraw)"` 90 | Drawcount int32 `orm:"column(drawCount)"` 91 | Tenrdawcount int32 `orm:"column(tenDrawCount)"` 92 | } 93 | 94 | //MainQuest 95 | type Mainquset struct { 96 | Id uint64 `orm:"column(uid)",auto` 97 | GroupId int32 `orm:"column(GroupId)"` 98 | GroupNum int32 `orm:"column(GroupNumber)"` 99 | Num int32 `orm:"column(num)"` 100 | } 101 | -------------------------------------------------------------------------------- /src/Server/game/gameserver.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "GAServer/log" 5 | "GAServer/service" 6 | "GAServer/util" 7 | "Server/cluster" 8 | "gameproto/msgs" 9 | "reflect" 10 | "time" 11 | 12 | "github.com/AsynkronIT/protoactor-go/actor" 13 | _ "github.com/AsynkronIT/protoactor-go/actor" 14 | ) 15 | 16 | type GameService struct { 17 | service.ServiceData 18 | } 19 | 20 | type PlayerInitEnd struct { 21 | Result msgs.GAErrorCode 22 | BaseInfo *msgs.UserBaseInfo 23 | TransData *msgs.CreatePlayer 24 | Sender *actor.PID 25 | } 26 | 27 | //Service 获取服务对象 28 | func Service() service.IService { 29 | return new(GameService) 30 | } 31 | 32 | func Type() string { 33 | return "game" 34 | } 35 | 36 | //以下为接口函数 37 | func (s *GameService) OnReceive(context service.Context) { 38 | log.Debug("game.OnReceive:", context.Message()) 39 | 40 | } 41 | 42 | func (s *GameService) OnInit() { 43 | 44 | } 45 | 46 | func (s *GameService) OnStart(as *service.ActorService) { 47 | as.RegisterMsg(reflect.TypeOf(&msgs.CreatePlayer{}), s.OnCreatePlayer) //登录 48 | as.RegisterMsg(reflect.TypeOf(&msgs.Tick{}), s.OnTick) //定时任务 49 | as.RegisterMsg(reflect.TypeOf(&PlayerInitEnd{}), s.OnPlayerInitEnd) //玩家初始化完成 50 | //注册到center 51 | cluster.RegServerWork(&s.ServiceData, nil) 52 | //定时任务 53 | util.StartLoopTask(time.Second*5, func() { 54 | s.Pid.Tell(&msgs.Tick{}) //转主线程执行 55 | }) 56 | 57 | } 58 | func (s *GameService) OnTick(context service.Context) { 59 | load := len(context.Children()) 60 | cluster.UpdateServiceLoad(s.Name, uint32(load), msgs.ServiceStateFree) 61 | } 62 | 63 | //请求创建玩家 64 | func (s *GameService) OnCreatePlayer(context service.Context) { 65 | log.Info("GameService.OnCreatePlayer:%v\n%v", context.Message(), context.Sender()) 66 | msg := context.Message().(*msgs.CreatePlayer) 67 | 68 | //todo:从db里load基本数据(比如player表)... 69 | //baseInfo := &msgs.UserBaseInfo{Uid: msg.Uid, Name: "玩家" + strconv.Itoa(int(msg.Uid))} 70 | //创建玩家对象actor(异步) 71 | NewPlayer(msg.Uid, msg.AgentPID, msg, context) //异步载入完成才发回 72 | //player, err := NewPlayer(msg.Uid, msg.AgentPID, context) 73 | //player.baseInfo = baseInfo 74 | //errCode := msgs.OK 75 | //if err != nil { 76 | // log.Error("NewPlayer error:%v,%v", msg.Uid, err) 77 | // errCode = msgs.Error 78 | //} 79 | //result := &msgs.CreatePlayerResult{Result: errCode, BaseInfo: baseInfo, PlayerPID: player.selfPID, TransData: msg} 80 | //context.Tell(context.Sender(), result) 81 | 82 | log.Println("GameService.OnCreatePlayer now:", msg.Uid) 83 | } 84 | 85 | //玩家数据载入完成 86 | func (s *GameService) OnPlayerInitEnd(context service.Context) { 87 | msg := context.Message().(*PlayerInitEnd) 88 | result := &msgs.CreatePlayerResult{ 89 | Result: msg.Result, 90 | BaseInfo: msg.BaseInfo, 91 | PlayerPID: msg.Sender, 92 | TransData: msg.TransData} 93 | 94 | ss := cluster.GetServicePID("session") 95 | context.Tell(ss.GetActorPID(), result) 96 | log.Println("GameService.OnCreatePlayer ok:", msg.BaseInfo.Uid, msg.Sender) 97 | } 98 | -------------------------------------------------------------------------------- /src/Server/game/module_test.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "GAServer/db" 5 | "GAServer/log" 6 | "GAServer/messages" 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/astaxie/beego/orm" 11 | 12 | "github.com/gogo/protobuf/proto" 13 | ) 14 | 15 | type TestModule struct { 16 | PlayerModuleBase 17 | testv int 18 | } 19 | 20 | /*************注册数据库表结构**************/ 21 | 22 | //bag 23 | type Bag struct { 24 | Id int64 `orm:"column(uid)",auto` 25 | ItemId int64 26 | ItemNum int64 27 | } 28 | 29 | //ownCard 30 | type OwnCard struct { 31 | Id int64 `orm:"column(uid)",auto` 32 | Cardid int64 33 | Cardnum int64 34 | Gaintime int64 35 | } 36 | 37 | //groupCard 38 | type GroupCard struct { 39 | Id int64 `orm:"column(uid)",auto` 40 | Cardindex int64 41 | Jobid int16 42 | Cardname string 43 | Cardlist string 44 | Equiplist string 45 | } 46 | 47 | //Hero 48 | type Favor struct { 49 | Id int64 `orm:"column(uid)",auto` 50 | Heroid int32 `orm:"column(heroId)"` 51 | Lv int16 `orm:"column(lv)"` 52 | Exp int32 `orm:"column(exp)"` 53 | Usecount int32 `orm:"column(useCount)"` 54 | Stairwin int32 `orm:"column(stairWin)"` 55 | Arenawin int32 `orm:"column(arenaWin)"` 56 | Usecard int32 `orm:"column(useCars)"` 57 | Battleindex int32 `orm:"column(battleIndex)"` 58 | Usedcardlist string `orm:"column(usedCarsList)"` 59 | Lasttime int32 `orm:"column(lastTime)"` 60 | } 61 | 62 | //=================接口实现====================== 63 | func (m *TestModule) OnInit() { 64 | } 65 | 66 | func (m *TestModule) OnStart() {} 67 | func (m *TestModule) OnLoad() {} 68 | func (m *TestModule) OnTick() {} 69 | func (m *TestModule) OnSave() { 70 | if !m.isDataDirty { 71 | return 72 | } 73 | //save action here... 74 | 75 | } 76 | func (m *TestModule) OnDestory() {} 77 | 78 | //===============feature functions==================== 79 | func (m *TestModule) ShopBuy(data []byte) messages.GAErrorCode { 80 | return messages.OK 81 | } 82 | 83 | func (m *TestModule) ShopSell(data []byte) { 84 | 85 | } 86 | 87 | //发送shop消息到客户端 88 | func (m *TestModule) SendClientMsg(msgId messages.ShopMsgType, msg proto.Message) { 89 | m.player.SendClientMsg(messages.Shop, byte(msgId), msg) 90 | } 91 | 92 | func Test(t *testing.T) { 93 | orm.RegisterModel(new(Favor)) 94 | //连接数据库 95 | client, err := db.ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/tcg_new", "default") 96 | if err != nil { 97 | t.Error(err) 98 | return 99 | } 100 | m := new(PlayerHeroModule) 101 | m.OnInit() 102 | uid := 100024 103 | //私人卡组 104 | var favor []Favor 105 | sql := fmt.Sprintf("select * from favor where uid = ?") 106 | _, err1 := client.Raw(sql, uid).QueryRows(&favor) 107 | if err1 != nil { 108 | log.Error("Select favor err :", err1) 109 | } else { 110 | fmt.Printf("alldata is :%v\n", favor) 111 | for _, v := range favor { 112 | var hero Hero 113 | var herousecount HeroUseCount 114 | var herousecard HeroUseCard 115 | heroid := v.Heroid 116 | fmt.Printf("heroid is :%d\n", heroid) 117 | hero.lv = v.Lv 118 | hero.exp = v.Exp 119 | m._hero[heroid] = hero 120 | herousecount.usecount = v.Usecount 121 | herousecount.stairwin = v.Stairwin 122 | herousecount.arenawin = v.Arenawin 123 | herousecount.usecard = v.Usecard 124 | herousecount.battleindex = v.Battleindex 125 | m._heroUseCount[heroid] = herousecount 126 | herousecard.lasttime = v.Lasttime 127 | herousecard.usecardlist = String2map(v.Usedcardlist) 128 | m._heroUseCard[heroid] = herousecard 129 | } 130 | fmt.Printf("hero is:%v\n", m._hero) 131 | fmt.Printf("herocard is:%v\n", m._heroUseCard) 132 | fmt.Printf("herocount is:%v\n", m._heroUseCount) 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/Server/game/playerChatModule.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "GAServer/log" 5 | "gameproto/msgs" 6 | 7 | "github.com/gogo/protobuf/proto" 8 | ) 9 | 10 | type PlayerChatModule struct { 11 | PlayerModuleBase 12 | } 13 | 14 | //=================接口实现====================== 15 | func (m *PlayerChatModule) OnInit() { 16 | m.RegistCmd(uint32(msgs.C2S_PrivateChat), m.PrivateChat) 17 | m.RegistCmd(uint32(msgs.C2S_WorldChat), m.WorldChat) 18 | } 19 | 20 | //===============feature functions==================== 21 | func (m *PlayerChatModule) ShopBuy(data []byte) { 22 | //var msg msgs.C2S_ShopBuyMsg 23 | //proto.Unmarshal(data, &msg) 24 | //fmt.Println("test buy something:", msg) 25 | //m.SendClientMsg(msgs.S2C_ShopBuy, &msgs.S2C_ShopBuyMsg{ItemId: msg.ItemId, Result: msgs.OK}) 26 | } 27 | 28 | func (m *PlayerChatModule) PrivateChat(data []byte) { 29 | var msg msgs.C2S_PrivateChatMsg 30 | proto.Unmarshal(data, &msg) 31 | 32 | result := AskSession(&msgs.GetSessionInfoByName{msg.TargetName}) 33 | if result != nil { 34 | log.Info("AskSession PrivateChat ok:", result) 35 | ssInfo := result.(*msgs.GetSessionInfoResult) 36 | if ssInfo.Result == msgs.OK && ssInfo.AgentPID != nil { 37 | //找到玩家agent地址 38 | SendPlayerClientMsg(ssInfo.AgentPID, 39 | msgs.Chat, 40 | byte(msgs.S2C_PrivateOtherChat), 41 | &msgs.S2C_PrivateOtherChatMsg{SendName: m.player.GetName(), Msg: msg.Msg}) 42 | 43 | //通知自己 44 | m.SendClientMsg(msgs.S2C_PrivateChat, 45 | &msgs.S2C_PrivateChatMsg{TargetName: msg.TargetName, Msg: msg.Msg, Result: msgs.OK}) 46 | log.Info("send PrivateChat:", msg) 47 | } else { 48 | //没找到玩家 49 | m.SendClientMsg(msgs.S2C_PrivateChat, 50 | &msgs.S2C_PrivateChatMsg{Result: msgs.NoFoundTarget}) 51 | log.Info("send PrivateChat,no found:%v,%v", ssInfo.Result, msg) 52 | 53 | } 54 | } 55 | } 56 | 57 | func (m *PlayerChatModule) WorldChat(data []byte) { 58 | var msg msgs.C2S_WorldChatMsg 59 | proto.Unmarshal(data, &msg) 60 | 61 | SendWorldMsg(msgs.Chat, byte(msgs.S2C_WorldChat), 62 | &msgs.S2C_WorldChatMsg{SendName: m.player.GetName(), Msg: msg.Msg}) 63 | } 64 | 65 | //发送shop消息到客户端 66 | func (m *PlayerChatModule) SendClientMsg(msgId msgs.ChatMsgType, msg proto.Message) { 67 | m.player.SendClientMsg(msgs.Chat, byte(msgId), msg) 68 | } 69 | -------------------------------------------------------------------------------- /src/Server/game/playerModuleBase.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "gameproto/msgs" 5 | ) 6 | 7 | type IPlayerModule interface { 8 | //初始化 9 | OnInit() 10 | //载入数据 11 | OnLoad() 12 | //开始 13 | OnStart() 14 | //tick 15 | OnTick() 16 | //保存数据 17 | OnSave() 18 | //销毁 19 | OnDestory() 20 | 21 | //路由消息 22 | route(msg *msgs.FrameMsg) bool 23 | 24 | //初始化data 25 | initData(*Player) 26 | } 27 | 28 | type PlayerModuleBase struct { 29 | player *Player 30 | msgHandler map[uint32]MessageFunc 31 | isDataDirty bool 32 | } 33 | 34 | func (m *PlayerModuleBase) initData(p *Player) { 35 | m.msgHandler = make(map[uint32]MessageFunc) 36 | m.player = p 37 | } 38 | 39 | //RegistCmd 注册消息 40 | func (m *PlayerModuleBase) RegistCmd(opcode uint32, fun MessageFunc) { 41 | m.msgHandler[opcode] = fun 42 | } 43 | 44 | //设置脏数据,等待异步写 45 | func (m *PlayerModuleBase) SetDataDirty() { 46 | m.isDataDirty = true 47 | m.player.SetDataDirty() 48 | } 49 | 50 | //接口函数 51 | func (m *PlayerModuleBase) route(msg *msgs.FrameMsg) bool { 52 | if fun, ok := m.msgHandler[msg.MsgId]; ok { 53 | fun(msg.RawData) 54 | return true 55 | } 56 | return false 57 | } 58 | 59 | func (m *PlayerModuleBase) OnInit() {} 60 | func (m *PlayerModuleBase) OnStart() {} 61 | func (m *PlayerModuleBase) OnLoad() {} 62 | func (m *PlayerModuleBase) OnTick() {} 63 | func (m *PlayerModuleBase) OnSave() {} 64 | func (m *PlayerModuleBase) OnDestory() {} 65 | -------------------------------------------------------------------------------- /src/Server/game/playerShopModule.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | _ "fmt" 5 | "gameproto" 6 | "gameproto/msgs" 7 | ) 8 | 9 | type PlayerShopModule struct { 10 | PlayerModuleBase 11 | testv int 12 | } 13 | 14 | //=================接口实现====================== 15 | func (m *PlayerShopModule) OnInit() { 16 | //m.RegistCmd(uint32(msgs.C2S_ShopBuy), m.ShopBuy) 17 | //m.RegistCmd(uint32(msgs.C2S_ShopSell), m.ShopSell) 18 | m.player.RegistCmd(gameproto.C2S_Test, m.ShopBuy) 19 | } 20 | 21 | func (m *PlayerShopModule) OnStart() {} 22 | func (m *PlayerShopModule) OnLoad() {} 23 | func (m *PlayerShopModule) OnTick() {} 24 | func (m *PlayerShopModule) OnSave() { 25 | if !m.isDataDirty { 26 | return 27 | } 28 | //save action here... 29 | 30 | } 31 | func (m *PlayerShopModule) OnDestory() {} 32 | 33 | //===============feature functions==================== 34 | func (m *PlayerShopModule) ShopBuy(data []byte) msgs.GAErrorCode { 35 | //var msg gameproto.S2C_SHOP_CARD_INFO 36 | //proto.Unmarshal(data, &msg) 37 | //m.SendClientMsg(msgs.S2C_ShopBuy, &msgs.S2C_ShopBuyMsg{ItemId: msg.ItemId, Result: msgs.OK}) 38 | m.player.SendGameMsg(gameproto.S2C_Test, &gameproto.S2C_TestMsg{Id: 10}) 39 | //m.testv++ 40 | //log.Println("test buy something:", msg, m.testv) 41 | //if m.testv == 10 { 42 | // m.player.ActiveLive() 43 | //} 44 | return msgs.OK 45 | } 46 | 47 | func (m *PlayerShopModule) ShopSell(data []byte) { 48 | 49 | } 50 | 51 | //发送shop消息到客户端 52 | //func (m *PlayerShopModule) SendClientMsg(msgId msgs.ShopMsgType, msg proto.Message) { 53 | // m.player.SendClientMsg(msgs.Shop, byte(msgId), msg) 54 | //} 55 | -------------------------------------------------------------------------------- /src/Server/gate/agentActor.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | gfw "GAServer/gateframework" 5 | "GAServer/log" 6 | "Server/cluster" 7 | "errors" 8 | "gameproto" 9 | "gameproto/msgs" 10 | 11 | "time" 12 | 13 | "github.com/AsynkronIT/protoactor-go/actor" 14 | "github.com/gogo/protobuf/proto" 15 | ) 16 | 17 | type AgentActor struct { 18 | key string 19 | verified bool 20 | bindAgent gfw.Agent 21 | pid *actor.PID 22 | parentPid *actor.PID 23 | baseInfo *msgs.UserBaseInfo 24 | bindServers []*msgs.UserBindServer 25 | wantDead bool 26 | } 27 | 28 | func NewAgentActor(ag gfw.Agent, parentPid *actor.PID) *AgentActor { 29 | //创建actor 30 | //r, err := parentPid.RequestFuture(&msgs.NewChild{}, 3*time.Second).Result() 31 | ab := &AgentActor{verified: false, bindAgent: ag} 32 | pid := actor.Spawn(actor.FromInstance(ab)) 33 | //pid, err := actor.SpawnWithParent(actor.FromInstance(ab), parentPid) 34 | //if err != nil { 35 | // log.Println("SpawnNamed agent actor error:", err) 36 | // return nil 37 | //} 38 | 39 | //pid := r.(msgs.NewChildResult).Pid 40 | ab.pid = pid 41 | ab.parentPid = parentPid 42 | log.Println("new agent actor:", pid, " parent:", parentPid) 43 | return ab 44 | } 45 | 46 | //外部调用tell 47 | func (ab *AgentActor) Tell(msg proto.Message) { 48 | 49 | } 50 | 51 | //收到后端消息 52 | func (ab *AgentActor) Receive(context actor.Context) { 53 | //log.Println("agent.ReceviceServerMsg:", reflect.TypeOf(context.Message())) 54 | switch msg := context.Message().(type) { 55 | case *msgs.Kick: 56 | ab.OnStop() 57 | //todo:not safe 58 | ab.bindAgent.SetDead() //被动死亡,防止二次关闭 59 | ab.bindAgent.Close() //关闭连接 60 | case *msgs.ClientDisconnect: 61 | //上报 62 | if ab.baseInfo != nil { 63 | ss := cluster.GetServicePID("session") 64 | ss.Tell(&msgs.UserLeave{Uid: ab.baseInfo.Uid, From: msgs.ST_GateServer, Reason: "client disconnect"}) 65 | } 66 | ab.OnStop() 67 | context.Self().Stop() 68 | case *msgs.ReceviceClientMsg: 69 | //收到客户端消息 70 | ab.ReceviceClientMsg(msg.Rawdata) 71 | case *msgs.FrameMsg: 72 | //log.Println("ReceviceServer:", msg) 73 | pack := new(NetPack) 74 | pack.channel = msg.Channel 75 | pack.msgID = byte(msg.MsgId) 76 | pack.rawData = msg.RawData 77 | ab.SendClientPack(pack) 78 | } 79 | } 80 | 81 | func (ab *AgentActor) GetChannelServer(channel msgs.ChannelType) *actor.PID { 82 | c := msgs.ChannelType(int(channel) / 100 * 100) //简单对应 83 | //log.Info("GetChannelServer,%v,%v", channel, c) 84 | if ab.bindServers == nil { 85 | return nil 86 | } 87 | for _, v := range ab.bindServers { 88 | //log.Info("try GetChannelServer,%v", v.Channel) 89 | if v.Channel == c { 90 | return v.GetPid() 91 | } 92 | } 93 | return nil 94 | } 95 | 96 | //收到前端消息 97 | func (ab *AgentActor) ReceviceClientMsg(data []byte) error { 98 | //log.Println("ReceviceClientMsg:", len(data)) 99 | pack := new(NetPack) 100 | if !pack.Read(data) { 101 | log.Error("AgentActor recv too short:", data) 102 | return errors.New("AgentActor recv too short") 103 | } 104 | //心跳包 105 | channel := msgs.ChannelType(pack.channel) 106 | if channel == msgs.Heartbeat { 107 | ab.SendClientPack(pack) 108 | return nil 109 | } 110 | 111 | //认证 112 | if !ab.verified { 113 | return ab.CheckLogin(pack) 114 | } 115 | 116 | //转发 117 | return ab.forward(pack) 118 | } 119 | 120 | //验证消息 121 | func (ab *AgentActor) CheckLogin(pack *NetPack) error { 122 | log.Info("checklogin....") 123 | msg := gameproto.PlatformUser{} 124 | err := proto.Unmarshal(pack.rawData, &msg) 125 | if err != nil { 126 | log.Error("CheckLogin fail:%v,msgid:%d", err, pack.msgID) 127 | return err 128 | } 129 | pretime := time.Now() 130 | smsg := &msgs.ServerCheckLogin{Uid: uint64(msg.PlatformUid), Key: msg.Key, AgentPID: ab.pid} 131 | //frame := &msgs.FrameMsg{msgs.ChannelType(channel), uint32(msgid), data[2:]} 132 | result, err := cluster.GetServicePID("session").Ask(smsg) 133 | if err == nil { 134 | checkResult := result.(*msgs.CheckLoginResult) 135 | if checkResult.Result == msgs.OK { 136 | //登录成功 137 | usetime := time.Now().Sub(pretime) 138 | log.Info("CheckLogin success:%v,time:%v", checkResult, usetime.Seconds()) 139 | ab.baseInfo = checkResult.BaseInfo 140 | ab.bindServers = checkResult.BindServers 141 | ab.verified = true 142 | ab.parentPid.Tell(&msgs.AddAgentToParent{Uid: checkResult.BaseInfo.Uid, Sender: ab.pid}) 143 | } else { 144 | log.Println("###CheckLogin fail:", checkResult) 145 | } 146 | 147 | ret := &gameproto.LoginReturn{ErrCode: int32(checkResult.Result), ServerTime: int32(time.Now().Unix())} 148 | ab.SendClient(msgs.Login, byte(gameproto.S2C_LOGIN_END), ret) 149 | 150 | } else { 151 | log.Error("CheckLogin error :" + err.Error()) 152 | } 153 | 154 | return nil 155 | } 156 | 157 | //发送消息到客户端 158 | func (ab *AgentActor) SendClient(c msgs.ChannelType, msgId byte, msg proto.Message) { 159 | pack := new(NetPack) 160 | pack.channel = c 161 | pack.msgID = msgId 162 | mdata, err := proto.Marshal(msg) 163 | if err != nil { 164 | log.Error("SendClient marshal error:%v", err) 165 | return 166 | } 167 | pack.rawData = mdata 168 | //log.Info("sendclient:msg%v,data:%d=>%v", pack.msgID, len(pack.rawData), pack.rawData) 169 | ab.SendClientPack(pack) 170 | } 171 | 172 | //func (ab *AgentActor) SendClientRaw(c msgs.ChannelType, msgId byte, mdata []byte) { 173 | // data := []byte{byte(c), msgId} 174 | // data = append(data, mdata...) 175 | // ab.bindAgent.WriteMsg(data) 176 | //} 177 | 178 | func (ab *AgentActor) SendClientPack(pack *NetPack) { 179 | data := pack.Write() 180 | ab.bindAgent.WriteMsg(data) 181 | } 182 | 183 | //转发 184 | func (ab *AgentActor) forward(pack *NetPack) error { 185 | channel := pack.channel 186 | msgid := pack.msgID 187 | //test gate 188 | //if channel == byte(msgs.Shop) { 189 | // ab.SendClient(msgs.Shop, byte(msgs.S2C_ShopBuy), &msgs.S2C_ShopBuyMsg{ItemId: 1, Result: msgs.OK}) 190 | // return nil 191 | //} 192 | 193 | pid := ab.GetChannelServer(channel) 194 | if pid == nil { 195 | log.Error("forward server nil:%+v,c=%v,m=%v", pid, channel, msgid) 196 | return nil 197 | } 198 | 199 | frame := &msgs.FrameMsg{channel, uint32(msgid), pack.rawData} 200 | pid.Tell(frame) 201 | //r, e := pid.RequestFuture(frame, time.Second*3).Result() 202 | //if e != nil { 203 | // log.Error("forward error:id=%v, err=%v", ab.baseInfo.Uid, e) 204 | //} 205 | 206 | //rep := r.(*msgs.FrameMsgRep) 207 | //repMsg := &gameproto.S2C_ConfirmInfo{MsgHead: int32(msgid), Code: int32(rep.ErrCode)} 208 | //ab.SendClient(msgs.GameServer, byte(gameproto.S2C_CONFIRM), repMsg) 209 | return nil 210 | } 211 | 212 | func (ab *AgentActor) OnStop() { 213 | if ab.verified && ab.baseInfo != nil { 214 | ab.parentPid.Tell(&msgs.RemoveAgentFromParent{Uid: ab.baseInfo.Uid}) 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/Server/gate/gameproto.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "gameproto/msgs" 5 | ) 6 | 7 | //标志位 8 | const ( 9 | NetPackFLag_Encode byte = 1 10 | NetPackFLag_Compress byte = 2 11 | ) 12 | 13 | type NetPack struct { 14 | channel msgs.ChannelType //主消息通道 15 | msgID byte //消息id 16 | cno byte //客户端请求号 17 | flag byte //压缩,加密等表示 18 | 19 | rawData []byte //数据段 20 | } 21 | 22 | func (pk *NetPack) Read(p []byte) bool { 23 | if len(p) < 3 { 24 | return false 25 | } 26 | pk.channel = msgs.GameServer 27 | pk.msgID = p[0] 28 | pk.cno = p[1] 29 | pk.flag = p[2] 30 | pk.rawData = p[3:] 31 | return true 32 | } 33 | 34 | func (pk *NetPack) Write() []byte { 35 | data := []byte{pk.msgID, pk.cno, pk.flag} 36 | data = append(data, pk.rawData...) 37 | return data 38 | } 39 | 40 | //加密 41 | func (pk *NetPack) IsEncode() bool { 42 | return (pk.flag & NetPackFLag_Encode) > 0 43 | } 44 | 45 | //加密 46 | func (pk *NetPack) IsCompress() bool { 47 | return (pk.flag & NetPackFLag_Compress) > 0 48 | } 49 | -------------------------------------------------------------------------------- /src/Server/gate/gateserver.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "GAServer/config" 5 | gfw "GAServer/gateframework" 6 | "GAServer/log" 7 | "GAServer/service" 8 | "GAServer/util" 9 | "Server/cluster" 10 | "gameproto/msgs" 11 | 12 | "reflect" 13 | "time" 14 | 15 | "github.com/AsynkronIT/protoactor-go/actor" 16 | ) 17 | 18 | type GateService struct { 19 | service.ServiceData 20 | agents map[uint64]*actor.PID 21 | actorchan chan *AgentActor //传说创建actor 22 | } 23 | 24 | //Service 获取服务对象 25 | func Service() service.IService { 26 | return new(GateService) 27 | } 28 | 29 | func Type() string { 30 | return "gate" 31 | } 32 | 33 | //以下为接口函数 34 | func (s *GateService) OnReceive(context service.Context) { 35 | log.Debug("GateService.OnReceive:", context.Message()) 36 | switch msg := context.Message().(type) { 37 | 38 | case *msgs.AddAgentToParent: 39 | log.Info("msgs.AddAgentToParent%v", msg.Uid) 40 | //子对象注册 41 | s.agents[msg.Uid] = msg.Sender 42 | case *msgs.RemoveAgentFromParent: 43 | log.Info("msgs.RemoveAgentFromParent%v", msg.Uid) 44 | delete(s.agents, msg.Uid) 45 | case *msgs.NewChild: 46 | //创建子节点 47 | ab := &AgentActor{verified: false} 48 | pid := context.Spawn(actor.FromInstance(ab)) 49 | ab.pid = pid 50 | ab.parentPid = context.Self() 51 | //context.Sender().Tell(&msgs.NewChildResult{Pid: pid}) 52 | s.actorchan <- ab 53 | case *msgs.UnicastFrameMsg: 54 | //单todo:... 55 | log.Println("gate.UnicastFrameMsg:", msg) 56 | 57 | case *msgs.MulticastFrameMsg: 58 | //组todo:... 59 | log.Println("gate.UnicastFrameMsg:", msg) 60 | 61 | case *msgs.BroadcastFrameMsg: 62 | //广播 63 | log.Println("gate.BroadcastFrameMsg:", msg, " child:", len(s.agents)) 64 | //children := context.Children() 65 | for _, child := range s.agents { 66 | log.Println("send agent:", child) 67 | child.Tell(msg.FrameMsg) 68 | } 69 | } 70 | } 71 | func (s *GateService) OnInit() { 72 | s.agents = make(map[uint64]*actor.PID) 73 | s.actorchan = make(chan *AgentActor) 74 | } 75 | 76 | func (s *GateService) OnStart(as *service.ActorService) { 77 | //as.RegisterMsg(reflect.TypeOf(&msgs.UserLogin{}), s.OnUserLogin) //注册登录 78 | as.RegisterMsg(reflect.TypeOf(&msgs.Tick{}), s.OnTick) //定时任务 79 | as.RegisterMsg(reflect.TypeOf(&msgs.Kick{}), s.OnKick) //踢人 80 | 81 | log.Println("gate start") 82 | gate := &gfw.Gate{ 83 | MaxConnNum: config.GetServiceConfigInt(s.Name, "MaxConnNum"), 84 | PendingWriteNum: 1024, 85 | MaxMsgLen: 65535, 86 | WSAddr: config.GetServiceConfigString(s.Name, "WsAddr"), 87 | HTTPTimeout: 5, 88 | CertFile: "", 89 | KeyFile: "", 90 | TCPAddr: config.GetServiceConfigString(s.Name, "TcpAddr"), 91 | LenMsgLen: 2, 92 | LittleEndian: true, 93 | Processor: nil, //msg.Processor, 94 | //AgentChanRPC: nil, //game.ChanRPC, 95 | } 96 | 97 | gate.Run(s) 98 | 99 | //注册 100 | val := &msgs.ServiceValue{"TcpAddr", config.GetServiceConfigString(s.Name, "TcpAddr")} 101 | cluster.RegServerWork(&s.ServiceData, []*msgs.ServiceValue{val}) 102 | //定时任务 103 | util.StartLoopTask(time.Second*5, func() { 104 | s.Pid.Tell(&msgs.Tick{}) //转主线程执行 105 | }) 106 | } 107 | 108 | func (s *GateService) OnTick(context service.Context) { 109 | load := len(s.agents) 110 | cluster.UpdateServiceLoad(s.Name, uint32(load), msgs.ServiceStateFree) 111 | } 112 | 113 | func (s *GateService) OnKick(context service.Context) { 114 | msg := context.Message().(*msgs.Kick) 115 | log.Info("GateService.OnKick:%v", msg) 116 | if agent, ok := s.agents[msg.Uid]; ok { 117 | agent.Tell(&msgs.Kick{Uid: msg.Uid}) 118 | } 119 | } 120 | 121 | func (s *GateService) OnDestory() { 122 | 123 | } 124 | 125 | //创建agentactor,外部线程调用.....not very safe... 126 | func (s *GateService) GetAgentActor(a gfw.Agent) *actor.PID { 127 | s.Pid.Tell(new(msgs.NewChild)) //请求一个actor 128 | agentActor := <-s.actorchan 129 | agentActor.bindAgent = a 130 | return agentActor.pid 131 | } 132 | -------------------------------------------------------------------------------- /src/Server/login/loginserver.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "GAServer/config" 5 | "GAServer/log" 6 | "GAServer/service" 7 | "Server/cluster" 8 | "fmt" 9 | "gameproto/msgs" 10 | "net/http" 11 | 12 | _ "Server/db" 13 | "gameproto" 14 | 15 | "strconv" 16 | "strings" 17 | _ "time" 18 | 19 | "github.com/gogo/protobuf/proto" 20 | ) 21 | 22 | type LoginService struct { 23 | service.ServiceData 24 | } 25 | 26 | //Service 获取服务对象 27 | func Service() service.IService { 28 | return new(LoginService) 29 | } 30 | 31 | func Type() string { 32 | return "login" 33 | } 34 | 35 | //以下为接口函数 36 | func (s *LoginService) OnReceive(context service.Context) { 37 | fmt.Println("center.OnReceive:", context.Message()) 38 | } 39 | func (s *LoginService) OnInit() { 40 | 41 | } 42 | 43 | func (s *LoginService) OnStart(as *service.ActorService) { 44 | //as.RegisterMsg(reflect.TypeOf(&messages.UserLogin{}), s.OnUserLogin) //注册登录 45 | 46 | //开启rpc,任意端口 47 | //remote.Start("127.0.0.1:0") 48 | //cluster.Start(&cluster.ClusterConfig{"127.0.0.1:8090", "127.0.0.1:8091"}) 49 | 50 | go func() { 51 | //开启http服务 52 | http.HandleFunc("/login", login) 53 | 54 | httpAddr := config.GetServiceConfigString(s.Name, "httpAddr") 55 | log.Println("login listen http:", s.Name, " ", httpAddr) 56 | http.ListenAndServe(httpAddr, nil) 57 | }() 58 | 59 | } 60 | 61 | func login(w http.ResponseWriter, req *http.Request) { 62 | req.ParseForm() 63 | if req.Form["a"] == nil || req.Form["p"] == nil { 64 | log.Error("a,p is empty:", req.Form) 65 | return 66 | } 67 | //账号 68 | acc := "" 69 | if al, ok := req.Form["a"]; ok { 70 | acc = al[0] 71 | } 72 | //pwd := "" 73 | //if pl, ok := req.Form["i"]; ok { 74 | // pwd = pl[0] 75 | //} 76 | 77 | //验证 here... 78 | log.Println("login account:", acc) 79 | strs := strings.Split(acc, "_") 80 | id, _ := strconv.Atoi(strs[1]) 81 | //now := time.Now().Unix() 82 | //user := &db.User{PlatformId: acc, LastLoginTime: now} 83 | //var id uint64 84 | //norow, e := db.GetGameDB().Read(user, "PlatformId") 85 | //if e != nil && !norow { 86 | // loginBackError(w, e) 87 | // return 88 | //} 89 | 90 | //user.LastLoginTime = now 91 | //if norow { 92 | //新用户ErrNoRows 93 | // user.RegisterTime = now 94 | // db.GetGameDB().Insert(user) 95 | //} else { 96 | //老用户 97 | // db.GetGameDB().Update(user, "LastLoginTime") 98 | //} 99 | 100 | //id = user.Id 101 | 102 | resp, err := cluster.GetServicePID("session").Ask(&msgs.UserLogin{acc, uint64(id)}) 103 | if err == nil { 104 | var s, _ = resp.(*gameproto.UserLoginResult).Marshal() 105 | //var s, _ = json.Marshal(resp) 106 | w.Write(s) 107 | log.Info("login ok:msg=%v", resp) 108 | } else { 109 | loginBackError(w, err) 110 | log.Println("login error:", acc, err) 111 | } 112 | } 113 | 114 | func loginBackError(w http.ResponseWriter, e error) { 115 | log.Error("create user db :%v", e) 116 | d, _ := proto.Marshal(&gameproto.UserLoginResult{Result: int32(msgs.Error)}) 117 | w.Write(d) 118 | } 119 | -------------------------------------------------------------------------------- /src/Server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "GAServer/app" 5 | "Server/center" 6 | "Server/cluster" 7 | "Server/config" 8 | "Server/db" 9 | "Server/game" 10 | "Server/gate" 11 | "Server/login" 12 | "Server/session" 13 | "flag" 14 | "log" 15 | //"GAServer/login" 16 | //logr "github.com/Sirupsen/logrus" 17 | //logr "GAServer/log" 18 | ) 19 | 20 | var ( 21 | confPath = flag.String("config", "config.json", "配置文件") 22 | ) 23 | 24 | func main() { 25 | flag.Parse() 26 | conf, err := config.LoadConfig(*confPath) 27 | if err != nil { 28 | log.Println("load config err:", err) 29 | return 30 | } 31 | app.RegisterService(center.Type(), center.Service) 32 | app.RegisterService(session.Type(), session.Service) 33 | app.RegisterService(login.Type(), login.Service) 34 | app.RegisterService(gate.Type(), gate.Service) 35 | app.RegisterService(game.Type(), game.Service) 36 | log.Println("===Run===", conf) 37 | app.Run(&conf.Base, cluster.New(), db.NewMgr()) 38 | log.Println("===GameOver===") 39 | } 40 | -------------------------------------------------------------------------------- /src/Server/session/UnloginData.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "GAServer/data-structures/queue" 5 | "time" 6 | ) 7 | 8 | type UnloginData struct { 9 | uid uint64 10 | key string 11 | deadline time.Time 12 | userdata interface{} 13 | } 14 | 15 | type UnloginDataMgr struct { 16 | dataMap map[uint64]*UnloginData 17 | q *queue.Queue 18 | deadTime time.Duration 19 | } 20 | 21 | func NewUnloginDataMgr(deadtime time.Duration) *UnloginDataMgr { 22 | mgr := &UnloginDataMgr{} 23 | mgr.dataMap = make(map[uint64]*UnloginData) 24 | mgr.q = queue.New() 25 | mgr.deadTime = deadtime 26 | return mgr 27 | } 28 | 29 | func (mgr *UnloginDataMgr) Push(uid uint64, key string, userdata interface{}) { 30 | data := &UnloginData{uid: uid, key: key, deadline: time.Now().Add(mgr.deadTime), userdata: userdata} 31 | mgr.q.Push(data) 32 | mgr.dataMap[uid] = data 33 | } 34 | 35 | func (mgr *UnloginDataMgr) Tick(now time.Time) { 36 | 37 | for { 38 | if mgr.q.Len() < 1 { 39 | break 40 | } 41 | head := mgr.q.Peek().(*UnloginData) 42 | if now.After(head.deadline) { 43 | mgr.q.Pop() 44 | delete(mgr.dataMap, head.uid) 45 | } else { 46 | break 47 | } 48 | } 49 | } 50 | 51 | func (mgr *UnloginDataMgr) Get(uid uint64) *UnloginData { 52 | return mgr.dataMap[uid] 53 | } 54 | 55 | func (mgr *UnloginDataMgr) Remove(data *UnloginData) { 56 | delete(mgr.dataMap, data.uid) 57 | f := func(o interface{}) bool { 58 | return o.(*UnloginData).uid == data.uid 59 | } 60 | mgr.q.PopRule(f) 61 | } 62 | -------------------------------------------------------------------------------- /src/Server/session/playerSession.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "gameproto/msgs" 5 | 6 | "github.com/AsynkronIT/protoactor-go/actor" 7 | ) 8 | 9 | type PlayerSession struct { 10 | userInfo *msgs.UserBaseInfo 11 | gatePid *actor.PID //gate服地址 12 | agentPid *actor.PID //agent对象地址 13 | gamePlayerPid *actor.PID //player对象地址 14 | 15 | key string //动态生成密码 16 | } 17 | 18 | //踢下线 19 | func (p *PlayerSession) Kick(reason string, ignServer msgs.ServerType) { 20 | msg := &msgs.Kick{Uid: p.userInfo.Uid, Reason: reason} 21 | if ignServer != msgs.ST_GateServer && p.agentPid != nil { 22 | p.agentPid.Tell(msg) 23 | } 24 | if ignServer != msgs.ST_GameServer && p.gamePlayerPid != nil { 25 | p.gamePlayerPid.Tell(msg) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Server/session/sessionManager.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | type SessionManager struct { 4 | players map[uint64]*PlayerSession 5 | name2players map[string]*PlayerSession //名字索引 6 | } 7 | 8 | func NewSessionManager() *SessionManager { 9 | sm := new(SessionManager) 10 | sm.players = make(map[uint64]*PlayerSession) 11 | sm.name2players = make(map[string]*PlayerSession) 12 | return sm 13 | } 14 | 15 | func (mgr *SessionManager) AddSession(session *PlayerSession) { 16 | mgr.players[session.userInfo.Uid] = session 17 | mgr.name2players[session.userInfo.Name] = session 18 | } 19 | 20 | func (mgr *SessionManager) GetSession(uid uint64) *PlayerSession { 21 | return mgr.players[uid] 22 | } 23 | func (mgr *SessionManager) GetSessionByName(name string) *PlayerSession { 24 | return mgr.name2players[name] 25 | } 26 | func (mgr *SessionManager) RemoveSession(uid uint64) *PlayerSession { 27 | ss := mgr.GetSession(uid) 28 | delete(mgr.players, uid) 29 | if ss != nil { 30 | delete(mgr.name2players, ss.userInfo.Name) 31 | } 32 | return ss 33 | } 34 | -------------------------------------------------------------------------------- /src/Server/session/session_test.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestUnloginData(t *testing.T) { 10 | mgr := NewUnloginDataMgr(time.Second * 3) 11 | mgr.Push(1, "1") 12 | time.Sleep(time.Second) 13 | mgr.Push(2, "2") 14 | time.Sleep(time.Second) 15 | mgr.Push(3, "3") 16 | mgr.Push(4, "4") 17 | for index := 0; index < 5; index++ { 18 | mgr.Tick(time.Now()) 19 | time.Sleep(time.Second) 20 | fmt.Printf("run %d,len=%d\n", index, mgr.q.Len()) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Server/session/sessionserver.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "GAServer/log" 5 | "GAServer/service" 6 | "Server/cluster" 7 | "fmt" 8 | "gameproto" 9 | "gameproto/msgs" 10 | "reflect" 11 | "time" 12 | ) 13 | 14 | type SessionService struct { 15 | service.ServiceData 16 | unlogiinDataMgr *UnloginDataMgr 17 | sessionMgr *SessionManager 18 | } 19 | 20 | //Service 获取服务对象 21 | func Service() service.IService { 22 | return new(SessionService) 23 | } 24 | 25 | func Type() string { 26 | return "session" 27 | } 28 | 29 | //以下为接口函数 30 | func (s *SessionService) OnReceive(context service.Context) { 31 | fmt.Println("session.OnReceive:", context.Message()) 32 | } 33 | 34 | func (s *SessionService) OnInit() { 35 | s.sessionMgr = NewSessionManager() 36 | s.unlogiinDataMgr = NewUnloginDataMgr(time.Second * 3) 37 | } 38 | 39 | func (s *SessionService) OnStart(as *service.ActorService) { 40 | as.RegisterMsg(reflect.TypeOf(&msgs.UserLogin{}), s.OnUserLogin) //注册登录 41 | as.RegisterMsg(reflect.TypeOf(&msgs.ServerCheckLogin{}), s.OnUserCheckLogin) //二次验证 42 | as.RegisterMsg(reflect.TypeOf(&msgs.CreatePlayerResult{}), s.OnUserCheckLoginGsBack) //二次验证gs返回 43 | as.RegisterMsg(reflect.TypeOf(&msgs.GetSessionInfo{}), s.GetSessionInfo) //查询玩家信息 44 | as.RegisterMsg(reflect.TypeOf(&msgs.GetSessionInfoByName{}), s.GetSessionInfoByName) //查询玩家信息通过名字 45 | as.RegisterMsg(reflect.TypeOf(&msgs.UserLeave{}), s.OnUserLeave) //玩家掉线 46 | 47 | } 48 | 49 | //查询玩家信息 50 | func (s *SessionService) GetSessionInfo(context service.Context) { 51 | fmt.Println("SessionService.GetSessionInfo:", context.Message()) 52 | msg := context.Message().(*msgs.GetSessionInfo) 53 | ss := s.sessionMgr.GetSession(msg.Uid) 54 | if ss != nil { 55 | context.Tell(context.Sender(), &msgs.GetSessionInfoResult{Result: msgs.OK, UserInfo: ss.userInfo, AgentPID: ss.agentPid}) 56 | } else { 57 | context.Tell(context.Sender(), &msgs.GetSessionInfoResult{Result: msgs.Fail}) 58 | } 59 | } 60 | 61 | //查询玩家信息 by name 62 | func (s *SessionService) GetSessionInfoByName(context service.Context) { 63 | fmt.Println("SessionService.GetSessionInfoByName:", context.Message()) 64 | msg := context.Message().(*msgs.GetSessionInfoByName) 65 | ss := s.sessionMgr.GetSessionByName(msg.Name) 66 | if ss != nil { 67 | context.Tell(context.Sender(), &msgs.GetSessionInfoResult{Result: msgs.OK, UserInfo: ss.userInfo, AgentPID: ss.agentPid}) 68 | } else { 69 | context.Tell(context.Sender(), &msgs.GetSessionInfoResult{Result: msgs.Fail}) 70 | } 71 | fmt.Println("GetSessionInfoByName end") 72 | } 73 | 74 | //玩家登陆 75 | func (s *SessionService) OnUserLogin(context service.Context) { 76 | fmt.Println("SessionService.OnUserLogin:", context.Message()) 77 | msg := context.Message().(*msgs.UserLogin) 78 | 79 | //踢掉老玩家 80 | oldSession := s.sessionMgr.GetSession(msg.Uid) 81 | if oldSession != nil { 82 | oldSession.Kick("try kick same", msgs.ST_NONE) 83 | s.sessionMgr.RemoveSession(msg.Uid) 84 | } 85 | 86 | //查看是否多次验证 87 | oldCheck := s.unlogiinDataMgr.Get(msg.Uid) 88 | if oldCheck != nil { 89 | s.unlogiinDataMgr.Remove(oldCheck) 90 | } 91 | 92 | //请求gate 93 | result, err := cluster.GetServicePID("center").Ask(&msgs.ApplyService{"gate"}) 94 | if err != nil { 95 | log.Error("get gate server,%v", err) 96 | context.Tell(context.Sender(), &gameproto.UserLoginResult{Result: int32(msgs.Error)}) 97 | return 98 | } 99 | 100 | sr := result.(*msgs.ApplyServiceResult) 101 | if sr.Result != msgs.OK { 102 | context.Tell(context.Sender(), &gameproto.UserLoginResult{Result: int32(sr.Result)}) 103 | return 104 | } 105 | 106 | //加入数据 107 | key := "1111" 108 | //uInfo := &msgs.UserBaseInfo{msg.Account, "玩家" + strconv.Itoa(int(msg.Uid)), msg.Uid} 109 | //ss := &PlayerSession{userInfo: uInfo, gatePid: sr.Pid, key: "1111"} 110 | //s.sessionMgr.AddSession(ss) 111 | s.unlogiinDataMgr.Push(msg.Uid, key, nil) 112 | 113 | gateAddr := GetServiceValue("TcpAddr", sr.Values) 114 | context.Tell(context.Sender(), &gameproto.UserLoginResult{Uid: uint32(msg.Uid), GateAddr: gateAddr, Key: key, Result: int32(msgs.OK)}) 115 | } 116 | 117 | func GetServiceValue(key string, values []*msgs.ServiceValue) string { 118 | for _, v := range values { 119 | if v.Key == key { 120 | return v.Value 121 | } 122 | } 123 | return "" 124 | } 125 | 126 | //玩家验证 127 | func (s *SessionService) OnUserCheckLogin(context service.Context) { 128 | fmt.Println("SessionService.OnUserCheckLogin:", context.Message()) 129 | msg := context.Message().(*msgs.ServerCheckLogin) 130 | 131 | checkData := s.unlogiinDataMgr.Get(msg.Uid) 132 | //人不在 133 | if checkData == nil { 134 | log.Error("OnUserCheckLogin,no found player,id=%v,count=%d", msg.Uid, len(s.unlogiinDataMgr.dataMap)) 135 | context.Tell(context.Sender(), &msgs.CheckLoginResult{Result: msgs.Fail}) 136 | return 137 | } 138 | s.unlogiinDataMgr.Remove(checkData) 139 | //密码错 140 | if checkData.key != msg.Key { 141 | log.Error("OnUserCheckLogin,key error,id=%v,key=%v:%v", msg.Uid, checkData.key, msg.Key) 142 | context.Tell(context.Sender(), &msgs.CheckLoginResult{Result: msgs.KeyError}) 143 | return 144 | } 145 | //请求gameserver 146 | result, err := cluster.GetServicePID("center").Ask(&msgs.ApplyService{"game"}) 147 | if err != nil { 148 | log.Error("get gameserver error:%v", err) 149 | context.Tell(context.Sender(), &msgs.CheckLoginResult{Result: msgs.Error}) 150 | return 151 | } 152 | 153 | sr := result.(*msgs.ApplyServiceResult) 154 | if sr.Result != msgs.OK { 155 | context.Tell(context.Sender(), &msgs.CheckLoginResult{Result: sr.Result}) 156 | return 157 | } 158 | gsPid := sr.Pid 159 | context.Request(gsPid, &msgs.CreatePlayer{Uid: msg.Uid, AgentPID: msg.AgentPID, Sender: context.Sender(), 160 | GatePID: nil, Key: "1111"}) 161 | log.Println("SessionService.OnUserCheckLogin pre:", msg.Uid) 162 | /* 163 | //安装 164 | //todo:这里可能比较耗时,以后改成异步 165 | gsPid := sr.Pid 166 | r, err := context.RequestFuture(gsPid, &msgs.CreatePlayer{msg.Uid, msg.AgentPID}, time.Second*3).Result() 167 | if err != nil { 168 | log.Error("OnUserCheckLogin,create player error,id=%v,%v", msg.Uid, err) 169 | context.Tell(context.Sender(), &msgs.CheckLoginResult{Result: msgs.Error}) 170 | return 171 | } 172 | cresult, _ := r.(*msgs.CreatePlayerResult) 173 | if cresult.Result != msgs.OK { 174 | log.Error("OnUserCheckLogin,create player fail,id=%v,%v", msg.Uid, cresult.Result) 175 | context.Tell(context.Sender(), &msgs.CheckLoginResult{Result: msgs.Error}) 176 | return 177 | } 178 | //完成 179 | 180 | //uInfo := &msgs.UserBaseInfo{"", "玩家" + strconv.Itoa(int(msg.Uid)), msg.Uid} 181 | ss := &PlayerSession{userInfo: cresult.BaseInfo, gatePid: sr.Pid, key: "1111"} 182 | s.sessionMgr.AddSession(ss) 183 | ss.agentPid = msg.AgentPID 184 | ss.gamePlayerPid = cresult.PlayerPID 185 | 186 | //发送消息 187 | gsValue := msgs.UserBindServer{msgs.GameServer, cresult.GetPlayerPID()} 188 | context.Tell(context.Sender(), &msgs.CheckLoginResult{ 189 | Result: msgs.OK, 190 | BaseInfo: ss.userInfo, 191 | BindServers: []*msgs.UserBindServer{&gsValue}}) 192 | 193 | log.Println("SessionService.OnUserCheckLogin ok:", msg.Uid) 194 | */ 195 | } 196 | 197 | func (s *SessionService) OnUserCheckLoginGsBack(context service.Context) { 198 | fmt.Println("SessionService.OnUserCheckLogin:", context.Message()) 199 | cresult := context.Message().(*msgs.CreatePlayerResult) 200 | 201 | id := cresult.TransData.Uid 202 | sender := cresult.TransData.Sender 203 | if cresult.Result != msgs.OK { 204 | log.Error("OnUserCheckLogin,create player fail,id=%v,%v", id, cresult.Result) 205 | context.Tell(sender, &msgs.CheckLoginResult{Result: msgs.Error}) 206 | return 207 | } 208 | //完成 209 | 210 | //uInfo := &msgs.UserBaseInfo{"", "玩家" + strconv.Itoa(int(msg.Uid)), msg.Uid} 211 | ss := &PlayerSession{userInfo: cresult.BaseInfo, gatePid: cresult.TransData.GatePID, key: cresult.TransData.Key} 212 | s.sessionMgr.AddSession(ss) 213 | ss.agentPid = cresult.TransData.AgentPID 214 | ss.gamePlayerPid = cresult.PlayerPID 215 | 216 | //发送消息 217 | gsValue := msgs.UserBindServer{msgs.GameServer, cresult.GetPlayerPID()} 218 | context.Tell(sender, &msgs.CheckLoginResult{ 219 | Result: msgs.OK, 220 | BaseInfo: ss.userInfo, 221 | BindServers: []*msgs.UserBindServer{&gsValue}}) 222 | 223 | log.Println("SessionService.OnUserCheckLogin ok:", id) 224 | } 225 | 226 | //离线 227 | func (s *SessionService) OnUserLeave(context service.Context) { 228 | fmt.Println("SessionService.OnUserLeave:", context.Message()) 229 | msg := context.Message().(*msgs.UserLeave) 230 | //内存移除 231 | ss := s.sessionMgr.RemoveSession(msg.Uid) 232 | //踢人 233 | if ss != nil { 234 | ss.Kick(msg.Reason, msg.From) 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/gameproto/gamecode.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. 2 | // source: gamecode.proto 3 | // DO NOT EDIT! 4 | 5 | /* 6 | Package gameproto is a generated protocol buffer package. 7 | 8 | It is generated from these files: 9 | gamecode.proto 10 | login.proto 11 | share.proto 12 | 13 | It has these top-level messages: 14 | UserLoginResult 15 | PlatformUser 16 | LoginReturn 17 | C2S_TestMsg 18 | S2C_TestMsg 19 | S2C_ConfirmInfo 20 | */ 21 | package gameproto 22 | 23 | import proto "github.com/gogo/protobuf/proto" 24 | import fmt "fmt" 25 | import math "math" 26 | 27 | import strconv "strconv" 28 | 29 | // Reference imports to suppress errors if they are not otherwise used. 30 | var _ = proto.Marshal 31 | var _ = fmt.Errorf 32 | var _ = math.Inf 33 | 34 | // This is a compile-time assertion to ensure that this generated file 35 | // is compatible with the proto package it is being compiled against. 36 | // A compilation error at this line likely means your copy of the 37 | // proto package needs to be updated. 38 | const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package 39 | 40 | type C2GS_CMD int32 41 | 42 | const ( 43 | C2GS_NONE C2GS_CMD = 0 44 | C2S_LOGIN C2GS_CMD = 1 45 | C2S_Test C2GS_CMD = 10 46 | C2S_HEART_INFO C2GS_CMD = 254 47 | C2S_ACK C2GS_CMD = 255 48 | ) 49 | 50 | var C2GS_CMD_name = map[int32]string{ 51 | 0: "C2GS_NONE", 52 | 1: "C2S_LOGIN", 53 | 10: "C2S_Test", 54 | 254: "C2S_HEART_INFO", 55 | 255: "C2S_ACK", 56 | } 57 | var C2GS_CMD_value = map[string]int32{ 58 | "C2GS_NONE": 0, 59 | "C2S_LOGIN": 1, 60 | "C2S_Test": 10, 61 | "C2S_HEART_INFO": 254, 62 | "C2S_ACK": 255, 63 | } 64 | 65 | func (C2GS_CMD) EnumDescriptor() ([]byte, []int) { return fileDescriptorGamecode, []int{0} } 66 | 67 | type GS2C_CMD int32 68 | 69 | const ( 70 | GS2C_NONE GS2C_CMD = 0 71 | S2C_CONFIRM GS2C_CMD = 1 72 | S2C_LOGIN_END GS2C_CMD = 2 73 | S2C_LOGIN_CHAR_INFO GS2C_CMD = 3 74 | S2C_Test GS2C_CMD = 10 75 | ) 76 | 77 | var GS2C_CMD_name = map[int32]string{ 78 | 0: "GS2C_NONE", 79 | 1: "S2C_CONFIRM", 80 | 2: "S2C_LOGIN_END", 81 | 3: "S2C_LOGIN_CHAR_INFO", 82 | 10: "S2C_Test", 83 | } 84 | var GS2C_CMD_value = map[string]int32{ 85 | "GS2C_NONE": 0, 86 | "S2C_CONFIRM": 1, 87 | "S2C_LOGIN_END": 2, 88 | "S2C_LOGIN_CHAR_INFO": 3, 89 | "S2C_Test": 10, 90 | } 91 | 92 | func (GS2C_CMD) EnumDescriptor() ([]byte, []int) { return fileDescriptorGamecode, []int{1} } 93 | 94 | func init() { 95 | proto.RegisterEnum("gameproto.C2GS_CMD", C2GS_CMD_name, C2GS_CMD_value) 96 | proto.RegisterEnum("gameproto.GS2C_CMD", GS2C_CMD_name, GS2C_CMD_value) 97 | } 98 | func (x C2GS_CMD) String() string { 99 | s, ok := C2GS_CMD_name[int32(x)] 100 | if ok { 101 | return s 102 | } 103 | return strconv.Itoa(int(x)) 104 | } 105 | func (x GS2C_CMD) String() string { 106 | s, ok := GS2C_CMD_name[int32(x)] 107 | if ok { 108 | return s 109 | } 110 | return strconv.Itoa(int(x)) 111 | } 112 | 113 | func init() { proto.RegisterFile("gamecode.proto", fileDescriptorGamecode) } 114 | 115 | var fileDescriptorGamecode = []byte{ 116 | // 235 bytes of a gzipped FileDescriptorProto 117 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0x4f, 0xcc, 0x4d, 118 | 0x4d, 0xce, 0x4f, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x04, 0xf1, 0xc1, 0x4c, 119 | 0xad, 0x48, 0x2e, 0x0e, 0x67, 0x23, 0xf7, 0xe0, 0x78, 0x67, 0x5f, 0x17, 0x21, 0x5e, 0x2e, 0x4e, 120 | 0x30, 0xdb, 0xcf, 0xdf, 0xcf, 0x55, 0x80, 0x01, 0xc2, 0x0d, 0x8e, 0xf7, 0xf1, 0x77, 0xf7, 0xf4, 121 | 0x13, 0x60, 0x14, 0xe2, 0x01, 0xa9, 0x0c, 0x8e, 0x0f, 0x49, 0x2d, 0x2e, 0x11, 0xe0, 0x12, 0x12, 122 | 0xe6, 0xe2, 0x03, 0xf1, 0x3c, 0x5c, 0x1d, 0x83, 0x42, 0xe2, 0x3d, 0xfd, 0xdc, 0xfc, 0x05, 0xfe, 123 | 0x81, 0x94, 0xb0, 0x83, 0x04, 0x1d, 0x9d, 0xbd, 0x05, 0xfe, 0x33, 0x6a, 0xa5, 0x70, 0x71, 0xb8, 124 | 0x07, 0x1b, 0x39, 0xc3, 0x8c, 0x06, 0xb3, 0xa1, 0x46, 0xf3, 0x73, 0x71, 0x83, 0x65, 0xfc, 0xfd, 125 | 0xdc, 0x3c, 0x83, 0x7c, 0x05, 0x18, 0x85, 0x04, 0xb9, 0x78, 0x41, 0x02, 0x60, 0xbb, 0xe2, 0x5d, 126 | 0xfd, 0x5c, 0x04, 0x98, 0x84, 0xc4, 0xb9, 0x84, 0x11, 0x42, 0xce, 0x1e, 0x8e, 0x41, 0x10, 0x6b, 127 | 0x98, 0x41, 0x0e, 0x01, 0x49, 0x40, 0x1c, 0xe2, 0xa4, 0x73, 0xe1, 0xa1, 0x1c, 0xc3, 0x8d, 0x87, 128 | 0x72, 0x0c, 0x1f, 0x1e, 0xca, 0x31, 0x36, 0x3c, 0x92, 0x63, 0x5c, 0xf1, 0x48, 0x8e, 0xf1, 0xc4, 129 | 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x7c, 0xf1, 0x48, 0x8e, 0xe1, 130 | 0xc3, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x92, 0xd8, 0xc0, 0xbe, 0x36, 0x06, 0x04, 0x00, 131 | 0x00, 0xff, 0xff, 0x2e, 0xef, 0x9a, 0x80, 0x12, 0x01, 0x00, 0x00, 132 | } 133 | -------------------------------------------------------------------------------- /src/gameproto/msgs/share.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. 2 | // source: share.proto 3 | // DO NOT EDIT! 4 | 5 | package msgs 6 | 7 | import proto "github.com/gogo/protobuf/proto" 8 | import fmt "fmt" 9 | import math "math" 10 | 11 | import strconv "strconv" 12 | 13 | // Reference imports to suppress errors if they are not otherwise used. 14 | var _ = proto.Marshal 15 | var _ = fmt.Errorf 16 | var _ = math.Inf 17 | 18 | // 错误类型 19 | type GAErrorCode int32 20 | 21 | const ( 22 | OK GAErrorCode = 0 23 | Fail GAErrorCode = 1 24 | Error GAErrorCode = 2 25 | ServerFull GAErrorCode = 3 26 | KeyError GAErrorCode = 4 27 | NoFoundTarget GAErrorCode = 5 28 | // old code 29 | IMPORTANT_WRONG_HEAD GAErrorCode = -1000 30 | RESOURCE_VITALITY_ERROR GAErrorCode = 1002 31 | RESOURCE_GOLD_ERROR GAErrorCode = 1003 32 | RESOURCE_RMB_ERROR GAErrorCode = 1004 33 | GUILD_EXIT_CHAIRMAN_ERROR GAErrorCode = 1022 34 | UNKNOWN_ERROR GAErrorCode = -9999 35 | ) 36 | 37 | var GAErrorCode_name = map[int32]string{ 38 | 0: "OK", 39 | 1: "Fail", 40 | 2: "Error", 41 | 3: "ServerFull", 42 | 4: "KeyError", 43 | 5: "NoFoundTarget", 44 | -1000: "IMPORTANT_WRONG_HEAD", 45 | 1002: "RESOURCE_VITALITY_ERROR", 46 | 1003: "RESOURCE_GOLD_ERROR", 47 | 1004: "RESOURCE_RMB_ERROR", 48 | 1022: "GUILD_EXIT_CHAIRMAN_ERROR", 49 | -9999: "UNKNOWN_ERROR", 50 | } 51 | var GAErrorCode_value = map[string]int32{ 52 | "OK": 0, 53 | "Fail": 1, 54 | "Error": 2, 55 | "ServerFull": 3, 56 | "KeyError": 4, 57 | "NoFoundTarget": 5, 58 | "IMPORTANT_WRONG_HEAD": -1000, 59 | "RESOURCE_VITALITY_ERROR": 1002, 60 | "RESOURCE_GOLD_ERROR": 1003, 61 | "RESOURCE_RMB_ERROR": 1004, 62 | "GUILD_EXIT_CHAIRMAN_ERROR": 1022, 63 | "UNKNOWN_ERROR": -9999, 64 | } 65 | 66 | func (GAErrorCode) EnumDescriptor() ([]byte, []int) { return fileDescriptorShare, []int{0} } 67 | 68 | // 服务器类型 69 | type ServerType int32 70 | 71 | const ( 72 | ST_NONE ServerType = 0 73 | ST_LoginServer ServerType = 1 74 | ST_GateServer ServerType = 2 75 | ST_GameServer ServerType = 4 76 | ST_BattleServer ServerType = 8 77 | ST_CenterServer ServerType = 16 78 | ST_SessionServer ServerType = 32 79 | ST_ALLServer ServerType = 63 80 | ) 81 | 82 | var ServerType_name = map[int32]string{ 83 | 0: "ST_NONE", 84 | 1: "ST_LoginServer", 85 | 2: "ST_GateServer", 86 | 4: "ST_GameServer", 87 | 8: "ST_BattleServer", 88 | 16: "ST_CenterServer", 89 | 32: "ST_SessionServer", 90 | 63: "ST_ALLServer", 91 | } 92 | var ServerType_value = map[string]int32{ 93 | "ST_NONE": 0, 94 | "ST_LoginServer": 1, 95 | "ST_GateServer": 2, 96 | "ST_GameServer": 4, 97 | "ST_BattleServer": 8, 98 | "ST_CenterServer": 16, 99 | "ST_SessionServer": 32, 100 | "ST_ALLServer": 63, 101 | } 102 | 103 | func (ServerType) EnumDescriptor() ([]byte, []int) { return fileDescriptorShare, []int{1} } 104 | 105 | // 消息主类型 106 | type ChannelType int32 107 | 108 | const ( 109 | Login ChannelType = 0 110 | Heartbeat ChannelType = 1 111 | GameServer ChannelType = 100 112 | Shop ChannelType = 101 113 | Chat ChannelType = 102 114 | Bag ChannelType = 103 115 | Attr ChannelType = 104 116 | GroupCard ChannelType = 105 117 | Stage ChannelType = 106 118 | Hero ChannelType = 107 119 | Wallet ChannelType = 108 120 | MainQuest ChannelType = 109 121 | DailyQuest ChannelType = 110 122 | BattleServer ChannelType = 200 123 | ) 124 | 125 | var ChannelType_name = map[int32]string{ 126 | 0: "Login", 127 | 1: "Heartbeat", 128 | 100: "GameServer", 129 | 101: "Shop", 130 | 102: "Chat", 131 | 103: "Bag", 132 | 104: "Attr", 133 | 105: "GroupCard", 134 | 106: "Stage", 135 | 107: "Hero", 136 | 108: "Wallet", 137 | 109: "MainQuest", 138 | 110: "DailyQuest", 139 | 200: "BattleServer", 140 | } 141 | var ChannelType_value = map[string]int32{ 142 | "Login": 0, 143 | "Heartbeat": 1, 144 | "GameServer": 100, 145 | "Shop": 101, 146 | "Chat": 102, 147 | "Bag": 103, 148 | "Attr": 104, 149 | "GroupCard": 105, 150 | "Stage": 106, 151 | "Hero": 107, 152 | "Wallet": 108, 153 | "MainQuest": 109, 154 | "DailyQuest": 110, 155 | "BattleServer": 200, 156 | } 157 | 158 | func (ChannelType) EnumDescriptor() ([]byte, []int) { return fileDescriptorShare, []int{2} } 159 | 160 | func init() { 161 | proto.RegisterEnum("msgs.GAErrorCode", GAErrorCode_name, GAErrorCode_value) 162 | proto.RegisterEnum("msgs.ServerType", ServerType_name, ServerType_value) 163 | proto.RegisterEnum("msgs.ChannelType", ChannelType_name, ChannelType_value) 164 | } 165 | func (x GAErrorCode) String() string { 166 | s, ok := GAErrorCode_name[int32(x)] 167 | if ok { 168 | return s 169 | } 170 | return strconv.Itoa(int(x)) 171 | } 172 | func (x ServerType) String() string { 173 | s, ok := ServerType_name[int32(x)] 174 | if ok { 175 | return s 176 | } 177 | return strconv.Itoa(int(x)) 178 | } 179 | func (x ChannelType) String() string { 180 | s, ok := ChannelType_name[int32(x)] 181 | if ok { 182 | return s 183 | } 184 | return strconv.Itoa(int(x)) 185 | } 186 | 187 | func init() { proto.RegisterFile("share.proto", fileDescriptorShare) } 188 | 189 | var fileDescriptorShare = []byte{ 190 | // 530 bytes of a gzipped FileDescriptorProto 191 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0x31, 0x6f, 0xd3, 0x40, 192 | 0x14, 0xc7, 0x7d, 0x69, 0xda, 0xb4, 0x2f, 0x6d, 0xb9, 0xbe, 0x56, 0x2a, 0x20, 0x74, 0x82, 0xb5, 193 | 0x42, 0x2c, 0x7c, 0x00, 0xe4, 0xb8, 0xae, 0x63, 0x35, 0xb1, 0xc1, 0xbe, 0x52, 0x98, 0xac, 0xab, 194 | 0x72, 0x38, 0x06, 0xd7, 0x8e, 0xce, 0x17, 0xa4, 0x6e, 0xec, 0x2c, 0x8c, 0x7c, 0x01, 0x24, 0x56, 195 | 0xbe, 0x01, 0x63, 0xc7, 0x8e, 0x8c, 0xd4, 0x2c, 0x08, 0x18, 0xca, 0xc6, 0x04, 0xc8, 0x89, 0x1d, 196 | 0xc1, 0x4d, 0x77, 0xbf, 0xff, 0x5f, 0xef, 0xfd, 0x9f, 0xde, 0x41, 0xb7, 0x18, 0x0b, 0x25, 0xef, 197 | 0x4d, 0x54, 0xae, 0x73, 0x6c, 0x9f, 0x16, 0x71, 0xb1, 0xf7, 0xba, 0x05, 0x5d, 0xc7, 0xb4, 0x95, 198 | 0xca, 0x95, 0x95, 0x8f, 0x24, 0xae, 0x40, 0xcb, 0x3f, 0xa4, 0x06, 0xae, 0x42, 0xfb, 0x40, 0x24, 199 | 0x29, 0x25, 0xb8, 0x06, 0xcb, 0x33, 0x99, 0xb6, 0x70, 0x13, 0x20, 0x94, 0xea, 0xa5, 0x54, 0x07, 200 | 0xd3, 0x34, 0xa5, 0x4b, 0xb8, 0x0e, 0xab, 0x87, 0xf2, 0x6c, 0xae, 0xb6, 0x71, 0x0b, 0x36, 0xbc, 201 | 0xfc, 0x20, 0x9f, 0x66, 0x23, 0x2e, 0x54, 0x2c, 0x35, 0x5d, 0xc6, 0x3b, 0xb0, 0xe3, 0x0e, 0x1f, 202 | 0xfa, 0x01, 0x37, 0x3d, 0x1e, 0x1d, 0x07, 0xbe, 0xe7, 0x44, 0x7d, 0xdb, 0xdc, 0xa7, 0x6f, 0x7f, 203 | 0xfd, 0x99, 0x1f, 0x82, 0xb7, 0x60, 0x37, 0xb0, 0x43, 0xff, 0x28, 0xb0, 0xec, 0xe8, 0xb1, 0xcb, 204 | 0xcd, 0x81, 0xcb, 0x9f, 0x46, 0x76, 0x10, 0xf8, 0x01, 0xfd, 0xd6, 0xc1, 0xeb, 0xb0, 0xbd, 0x50, 205 | 0x1d, 0x7f, 0xb0, 0x5f, 0x2b, 0xdf, 0x3b, 0xb8, 0x0b, 0xb8, 0x50, 0x82, 0x61, 0xaf, 0x16, 0x7e, 206 | 0x74, 0x90, 0xc1, 0x0d, 0xe7, 0xc8, 0xad, 0xac, 0x4f, 0x5c, 0x1e, 0x59, 0x7d, 0xd3, 0x0d, 0x86, 207 | 0xa6, 0x57, 0xeb, 0xbf, 0x3b, 0x78, 0x13, 0x36, 0x8e, 0xbc, 0x43, 0xcf, 0x3f, 0x6e, 0xd8, 0xcf, 208 | 0x0f, 0x4d, 0x98, 0xbd, 0x77, 0xa4, 0x99, 0x90, 0x9f, 0x4d, 0x24, 0x76, 0xa1, 0x13, 0xf2, 0xc8, 209 | 0xf3, 0x3d, 0x9b, 0x1a, 0x88, 0xb0, 0x19, 0xf2, 0x68, 0x90, 0xc7, 0x49, 0x36, 0xb7, 0x50, 0x52, 210 | 0x8d, 0x1c, 0xf2, 0xc8, 0x11, 0x5a, 0xd6, 0xa8, 0xb5, 0x40, 0xa7, 0x0d, 0x6a, 0xe3, 0x36, 0x5c, 211 | 0x0b, 0x79, 0xd4, 0x13, 0x5a, 0xa7, 0x0d, 0x5c, 0xad, 0xa1, 0x25, 0x33, 0x2d, 0x55, 0x0d, 0x29, 212 | 0xee, 0x00, 0x0d, 0x79, 0x14, 0xca, 0xa2, 0x48, 0xf2, 0xa6, 0xcb, 0x6d, 0xa4, 0xb0, 0x1e, 0xf2, 213 | 0xc8, 0x1c, 0x0c, 0x6a, 0xf2, 0x60, 0xef, 0x23, 0x81, 0xae, 0x35, 0x16, 0x59, 0x26, 0xd3, 0x59, 214 | 0xd0, 0x35, 0x58, 0x9e, 0x05, 0xa3, 0x06, 0x6e, 0xc0, 0x5a, 0x5f, 0x0a, 0xa5, 0x4f, 0xa4, 0xd0, 215 | 0x94, 0x54, 0x2b, 0xfb, 0x27, 0xcb, 0xa8, 0xda, 0x6b, 0x38, 0xce, 0x27, 0x54, 0x56, 0x37, 0x6b, 216 | 0x2c, 0x34, 0x7d, 0x86, 0x1d, 0x58, 0xea, 0x89, 0x98, 0xc6, 0x15, 0x32, 0xb5, 0x56, 0x74, 0x5c, 217 | 0x55, 0x71, 0x54, 0x3e, 0x9d, 0x58, 0x42, 0x8d, 0x68, 0x52, 0xd5, 0x0f, 0xb5, 0x88, 0x25, 0x7d, 218 | 0x5e, 0x79, 0xfa, 0x52, 0xe5, 0xf4, 0x05, 0x02, 0xac, 0x1c, 0x8b, 0x34, 0x95, 0x9a, 0xa6, 0x95, 219 | 0x7f, 0x28, 0x92, 0xec, 0xd1, 0x54, 0x16, 0x9a, 0x9e, 0x56, 0x5d, 0xf7, 0x45, 0x92, 0x9e, 0xcd, 220 | 0xdf, 0x19, 0x6e, 0xc1, 0xfa, 0x7f, 0xe3, 0x9f, 0x93, 0xde, 0xdd, 0x8b, 0x4b, 0x66, 0x7c, 0xba, 221 | 0x64, 0xc6, 0xd5, 0x25, 0x23, 0xaf, 0x4a, 0x46, 0xde, 0x97, 0x8c, 0x9c, 0x97, 0x8c, 0x5c, 0x94, 222 | 0x8c, 0x7c, 0x2e, 0x19, 0xf9, 0x5a, 0x32, 0xe3, 0xaa, 0x64, 0xe4, 0xcd, 0x17, 0x66, 0x9c, 0xac, 223 | 0xcc, 0xfe, 0xec, 0xfd, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x74, 0x15, 0xbb, 0x40, 0xc2, 0x02, 224 | 0x00, 0x00, 225 | } 226 | --------------------------------------------------------------------------------