Commit c47aa250d2603e4af3134a5917dac109a33867f1
1 parent
15864203
feat: 增加GM相关接口。详情请看protoc/doc/gm.md文档
Showing
12 changed files
with
189 additions
and
16 deletions
Show diff stats
| @@ -0,0 +1,33 @@ | @@ -0,0 +1,33 @@ | ||
| 1 | +package action | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "pro2d/common" | ||
| 5 | + "pro2d/common/components" | ||
| 6 | + "pro2d/common/logger" | ||
| 7 | + "pro2d/models" | ||
| 8 | + "strconv" | ||
| 9 | +) | ||
| 10 | + | ||
| 11 | +type GmAction struct { | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +func (gm *GmAction) AddExp(properties map[string]interface{}) int { | ||
| 15 | + r := properties[common.Role_] | ||
| 16 | + c := properties[common.Conn_] | ||
| 17 | + | ||
| 18 | + role := r.(*models.RoleModel) | ||
| 19 | + var conn components.IConnection | ||
| 20 | + if c == nil { | ||
| 21 | + conn = nil | ||
| 22 | + } else { | ||
| 23 | + conn = c.(components.IConnection) | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + logger.Debug(properties) | ||
| 27 | + exp, _ := strconv.Atoi(properties["exp"].(string)) | ||
| 28 | + logger.Debug("update before id: %s, exp: %d", role.Role.Id, role.Role.Exp) | ||
| 29 | + role.Role.Exp += int64(exp) | ||
| 30 | + role.UpdateProperty(conn, "exp", role.Role.Exp, true) | ||
| 31 | + logger.Debug("update after id: %s, exp: %d", role.Role.Id, role.Role.Exp) | ||
| 32 | + return 0 | ||
| 33 | +} |
cmd/gameserver/action/RoleAction.go
| @@ -48,6 +48,7 @@ func CreateRpc(agent components.IAgent, msg components.IMessage) (int32, interfa | @@ -48,6 +48,7 @@ func CreateRpc(agent components.IAgent, msg components.IMessage) (int32, interfa | ||
| 48 | 48 | ||
| 49 | roleId := common.SnowFlack.NextValStr() | 49 | roleId := common.SnowFlack.NextValStr() |
| 50 | role = models.NewRole(roleId) | 50 | role = models.NewRole(roleId) |
| 51 | + role.Role.Uid = req.Token | ||
| 51 | role.Role.Nick = getRandomName() | 52 | role.Role.Nick = getRandomName() |
| 52 | if err := role.Create(); err != nil { | 53 | if err := role.Create(); err != nil { |
| 53 | logger.Error("CreateRpc role create err: %v", err) | 54 | logger.Error("CreateRpc role create err: %v", err) |
cmd/gameserver/main.go
| @@ -19,13 +19,19 @@ func main() { | @@ -19,13 +19,19 @@ func main() { | ||
| 19 | userChan := make(chan os.Signal) | 19 | userChan := make(chan os.Signal) |
| 20 | signal.Notify(userChan, syscall.SIGUSR1, syscall.SIGUSR2) | 20 | signal.Notify(userChan, syscall.SIGUSR1, syscall.SIGUSR2) |
| 21 | 21 | ||
| 22 | - s, err1 := service.NewGameServer(common.GlobalConf.GameConf) | 22 | + sconf := common.GlobalConf.GameConf |
| 23 | + s, err1 := service.NewGameServer(sconf) | ||
| 23 | if err1 != nil { | 24 | if err1 != nil { |
| 24 | logger.Error(err1) | 25 | logger.Error(err1) |
| 25 | return | 26 | return |
| 26 | } | 27 | } |
| 27 | go func() { | 28 | go func() { |
| 28 | - err <- http.ListenAndServe(fmt.Sprintf("localhost:%d", common.GlobalConf.GameConf.DebugPort), nil) | 29 | + err <- http.ListenAndServe(fmt.Sprintf("localhost:%d", sconf.DebugPort), nil) |
| 30 | + }() | ||
| 31 | + | ||
| 32 | + gm := service.NewGmServer(s, fmt.Sprintf(":%d", sconf.GMPort)) | ||
| 33 | + go func() { | ||
| 34 | + err <- gm.Start() | ||
| 29 | }() | 35 | }() |
| 30 | 36 | ||
| 31 | go func() { | 37 | go func() { |
cmd/gameserver/service/agent.go
| @@ -37,6 +37,8 @@ func NewAgent(s components.IServer) *Agent { | @@ -37,6 +37,8 @@ func NewAgent(s components.IServer) *Agent { | ||
| 37 | 37 | ||
| 38 | func (c *Agent) SetSchema(schema components.ISchema) { | 38 | func (c *Agent) SetSchema(schema components.ISchema) { |
| 39 | c.Role = schema.(*models.RoleModel) | 39 | c.Role = schema.(*models.RoleModel) |
| 40 | + | ||
| 41 | + c.Server.GetConnManage().AddRID(c.Role.Role.Id, c.IConnection.GetID()) | ||
| 40 | } | 42 | } |
| 41 | 43 | ||
| 42 | func (c *Agent) GetSchema() components.ISchema { | 44 | func (c *Agent) GetSchema() components.ISchema { |
| @@ -110,6 +112,7 @@ func (c *Agent) OnClose() { | @@ -110,6 +112,7 @@ func (c *Agent) OnClose() { | ||
| 110 | return | 112 | return |
| 111 | } | 113 | } |
| 112 | 114 | ||
| 115 | + c.Server.GetConnManage().DelRID(c.Role.Role.Id) | ||
| 113 | c.Role.OnOfflineEvent() | 116 | c.Role.OnOfflineEvent() |
| 114 | } | 117 | } |
| 115 | 118 |
| @@ -0,0 +1,74 @@ | @@ -0,0 +1,74 @@ | ||
| 1 | +package service | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "github.com/gin-gonic/gin" | ||
| 5 | + "net/http" | ||
| 6 | + "pro2d/cmd/gameserver/action" | ||
| 7 | + "pro2d/common/components" | ||
| 8 | + "pro2d/models" | ||
| 9 | + "reflect" | ||
| 10 | +) | ||
| 11 | + | ||
| 12 | +type GmServer struct { | ||
| 13 | + components.IHttp | ||
| 14 | + Server components.IServer | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +func NewGmServer(server components.IServer, port ...string) *GmServer { | ||
| 18 | + return &GmServer{ | ||
| 19 | + IHttp: components.NewHttpServer("", port...), | ||
| 20 | + Server: server, | ||
| 21 | + } | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +func (s *GmServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { | ||
| 25 | + return func(c *gin.Context) { | ||
| 26 | + c.Request.ParseForm() | ||
| 27 | + roleId, ok := c.GetPostForm("role_id") | ||
| 28 | + if !ok { | ||
| 29 | + c.JSON(http.StatusOK, gin.H{"code": -101, "message": "role not exist"}) | ||
| 30 | + return | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + conn := s.Server.GetConnManage().GetConnByRID(roleId) | ||
| 34 | + var role *models.RoleModel | ||
| 35 | + if conn != nil { | ||
| 36 | + //在线 | ||
| 37 | + role = conn.(*Agent).Role | ||
| 38 | + } else { | ||
| 39 | + //离线 | ||
| 40 | + role = models.NewRole(roleId) | ||
| 41 | + if err := role.Load(); err != nil { | ||
| 42 | + c.JSON(http.StatusOK, gin.H{"code": -102, "message": "role not exist"}) | ||
| 43 | + return | ||
| 44 | + } | ||
| 45 | + role.LoadAll() | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + properties := make(map[string]interface{}) | ||
| 49 | + | ||
| 50 | + for k, v := range c.Request.PostForm { | ||
| 51 | + properties[k] = v[0] | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + properties["_conn"] = conn | ||
| 55 | + properties["_role"] = role | ||
| 56 | + | ||
| 57 | + v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(properties)}) | ||
| 58 | + | ||
| 59 | + role.SaveRoleData(0) | ||
| 60 | + | ||
| 61 | + if len(v) != 1 { | ||
| 62 | + c.JSON(http.StatusNotFound, gin.H{"code": -100, "message": "request param len is error"}) | ||
| 63 | + return | ||
| 64 | + } | ||
| 65 | + c.JSON(http.StatusOK, gin.H{"code": v[0].Interface()}) | ||
| 66 | + } | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +func (s *GmServer) Start() error { | ||
| 70 | + s.SetHandlerFuncCallback(s.HandlerFuncObj) | ||
| 71 | + s.BindHandler(&action.GmAction{}) | ||
| 72 | + //gin.SetMode(gin.ReleaseMode) | ||
| 73 | + return s.IHttp.Start() | ||
| 74 | +} |
common/components/connmanage.go
| @@ -5,12 +5,18 @@ import "sync" | @@ -5,12 +5,18 @@ import "sync" | ||
| 5 | type ConnManage struct { | 5 | type ConnManage struct { |
| 6 | mu sync.RWMutex | 6 | mu sync.RWMutex |
| 7 | conns map[uint32]IConnection | 7 | conns map[uint32]IConnection |
| 8 | + | ||
| 9 | + r2cRW sync.RWMutex | ||
| 10 | + r2c map[string]uint32 // role to connID | ||
| 8 | } | 11 | } |
| 9 | 12 | ||
| 10 | func NewConnManage() *ConnManage { | 13 | func NewConnManage() *ConnManage { |
| 11 | return &ConnManage{ | 14 | return &ConnManage{ |
| 12 | mu: sync.RWMutex{}, | 15 | mu: sync.RWMutex{}, |
| 13 | conns: make(map[uint32]IConnection), | 16 | conns: make(map[uint32]IConnection), |
| 17 | + | ||
| 18 | + r2cRW: sync.RWMutex{}, | ||
| 19 | + r2c: make(map[string]uint32), | ||
| 14 | } | 20 | } |
| 15 | } | 21 | } |
| 16 | 22 | ||
| @@ -51,3 +57,22 @@ func (c *ConnManage) StopAllConns() { | @@ -51,3 +57,22 @@ func (c *ConnManage) StopAllConns() { | ||
| 51 | return true | 57 | return true |
| 52 | }) | 58 | }) |
| 53 | } | 59 | } |
| 60 | + | ||
| 61 | +func (c *ConnManage) AddRID(rid string, id uint32) { | ||
| 62 | + c.r2cRW.Lock() | ||
| 63 | + defer c.r2cRW.Unlock() | ||
| 64 | + c.r2c[rid] = id | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +func (c *ConnManage) DelRID(rid string) { | ||
| 68 | + c.r2cRW.Lock() | ||
| 69 | + defer c.r2cRW.Unlock() | ||
| 70 | + delete(c.r2c, rid) | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +func (c *ConnManage) GetConnByRID(rid string) IConnection { | ||
| 74 | + c.r2cRW.RLock() | ||
| 75 | + defer c.r2cRW.RUnlock() | ||
| 76 | + cid := c.r2c[rid] | ||
| 77 | + return c.GetConn(cid) | ||
| 78 | +} |
common/components/http.go
| @@ -9,9 +9,10 @@ import ( | @@ -9,9 +9,10 @@ import ( | ||
| 9 | 9 | ||
| 10 | type HttpServer struct { | 10 | type HttpServer struct { |
| 11 | IHttp | 11 | IHttp |
| 12 | - version string | ||
| 13 | - port []string | ||
| 14 | - Handler interface{} | 12 | + version string |
| 13 | + port []string | ||
| 14 | + Handler interface{} | ||
| 15 | + HandlerFuncCallBack func(tvl, obj reflect.Value) gin.HandlerFunc | ||
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | func Pong(c *gin.Context) { | 18 | func Pong(c *gin.Context) { |
| @@ -29,6 +30,10 @@ func GetRoutePath(objName, objFunc string) string { | @@ -29,6 +30,10 @@ func GetRoutePath(objName, objFunc string) string { | ||
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | func (h *HttpServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { | 32 | func (h *HttpServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { |
| 33 | + if h.HandlerFuncCallBack != nil { | ||
| 34 | + return h.HandlerFuncCallBack(tvl, obj) | ||
| 35 | + } | ||
| 36 | + | ||
| 32 | return func(c *gin.Context) { | 37 | return func(c *gin.Context) { |
| 33 | v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(c)}) | 38 | v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(c)}) |
| 34 | if len(v) != 2 { | 39 | if len(v) != 2 { |
| @@ -44,6 +49,10 @@ func (h *HttpServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { | @@ -44,6 +49,10 @@ func (h *HttpServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { | ||
| 44 | } | 49 | } |
| 45 | } | 50 | } |
| 46 | 51 | ||
| 52 | +func (h *HttpServer) SetHandlerFuncCallback(gh func(tvl, obj reflect.Value) gin.HandlerFunc) { | ||
| 53 | + h.HandlerFuncCallBack = gh | ||
| 54 | +} | ||
| 55 | + | ||
| 47 | func (h *HttpServer) BindHandler(handler interface{}) { | 56 | func (h *HttpServer) BindHandler(handler interface{}) { |
| 48 | h.Handler = handler | 57 | h.Handler = handler |
| 49 | } | 58 | } |
common/components/icompontents.go
| 1 | package components | 1 | package components |
| 2 | 2 | ||
| 3 | -import "google.golang.org/protobuf/reflect/protoreflect" | 3 | +import ( |
| 4 | + "github.com/gin-gonic/gin" | ||
| 5 | + "google.golang.org/protobuf/reflect/protoreflect" | ||
| 6 | + "reflect" | ||
| 7 | +) | ||
| 4 | 8 | ||
| 5 | //----------------- | 9 | //----------------- |
| 6 | //----net start---- | 10 | //----net start---- |
| @@ -60,6 +64,10 @@ type ( | @@ -60,6 +64,10 @@ type ( | ||
| 60 | DelConn(id uint32) IConnection | 64 | DelConn(id uint32) IConnection |
| 61 | Range(f func(key interface{}, value interface{}) bool) | 65 | Range(f func(key interface{}, value interface{}) bool) |
| 62 | StopAllConns() | 66 | StopAllConns() |
| 67 | + | ||
| 68 | + AddRID(rid string, id uint32) | ||
| 69 | + DelRID(rid string) | ||
| 70 | + GetConnByRID(rid string) IConnection | ||
| 63 | } | 71 | } |
| 64 | //server | 72 | //server |
| 65 | IServer interface { | 73 | IServer interface { |
| @@ -97,6 +105,7 @@ type ( | @@ -97,6 +105,7 @@ type ( | ||
| 97 | IHttp interface { | 105 | IHttp interface { |
| 98 | Start() error | 106 | Start() error |
| 99 | Stop() | 107 | Stop() |
| 108 | + SetHandlerFuncCallback(func(tvl, obj reflect.Value) gin.HandlerFunc) | ||
| 100 | BindHandler(interface{}) | 109 | BindHandler(interface{}) |
| 101 | } | 110 | } |
| 102 | ActionHandler func(msg IMessage) (int32, interface{}) | 111 | ActionHandler func(msg IMessage) (int32, interface{}) |
common/conf.go
| @@ -36,8 +36,9 @@ type SConf struct { | @@ -36,8 +36,9 @@ type SConf struct { | ||
| 36 | Name string `yaml:"name"` | 36 | Name string `yaml:"name"` |
| 37 | IP string `yaml:"ip"` | 37 | IP string `yaml:"ip"` |
| 38 | Port int `yaml:"port"` | 38 | Port int `yaml:"port"` |
| 39 | - Encipher bool `yaml:"encipher"` | ||
| 40 | DebugPort int `yaml:"debugport"` | 39 | DebugPort int `yaml:"debugport"` |
| 40 | + GMPort int `yaml:"gm"` | ||
| 41 | + Encipher bool `yaml:"encipher"` | ||
| 41 | MongoConf *MongoConf `yaml:"mongo"` | 42 | MongoConf *MongoConf `yaml:"mongo"` |
| 42 | RedisConf *RedisConf `yaml:"redis"` | 43 | RedisConf *RedisConf `yaml:"redis"` |
| 43 | WorkerPoolSize int `yaml:"pool_size"` | 44 | WorkerPoolSize int `yaml:"pool_size"` |
common/const.go
| @@ -3,7 +3,7 @@ package common | @@ -3,7 +3,7 @@ package common | ||
| 3 | const ( | 3 | const ( |
| 4 | //最大包大 | 4 | //最大包大 |
| 5 | MaxPacketLength = 10 * 1024 * 1024 | 5 | MaxPacketLength = 10 * 1024 * 1024 |
| 6 | - MaxMsgChan = 100 | 6 | + MaxMsgChan = 100 |
| 7 | 7 | ||
| 8 | //心跳 | 8 | //心跳 |
| 9 | HeartTimerInterval = 5 //s | 9 | HeartTimerInterval = 5 //s |
| @@ -11,10 +11,20 @@ const ( | @@ -11,10 +11,20 @@ const ( | ||
| 11 | 11 | ||
| 12 | //保存数据时间 | 12 | //保存数据时间 |
| 13 | SaveDataInterval = 5 //s | 13 | SaveDataInterval = 5 //s |
| 14 | + | ||
| 15 | + //id相关 | ||
| 16 | + MaxRoleNum = 1000000 | ||
| 17 | + MaxUidNum = 1000000 | ||
| 18 | + MaxHeroNum = 1000000 | ||
| 19 | + MaxTeamNum = 1000000 | ||
| 20 | + | ||
| 21 | + //gm参数属性 | ||
| 22 | + Role_ = "_role" | ||
| 23 | + Conn_ = "_conn" | ||
| 14 | ) | 24 | ) |
| 15 | 25 | ||
| 16 | //redis keys | 26 | //redis keys |
| 17 | const ( | 27 | const ( |
| 18 | NickNames = "name:%s" | 28 | NickNames = "name:%s" |
| 19 | - SMSCode = "smscode:%s" | 29 | + SMSCode = "smscode:%s" |
| 20 | ) | 30 | ) |
conf/conf.yaml
| @@ -40,8 +40,9 @@ server_game: | @@ -40,8 +40,9 @@ server_game: | ||
| 40 | ip: "192.168.0.206" | 40 | ip: "192.168.0.206" |
| 41 | encipher: false | 41 | encipher: false |
| 42 | port: 8850 | 42 | port: 8850 |
| 43 | - pool_size: 1 | ||
| 44 | debugport: 6061 | 43 | debugport: 6061 |
| 44 | + gm: 8881 | ||
| 45 | + pool_size: 1 | ||
| 45 | plugin_path: "./bin/plugin.so" | 46 | plugin_path: "./bin/plugin.so" |
| 46 | mongo: | 47 | mongo: |
| 47 | <<: *default-mongo | 48 | <<: *default-mongo |
models/role.go
| @@ -24,7 +24,7 @@ func RoleExistByUid(uid string) *RoleModel { | @@ -24,7 +24,7 @@ func RoleExistByUid(uid string) *RoleModel { | ||
| 24 | data := &pb.Role{Uid: uid} | 24 | data := &pb.Role{Uid: uid} |
| 25 | 25 | ||
| 26 | if err := mongoproxy.FindOne(mongoproxy.GetBsonM("uid", uid), data); err != nil { | 26 | if err := mongoproxy.FindOne(mongoproxy.GetBsonM("uid", uid), data); err != nil { |
| 27 | - logger.Error("Role exist err: %v", err) | 27 | + logger.Error("Role not exist err: %v", err) |
| 28 | return nil | 28 | return nil |
| 29 | } | 29 | } |
| 30 | 30 | ||
| @@ -35,6 +35,7 @@ func RoleExistByUid(uid string) *RoleModel { | @@ -35,6 +35,7 @@ func RoleExistByUid(uid string) *RoleModel { | ||
| 35 | Teams: make(SchemaMap), | 35 | Teams: make(SchemaMap), |
| 36 | Prop: new(PropModel), | 36 | Prop: new(PropModel), |
| 37 | } | 37 | } |
| 38 | + r.Load() | ||
| 38 | r.LoadAll() | 39 | r.LoadAll() |
| 39 | return r | 40 | return r |
| 40 | } | 41 | } |
| @@ -154,7 +155,7 @@ func (m *RoleModel) UpdateProperties(conn components.IConnection, property map[s | @@ -154,7 +155,7 @@ func (m *RoleModel) UpdateProperties(conn components.IConnection, property map[s | ||
| 154 | logger.Error("id %s, err:", m.Role.Id, err) | 155 | logger.Error("id %s, err:", m.Role.Id, err) |
| 155 | return | 156 | return |
| 156 | } else { | 157 | } else { |
| 157 | - if conn != nil { | 158 | + if conn != nil && notify { |
| 158 | conn.Send(0, uint32(pb.ProtoCode_UpdateRolePropertyRsp), rsp) | 159 | conn.Send(0, uint32(pb.ProtoCode_UpdateRolePropertyRsp), rsp) |
| 159 | } | 160 | } |
| 160 | } | 161 | } |
| @@ -199,16 +200,16 @@ func (m *RoleModel) UpdateTeam(teams []*pb.Team) { | @@ -199,16 +200,16 @@ func (m *RoleModel) UpdateTeam(teams []*pb.Team) { | ||
| 199 | } | 200 | } |
| 200 | 201 | ||
| 201 | func (m *RoleModel) OnRecoverTimer(now int64) { | 202 | func (m *RoleModel) OnRecoverTimer(now int64) { |
| 202 | - m.saveRoleData(now) | 203 | + m.SaveRoleData(now) |
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | func (m *RoleModel) OnOfflineEvent() { | 206 | func (m *RoleModel) OnOfflineEvent() { |
| 206 | // 设置最新的登录时间 | 207 | // 设置最新的登录时间 |
| 207 | - m.saveRoleData(common.Timex()) | 208 | + m.SaveRoleData(common.Timex()) |
| 208 | } | 209 | } |
| 209 | 210 | ||
| 210 | -func (m *RoleModel) saveRoleData(now int64) { | ||
| 211 | - if now-m.lastSaveTs < common.SaveDataInterval { | 211 | +func (m *RoleModel) SaveRoleData(now int64) { |
| 212 | + if now > 0 && now-m.lastSaveTs < common.SaveDataInterval { | ||
| 212 | return | 213 | return |
| 213 | } | 214 | } |
| 214 | atomic.StoreInt64(&m.lastSaveTs, now) | 215 | atomic.StoreInt64(&m.lastSaveTs, now) |