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 | } | ... | ... |