Commit 69d286a7c94629a66d3065140ade7d58ae77166b
1 parent
cd2f96ab
fix: 插件用来做部分热更
1. 调整逻辑代码位置 2. 插件里做部分逻辑热更
Showing
11 changed files
with
161 additions
and
44 deletions
 
Show diff stats
Makefile
cmd/gameserver/plugin/RolePlugin.go renamed to cmd/gameserver/action/RoleAction.go
| 1 | -package main | |
| 1 | +package action | |
| 2 | 2 | |
| 3 | 3 | import ( | 
| 4 | 4 | "github.com/golang/protobuf/proto" | 
| ... | ... | @@ -9,12 +9,12 @@ import ( | 
| 9 | 9 | "pro2d/pb" | 
| 10 | 10 | ) | 
| 11 | 11 | |
| 12 | -func HeartRpc(msg components.IMessage) (int32, interface{}) { | |
| 12 | +func HeartRpc(msg components.IMessage) (int32, interface{}) { | |
| 13 | 13 | //msg.Conn.SetLastHeartCheckTime() | 
| 14 | 14 | return 0, nil | 
| 15 | 15 | } | 
| 16 | 16 | |
| 17 | -func CreateRpc(msg components.IMessage) (int32, interface{}) { | |
| 17 | +func CreateRpc(msg components.IMessage) (int32, interface{}) { | |
| 18 | 18 | req := pb.CreateReq{} | 
| 19 | 19 | if err := proto.Unmarshal(msg.GetData(), &req); err != nil { | 
| 20 | 20 | logger.Error("CreateRpc err: %v", err) | 
| ... | ... | @@ -27,14 +27,14 @@ func CreateRpc(msg components.IMessage) (int32, interface{}) { | 
| 27 | 27 | |
| 28 | 28 | roleId := common.SnowFlack.NextValStr() | 
| 29 | 29 | role = models.NewRole(roleId) | 
| 30 | - if err := role.Create(); err != nil { | |
| 30 | + if err := role.Create(); err != nil { | |
| 31 | 31 | logger.Error("CreateRpc role create err: %v", err) | 
| 32 | 32 | return 3, nil | 
| 33 | 33 | } | 
| 34 | 34 | return 0, nil | 
| 35 | 35 | } | 
| 36 | 36 | |
| 37 | -func LoginRpc(msg components.IMessage) (int32, interface{}) { | |
| 37 | +func LoginRpc(msg components.IMessage) (int32, interface{}) { | |
| 38 | 38 | //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData()) | 
| 39 | 39 | req := pb.LoginReq{} | 
| 40 | 40 | if err := proto.Unmarshal(msg.GetData(), &req); err != nil { | 
| ... | ... | @@ -49,9 +49,9 @@ func LoginRpc(msg components.IMessage) (int32, interface{}) { | 
| 49 | 49 | role.SetProperty("Device", req.Device) | 
| 50 | 50 | |
| 51 | 51 | return 0, &pb.RoleRsp{ | 
| 52 | - Role: role.Role, | |
| 53 | - Hero: role.GetAllHero(), | |
| 54 | - Team: role.Teams.Team, | |
| 52 | + Role: role.Role, | |
| 53 | + Hero: role.GetAllHero(), | |
| 54 | + Team: role.Teams.Team, | |
| 55 | 55 | Equips: []*pb.Equipment{role.Equip.Equip}, | 
| 56 | 56 | } | 
| 57 | -} | |
| 58 | 57 | \ No newline at end of file | 
| 58 | +} | ... | ... | 
cmd/gameserver/plugin/protocode.go renamed to cmd/gameserver/action/protocode.go
| 1 | -package main | |
| 1 | +package action | |
| 2 | 2 | |
| 3 | 3 | import ( | 
| 4 | 4 | "pro2d/common/logger" | 
| ... | ... | @@ -8,9 +8,9 @@ import ( | 
| 8 | 8 | func GetActionMap() map[interface{}]interface{} { | 
| 9 | 9 | logger.Debug("init protocode...") | 
| 10 | 10 | am := make(map[interface{}]interface{}) | 
| 11 | - am[pb.ProtoCode_HeartReq] = HeartRpc | |
| 12 | - am[pb.ProtoCode_LoginReq] = LoginRpc | |
| 13 | - am[pb.ProtoCode_CreateReq] = CreateRpc | |
| 11 | + am[uint32(pb.ProtoCode_HeartReq)] = HeartRpc | |
| 12 | + am[uint32(pb.ProtoCode_LoginReq)] = LoginRpc | |
| 13 | + am[uint32(pb.ProtoCode_CreateReq)] = CreateRpc | |
| 14 | 14 | |
| 15 | 15 | return am | 
| 16 | -} | |
| 17 | 16 | \ No newline at end of file | 
| 17 | +} | ... | ... | 
cmd/gameserver/game.go
| ... | ... | @@ -3,6 +3,7 @@ package main | 
| 3 | 3 | import ( | 
| 4 | 4 | "fmt" | 
| 5 | 5 | _ "net/http/pprof" | 
| 6 | + "pro2d/cmd/gameserver/action" | |
| 6 | 7 | "pro2d/common" | 
| 7 | 8 | "pro2d/common/components" | 
| 8 | 9 | "pro2d/common/db" | 
| ... | ... | @@ -29,6 +30,7 @@ func NewGameServer(sconf *common.SConf) (*GameServer, error) { | 
| 29 | 30 | } | 
| 30 | 31 | |
| 31 | 32 | iserver := components.NewServer(sconf.Port, options...) | 
| 33 | + iserver.SetActions(action.GetActionMap()) | |
| 32 | 34 | s.IServer = iserver | 
| 33 | 35 | |
| 34 | 36 | //mgo init | ... | ... | 
| ... | ... | @@ -0,0 +1,43 @@ | 
| 1 | +package main | |
| 2 | + | |
| 3 | +import ( | |
| 4 | + "github.com/golang/protobuf/proto" | |
| 5 | + "pro2d/common/components" | |
| 6 | + "pro2d/common/logger" | |
| 7 | + "pro2d/models" | |
| 8 | + "pro2d/pb" | |
| 9 | +) | |
| 10 | + | |
| 11 | +func init() { | |
| 12 | + logger.Debug("init game server plugin") | |
| 13 | +} | |
| 14 | + | |
| 15 | +func GetActionMap() map[interface{}]interface{} { | |
| 16 | + logger.Debug("init protocode...") | |
| 17 | + am := make(map[interface{}]interface{}) | |
| 18 | + am[uint32(pb.ProtoCode_LoginReq)] = LoginRpc | |
| 19 | + | |
| 20 | + return am | |
| 21 | +} | |
| 22 | + | |
| 23 | +func LoginRpc(msg components.IMessage) (int32, interface{}) { | |
| 24 | + //logger.Debug("11111111cmd: %v, msg: %s", msg.GetHeader().GetMsgID(), msg.GetData()) | |
| 25 | + req := pb.LoginReq{} | |
| 26 | + if err := proto.Unmarshal(msg.GetData(), &req); err != nil { | |
| 27 | + logger.Error("loginRpc err: %v", err) | |
| 28 | + return 1, nil | |
| 29 | + } | |
| 30 | + | |
| 31 | + role := models.RoleExistByUid(req.Uid) | |
| 32 | + if role == nil { | |
| 33 | + return 2, nil | |
| 34 | + } | |
| 35 | + role.SetProperty("Device", req.Device) | |
| 36 | + | |
| 37 | + return 0, &pb.RoleRsp{ | |
| 38 | + Role: role.Role, | |
| 39 | + Hero: role.GetAllHero(), | |
| 40 | + Team: role.Teams.Team, | |
| 41 | + Equips: []*pb.Equipment{role.Equip.Equip}, | |
| 42 | + } | |
| 43 | +} | ... | ... | 
| ... | ... | @@ -0,0 +1,55 @@ | 
| 1 | +package components | |
| 2 | + | |
| 3 | +import "sync" | |
| 4 | + | |
| 5 | +type ConnManage struct { | |
| 6 | + mu sync.RWMutex | |
| 7 | + conns map[int]IConnection | |
| 8 | +} | |
| 9 | + | |
| 10 | +func NewConnManage() *ConnManage { | |
| 11 | + return &ConnManage{ | |
| 12 | + mu: sync.RWMutex{}, | |
| 13 | + conns: make(map[int]IConnection), | |
| 14 | + } | |
| 15 | +} | |
| 16 | + | |
| 17 | +func (c *ConnManage) AddConn(id int, connection IConnection) { | |
| 18 | + c.mu.Lock() | |
| 19 | + defer c.mu.Unlock() | |
| 20 | + c.conns[id] = connection | |
| 21 | +} | |
| 22 | + | |
| 23 | +func (c *ConnManage) GetConn(id int) IConnection { | |
| 24 | + c.mu.RLock() | |
| 25 | + defer c.mu.RUnlock() | |
| 26 | + return c.conns[id] | |
| 27 | +} | |
| 28 | + | |
| 29 | +func (c *ConnManage) DelConn(id int) IConnection { | |
| 30 | + c.mu.Lock() | |
| 31 | + defer c.mu.Unlock() | |
| 32 | + conn := c.conns[id] | |
| 33 | + delete(c.conns, id) | |
| 34 | + return conn | |
| 35 | +} | |
| 36 | + | |
| 37 | +func (c *ConnManage) Range(f func(key interface{}, value interface{}) bool) { | |
| 38 | + for k, v := range c.conns { | |
| 39 | + c.mu.Lock() | |
| 40 | + if ok := f(k, v); !ok { | |
| 41 | + c.mu.Unlock() | |
| 42 | + return | |
| 43 | + } | |
| 44 | + c.mu.Unlock() | |
| 45 | + | |
| 46 | + } | |
| 47 | +} | |
| 48 | + | |
| 49 | +func (c *ConnManage) StopAllConns() { | |
| 50 | + c.Range(func(key interface{}, value interface{}) bool { | |
| 51 | + conn := value.(IConnection) | |
| 52 | + conn.Stop() | |
| 53 | + return true | |
| 54 | + }) | |
| 55 | +} | ... | ... | 
common/components/icompontents.go
| ... | ... | @@ -62,6 +62,7 @@ type ( | 
| 62 | 62 | GetSplitter() ISplitter | 
| 63 | 63 | GetPlugin() IPlugin | 
| 64 | 64 | GetAction(uint32) interface{} | 
| 65 | + SetActions(map[interface{}]interface{}) | |
| 65 | 66 | GetConnManage() IConnManage | 
| 66 | 67 | |
| 67 | 68 | SetConnectionCallback(ConnectionCallback) | 
| ... | ... | @@ -76,7 +77,7 @@ type ( | 
| 76 | 77 | Stop() | 
| 77 | 78 | BindHandler(interface{}) | 
| 78 | 79 | } | 
| 79 | - ActionHandler func(conn IConnection, msg IMessage) (int32, interface{}) | |
| 80 | + ActionHandler func(msg IMessage) (int32, interface{}) | |
| 80 | 81 | //用于热更逻辑的插件接口 | 
| 81 | 82 | IPlugin interface { | 
| 82 | 83 | LoadPlugin() error | ... | ... | 
common/components/plugin.go
| ... | ... | @@ -3,23 +3,24 @@ package components | 
| 3 | 3 | import ( | 
| 4 | 4 | "plugin" | 
| 5 | 5 | "pro2d/common/logger" | 
| 6 | - "pro2d/pb" | |
| 7 | 6 | "sync" | 
| 8 | 7 | ) | 
| 9 | 8 | |
| 10 | -type ActionMap sync.Map//map[pb.ProtoCode]ActionHandler | |
| 11 | - | |
| 12 | 9 | type PluginOption func(*Plugin) | 
| 13 | 10 | |
| 14 | 11 | type Plugin struct { | 
| 15 | 12 | pluginPath string | 
| 16 | 13 | |
| 17 | - Actions sync.Map | |
| 14 | + Actions sync.Map | |
| 18 | 15 | } | 
| 19 | 16 | |
| 20 | -func NewPlugin(path string, options ...PluginOption) IPlugin{ | |
| 17 | +func NewPlugin(path string, options ...PluginOption) IPlugin { | |
| 18 | + if path == "" { | |
| 19 | + return nil | |
| 20 | + } | |
| 21 | 21 | p := &Plugin{ | 
| 22 | 22 | pluginPath: path, | 
| 23 | + Actions: sync.Map{}, | |
| 23 | 24 | } | 
| 24 | 25 | for _, option := range options { | 
| 25 | 26 | option(p) | 
| ... | ... | @@ -41,7 +42,7 @@ func (p *Plugin) LoadPlugin() error { | 
| 41 | 42 | } | 
| 42 | 43 | logger.Debug("func LoadPlugin Lookup success...") | 
| 43 | 44 | |
| 44 | - if x, ok := f.(func()map[interface{}]interface{}); ok { | |
| 45 | + if x, ok := f.(func() map[interface{}]interface{}); ok { | |
| 45 | 46 | logger.Debug("func LoadPlugin GetActionMap success...") | 
| 46 | 47 | p.SetActions(x()) | 
| 47 | 48 | } | 
| ... | ... | @@ -50,7 +51,7 @@ func (p *Plugin) LoadPlugin() error { | 
| 50 | 51 | } | 
| 51 | 52 | |
| 52 | 53 | func (p *Plugin) GetAction(cmd uint32) interface{} { | 
| 53 | - f, ok := p.Actions.Load(pb.ProtoCode(cmd)) | |
| 54 | + f, ok := p.Actions.Load(cmd) | |
| 54 | 55 | if !ok { | 
| 55 | 56 | return nil | 
| 56 | 57 | } | 
| ... | ... | @@ -59,7 +60,7 @@ func (p *Plugin) GetAction(cmd uint32) interface{} { | 
| 59 | 60 | |
| 60 | 61 | func (p *Plugin) SetActions(am map[interface{}]interface{}) { | 
| 61 | 62 | for k, v := range am { | 
| 62 | - cmd := k.(pb.ProtoCode) | |
| 63 | + cmd := k.(uint32) | |
| 63 | 64 | p.Actions.Delete(cmd) | 
| 64 | 65 | p.Actions.Store(cmd, v) | 
| 65 | 66 | } | ... | ... | 
common/components/server.go
| ... | ... | @@ -55,7 +55,8 @@ type Server struct { | 
| 55 | 55 | timerCallback TimerCallback | 
| 56 | 56 | |
| 57 | 57 | port int | 
| 58 | - connManage *ConnManage | |
| 58 | + connManage IConnManage | |
| 59 | + Actions map[interface{}]interface{} | |
| 59 | 60 | } | 
| 60 | 61 | |
| 61 | 62 | func NewServer(port int, options ...ServerOption) IServer { | 
| ... | ... | @@ -79,7 +80,18 @@ func (s *Server) GetPlugin() IPlugin { | 
| 79 | 80 | } | 
| 80 | 81 | |
| 81 | 82 | func (s *Server) GetAction(cmd uint32) interface{} { | 
| 82 | - return s.plugins.GetAction(cmd) | |
| 83 | + if s.plugins != nil { | |
| 84 | + f := s.plugins.GetAction(cmd) | |
| 85 | + if f != nil { | |
| 86 | + return f | |
| 87 | + } | |
| 88 | + } | |
| 89 | + | |
| 90 | + return s.Actions[cmd] | |
| 91 | +} | |
| 92 | + | |
| 93 | +func (s *Server) SetActions(mi map[interface{}]interface{}) { | |
| 94 | + s.Actions = mi | |
| 83 | 95 | } | 
| 84 | 96 | |
| 85 | 97 | func (s *Server) GetConnManage() IConnManage { | 
| ... | ... | @@ -103,8 +115,10 @@ func (s *Server) SetTimerCallback(cb TimerCallback) { | 
| 103 | 115 | } | 
| 104 | 116 | |
| 105 | 117 | func (s *Server) Start() error { | 
| 106 | - if err := s.plugins.LoadPlugin(); err != nil { | |
| 107 | - return err | |
| 118 | + if s.plugins != nil { | |
| 119 | + if err := s.plugins.LoadPlugin(); err != nil { | |
| 120 | + return err | |
| 121 | + } | |
| 108 | 122 | } | 
| 109 | 123 | |
| 110 | 124 | port := fmt.Sprintf(":%d", s.port) | ... | ... | 
conf/conf.yaml
| ... | ... | @@ -22,7 +22,7 @@ server_account: | 
| 22 | 22 | ip: "192.168.0.206" | 
| 23 | 23 | port: 8858 | 
| 24 | 24 | pool_size: 1 | 
| 25 | - debugport: 6061 | |
| 25 | + debugport: 6062 | |
| 26 | 26 | mongo: | 
| 27 | 27 | <<: *default-mongo | 
| 28 | 28 | dbname: "account" | 
| ... | ... | @@ -33,7 +33,8 @@ server_game: | 
| 33 | 33 | ip: "192.168.0.206" | 
| 34 | 34 | port: 8850 | 
| 35 | 35 | pool_size: 1 | 
| 36 | - plugin_path: "./bin/plugin.so" | |
| 36 | + debugport: 6061 | |
| 37 | + # plugin_path: "./bin/plugin.so" | |
| 37 | 38 | mongo: | 
| 38 | 39 | <<: *default-mongo | 
| 39 | 40 | dbname: "game" | ... | ... | 
tools/protostostruct.go
| ... | ... | @@ -11,16 +11,17 @@ import ( | 
| 11 | 11 | ) | 
| 12 | 12 | |
| 13 | 13 | var ( | 
| 14 | - ProtoCode = "syntax = \"proto3\";\noption go_package = \"./pb;pb\";\n\npackage protocode;\n\nenum ProtoCode\n{\n UNKNOWN = 0;\n %s\n}" | |
| 14 | + ProtoCode = "syntax = \"proto3\";\noption go_package = \"../pb;pb\";\n\npackage protocode;\n\nenum ProtoCode\n{\n UNKNOWN = 0;\n %s\n}" | |
| 15 | 15 | ProtoCodeLineReq = "\t%sReq = %d;\n" | 
| 16 | 16 | ProtoCodeLineRsp = "\t%sRsp = %d;\n" | 
| 17 | 17 | |
| 18 | - GoProtoCodeStr = "package main\n\nimport (\n\t\"pro2d/pb\"\n\t\"pro2d/utils/logger\"\n)\n\nfunc GetActionMap() map[interface{}]interface{} {\n\tlogger.Debug(\"init protocode...\")\n\tam := make(map[interface{}]interface{})\n%s\n\treturn am\n}" | |
| 19 | - GoProtoCodeLine = "\tam[pb.ProtoCode_%sReq] = %sRpc\n" | |
| 18 | + GoProtoCodeStr = "package action\n\nimport (\n\t\"pro2d/common/logger\"\n\t\"pro2d/pb\"\n)\n\nfunc GetActionMap() map[interface{}]interface{} {\n\tlogger.Debug(\"init protocode...\")\n\tam := make(map[interface{}]interface{})\n%s\n\treturn am\n}" | |
| 19 | + | |
| 20 | + GoProtoCodeLine = "\tam[uint32(pb.ProtoCode_%sReq)] = %sRpc\n" | |
| 20 | 21 | ) | 
| 21 | 22 | |
| 22 | 23 | func ProtoToCode(readPath, filename string) (string, string) { | 
| 23 | - protofile , err := os.Open(readPath+filename) | |
| 24 | + protofile, err := os.Open(readPath + filename) | |
| 24 | 25 | code := 0x000 | 
| 25 | 26 | protoData := "" | 
| 26 | 27 | goProtoData := "" | 
| ... | ... | @@ -57,45 +58,44 @@ func ProtoToCode(readPath, filename string) (string, string) { | 
| 57 | 58 | for _, v := range lb { | 
| 58 | 59 | n1 := bytes.Index(v, []byte("Req")) | 
| 59 | 60 | n2 := bytes.Index(v, []byte("Rsp")) | 
| 60 | - if n1 < 0 && n2 < 0 { | |
| 61 | + if n1 < 0 && n2 < 0 { | |
| 61 | 62 | continue | 
| 62 | 63 | } | 
| 63 | 64 | if n1 >= 0 { | 
| 64 | 65 | code++ | 
| 65 | - protoData += fmt.Sprintf(ProtoCodeLineReq, v[:n1],code) | |
| 66 | + protoData += fmt.Sprintf(ProtoCodeLineReq, v[:n1], code) | |
| 66 | 67 | goProtoData += fmt.Sprintf(GoProtoCodeLine, v[:n1], v[:n1]) | 
| 67 | 68 | } | 
| 68 | 69 | if n2 >= 0 { | 
| 69 | 70 | code++ | 
| 70 | - protoData += fmt.Sprintf(ProtoCodeLineRsp, v[:n2],code) | |
| 71 | + protoData += fmt.Sprintf(ProtoCodeLineRsp, v[:n2], code) | |
| 71 | 72 | } | 
| 72 | 73 | } | 
| 73 | 74 | } | 
| 74 | 75 | |
| 75 | - return protoData ,goProtoData | |
| 76 | + return protoData, goProtoData | |
| 76 | 77 | } | 
| 77 | 78 | |
| 78 | -func ReadProtos(readPath, OutPath string ) error { | |
| 79 | +func ReadProtos(readPath, OutPath string) error { | |
| 79 | 80 | files, err := ioutil.ReadDir(readPath) | 
| 80 | 81 | if err != nil { | 
| 81 | 82 | return fmt.Errorf("ReadExcel|ReadDir is err:%v", err) | 
| 82 | 83 | } | 
| 83 | 84 | |
| 84 | - | |
| 85 | 85 | protoData, goProtoData := "", "" | 
| 86 | 86 | for _, file := range files { | 
| 87 | - if path.Ext(file.Name()) != ".proto"{ | |
| 87 | + if path.Ext(file.Name()) != ".proto" { | |
| 88 | 88 | continue | 
| 89 | 89 | } | 
| 90 | 90 | tprotoData, tgoProtoData := ProtoToCode(readPath, file.Name()) | 
| 91 | 91 | if tprotoData == "" || tgoProtoData == "" { | 
| 92 | - continue | |
| 92 | + continue | |
| 93 | 93 | } | 
| 94 | 94 | protoData += tprotoData | 
| 95 | 95 | goProtoData += tgoProtoData | 
| 96 | 96 | |
| 97 | 97 | } | 
| 98 | - fw, err := os.OpenFile( OutPath+"protos/protocode.proto", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | |
| 98 | + fw, err := os.OpenFile(OutPath+"protos/protocode.proto", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | |
| 99 | 99 | if err != nil { | 
| 100 | 100 | return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err) | 
| 101 | 101 | } | 
| ... | ... | @@ -106,7 +106,7 @@ func ReadProtos(readPath, OutPath string ) error { | 
| 106 | 106 | return fmt.Errorf("WriteNewFile|Write is err:%v", err) | 
| 107 | 107 | } | 
| 108 | 108 | |
| 109 | - fw, err = os.OpenFile( OutPath+"cmd/gameserver/plugin/protocode.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | |
| 109 | + fw, err = os.OpenFile(OutPath+"cmd/gameserver/action/protocode.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | |
| 110 | 110 | if err != nil { | 
| 111 | 111 | return fmt.Errorf("WriteNewFile|OpenFile is err:%v", err) | 
| 112 | 112 | } | ... | ... |