From cd7985e4915fd9b5912242c90446c8e7c75da23e Mon Sep 17 00:00:00 2001 From: LiuShaowen Date: Wed, 11 Aug 2021 16:44:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0protobuf=E3=80=81aoi=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E3=80=81=E8=81=8A=E5=A4=A9=E9=80=9A=E8=AE=AF=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 + go.sum | 10 +- mmo/Client.go | 139 ++++++++++++ mmo/Client1.go | 137 ++++++++++++ mmo/api/WorldChat.go | 33 +++ mmo/conf/conf.yaml | 5 + mmo/core/Grid.go | 55 +++++ mmo/core/Player.go | 99 +++++++++ mmo/core/WorldManager.go | 55 +++++ mmo/core/aoi.go | 149 +++++++++++++ mmo/core/aoi_test.go | 29 +++ mmo/main.go | 33 +++ mmo/pb/gen-golang.bat | 1 + mmo/pb/gen-golang.sh | 2 + mmo/pb/msg.proto | 36 ++++ mmo/pb/msg/msg.pb.go | 442 +++++++++++++++++++++++++++++++++++++++ net/MsgHandler.go | 1 + utils/globalobj.go | 14 ++ 18 files changed, 1241 insertions(+), 1 deletion(-) create mode 100644 mmo/Client.go create mode 100644 mmo/Client1.go create mode 100644 mmo/api/WorldChat.go create mode 100644 mmo/conf/conf.yaml create mode 100644 mmo/core/Grid.go create mode 100644 mmo/core/Player.go create mode 100644 mmo/core/WorldManager.go create mode 100644 mmo/core/aoi.go create mode 100644 mmo/core/aoi_test.go create mode 100644 mmo/main.go create mode 100644 mmo/pb/gen-golang.bat create mode 100644 mmo/pb/gen-golang.sh create mode 100644 mmo/pb/msg.proto create mode 100644 mmo/pb/msg/msg.pb.go diff --git a/go.mod b/go.mod index 80833f9..16f9289 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.16 require ( github.com/gin-gonic/gin v1.7.2 + github.com/golang/protobuf v1.5.0 github.com/panjf2000/gnet v1.5.3 go.uber.org/atomic v1.9.0 // indirect + google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) diff --git a/go.sum b/go.sum index adc043d..097a3a3 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,11 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -86,6 +89,11 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 h1:Yq9t9jnGoR+dBuitxdo9l6Q7xh/zOyNnYUtDKaQ3x0E= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/mmo/Client.go b/mmo/Client.go new file mode 100644 index 0000000..8c9799b --- /dev/null +++ b/mmo/Client.go @@ -0,0 +1,139 @@ +package main + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "io" + "net" + "time" + pMsg "wukong/mmo/pb/msg" + wkNet "wukong/net" +) + +func main() { + + fmt.Println("--------------> 陆离频道 <--------------") + time.Sleep(1 + time.Second) + + conn, err := net.Dial("tcp", "127.0.0.1:9527") + if err != nil { + fmt.Println("client start err exit! ") + return + } + + for i := 0; i < 2; i++ { + dp := wkNet.NewDataPack() + //binaryMsg, err := dp.Pack(wkNet.NewMessage(0, []byte("LiuLiGamesV0.9 client0 Test Message "))) + //if err != nil { + // fmt.Println("Pack error", err) + //} + // + //if _, err := conn.Write(binaryMsg); err != nil { + // fmt.Println("conn Write error", err) + // return + //} + + binaryHead := make([]byte, dp.GetHeadLen()) + if _, err := io.ReadFull(conn, binaryHead); err != nil { + fmt.Println("read head error", err) + return + } + + msgHead, err := dp.Unpack(binaryHead) + if err != nil { + fmt.Println("client unpack msgHead error", err) + break + } + + if msgHead.GetMsgLen() > 0 { + msg := msgHead.(*wkNet.Message) + msg.SetData(make([]byte, msg.GetMsgLen())) + + if _, err := io.ReadFull(conn, msg.Data); err != nil { + fmt.Println("read msg data error", err) + return + } + + data := &pMsg.SyncPid{} + err := proto.Unmarshal(msg.Data, data) + if err != nil { + fmt.Println("Unmarshal msg data error", err) + return + } + + fmt.Println("-----> Recv Server msgId= ", + msg.Id, " len= ", msg.MsgLen, " data = ", data) + } + + time.Sleep(1 * time.Second) + } + fmt.Println("-----> stop for") + + for { + + time.Sleep(5 * time.Second) + + fmt.Println("-----> start talk") + + talk(conn,"我是你爸爸~") + } + + +} + +func talk(conn net.Conn,content string) { + + data := &pMsg.Talk{ + Content: content, + Name: "陆离", + } + + marshalMsg, err := proto.Marshal(data) + if err != nil { + fmt.Println("Marshal msg err :", err) + return + } + + dp := wkNet.NewDataPack() + binaryMsg, err := dp.Pack(wkNet.NewMessage(2, marshalMsg)) + if err != nil { + fmt.Println("Pack error", err) + } + + if _, err := conn.Write(binaryMsg); err != nil { + fmt.Println("conn Write error", err) + return + } + + binaryHead := make([]byte, dp.GetHeadLen()) + if _, err := io.ReadFull(conn, binaryHead); err != nil { + fmt.Println("read head error", err) + return + } + + msgHead, err := dp.Unpack(binaryHead) + if err != nil { + fmt.Println("client unpack msgHead error", err) + return + } + + if msgHead.GetMsgLen() > 0 { + msg := msgHead.(*wkNet.Message) + msg.SetData(make([]byte, msg.GetMsgLen())) + + if _, err := io.ReadFull(conn, msg.Data); err != nil { + fmt.Println("read msg data error", err) + return + } + + data := &pMsg.BroadCast{} + err := proto.Unmarshal(msg.Data, data) + if err != nil { + fmt.Println("Unmarshal msg data error", err) + return + } + + fmt.Println("-----> Recv Server msgId= ", + msg.Id, " len= ", msg.MsgLen, " data = ", data) + } +} diff --git a/mmo/Client1.go b/mmo/Client1.go new file mode 100644 index 0000000..99d05fc --- /dev/null +++ b/mmo/Client1.go @@ -0,0 +1,137 @@ +package main + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "io" + "net" + "time" + pMsg "wukong/mmo/pb/msg" + wkNet "wukong/net" +) + +func main() { + + fmt.Println("--------------> 陆真人频道 <--------------") + time.Sleep(1 + time.Second) + + conn, err := net.Dial("tcp", "127.0.0.1:9527") + if err != nil { + fmt.Println("client start err exit! ") + return + } + + for i := 0; i < 2; i++ { + dp := wkNet.NewDataPack() + //binaryMsg, err := dp.Pack(wkNet.NewMessage(0, []byte("LiuLiGamesV0.9 client0 Test Message "))) + //if err != nil { + // fmt.Println("Pack error", err) + //} + // + //if _, err := conn.Write(binaryMsg); err != nil { + // fmt.Println("conn Write error", err) + // return + //} + + binaryHead := make([]byte, dp.GetHeadLen()) + if _, err := io.ReadFull(conn, binaryHead); err != nil { + fmt.Println("read head error", err) + return + } + + msgHead, err := dp.Unpack(binaryHead) + if err != nil { + fmt.Println("client unpack msgHead error", err) + break + } + + if msgHead.GetMsgLen() > 0 { + msg := msgHead.(*wkNet.Message) + msg.SetData(make([]byte, msg.GetMsgLen())) + + if _, err := io.ReadFull(conn, msg.Data); err != nil { + fmt.Println("read msg data error", err) + return + } + + data := &pMsg.SyncPid{} + err := proto.Unmarshal(msg.Data, data) + if err != nil { + fmt.Println("Unmarshal msg data error", err) + return + } + + fmt.Println("-----> Recv Server msgId= ", + msg.Id, " len= ", msg.MsgLen, " data = ", data) + } + + time.Sleep(1 * time.Second) + } + + fmt.Println("-----> stop for") + for { + + time.Sleep(6 * time.Second) + + fmt.Println("-----> start talk") + + talk1(conn, "我嫩爹!!!") + } +} + +func talk1(conn net.Conn, content string) { + + data := &pMsg.Talk{ + Content: content, + Name: "陆真人", + } + + marshalMsg, err := proto.Marshal(data) + if err != nil { + fmt.Println("Marshal msg err :", err) + return + } + + dp := wkNet.NewDataPack() + binaryMsg, err := dp.Pack(wkNet.NewMessage(2, marshalMsg)) + if err != nil { + fmt.Println("Pack error", err) + } + + if _, err := conn.Write(binaryMsg); err != nil { + fmt.Println("conn Write error", err) + return + } + + binaryHead := make([]byte, dp.GetHeadLen()) + if _, err := io.ReadFull(conn, binaryHead); err != nil { + fmt.Println("read head error", err) + return + } + + msgHead, err := dp.Unpack(binaryHead) + if err != nil { + fmt.Println("client unpack msgHead error", err) + return + } + + if msgHead.GetMsgLen() > 0 { + msg := msgHead.(*wkNet.Message) + msg.SetData(make([]byte, msg.GetMsgLen())) + + if _, err := io.ReadFull(conn, msg.Data); err != nil { + fmt.Println("read msg data error", err) + return + } + + data := &pMsg.BroadCast{} + err := proto.Unmarshal(msg.Data, data) + if err != nil { + fmt.Println("Unmarshal msg data error", err) + return + } + + fmt.Println("-----> Recv Server msgId= ", + msg.Id, " len= ", msg.MsgLen, " data = ", data) + } +} diff --git a/mmo/api/WorldChat.go b/mmo/api/WorldChat.go new file mode 100644 index 0000000..7d9e87a --- /dev/null +++ b/mmo/api/WorldChat.go @@ -0,0 +1,33 @@ +package api + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "wukong/iface" + "wukong/mmo/core" + "wukong/mmo/pb/msg" + "wukong/net" +) + +type WorldChatApi struct { + net.BaseRouter +} + +func (wc WorldChatApi) Handle(request iface.IRequest) { + protoMag := &msg.Talk{} + err := proto.Unmarshal(request.GetData(), protoMag) + if err != nil { + fmt.Println("talk Unmarshal error : ", err) + return + } + + pId, err := request.GetConnection().GetProperty("PId") + if err != nil { + fmt.Println("get Property PId error : ", err) + return + } + + player := core.WorldManagerObj.GetPlayerByPId(pId.(int32)) + + player.Talk(fmt.Sprintf("玩家 [%s] : %s", protoMag.Name, protoMag.Content)) +} diff --git a/mmo/conf/conf.yaml b/mmo/conf/conf.yaml new file mode 100644 index 0000000..acada37 --- /dev/null +++ b/mmo/conf/conf.yaml @@ -0,0 +1,5 @@ +name: "MMO Games" +Host: "0.0.0.0" +TcpPort: 9527 +MaxConn: 3000 +WorkerPoolSize: 10 \ No newline at end of file diff --git a/mmo/core/Grid.go b/mmo/core/Grid.go new file mode 100644 index 0000000..77dcd3c --- /dev/null +++ b/mmo/core/Grid.go @@ -0,0 +1,55 @@ +package core + +import ( + "fmt" + "sync" +) + +type Grid struct { + GId int + MinX int + MaxX int + MinY int + MaxY int + PlayerIds map[int]bool + PIdLock sync.RWMutex +} + +func NewGrid(gId, minX, maxX, minY, maxY int) *Grid { + return &Grid{ + GId: gId, + MinX: minX, + MaxX: maxX, + MinY: minY, + MaxY: maxY, + PlayerIds: make(map[int]bool), + } +} + +func (g *Grid) Add(playerId int) { + g.PIdLock.Lock() + defer g.PIdLock.Unlock() + + g.PlayerIds[playerId] = true +} + +func (g *Grid) Remove(playerId int) { + g.PIdLock.Lock() + defer g.PIdLock.Unlock() + + delete(g.PlayerIds, playerId) +} + +func (g *Grid) GetPlayerIds() (playerIds []int) { + g.PIdLock.RLock() + defer g.PIdLock.RUnlock() + for k, _ := range g.PlayerIds { + playerIds = append(playerIds, k) + } + return +} + +func (g *Grid) String() string { + return fmt.Sprintf("Grid:%d, minX:%d, maxX:%d, minY:%d, maxY:%d, playerIds:%v", + g.GId, g.MinX, g.MaxX, g.MinY, g.MaxY, g.PlayerIds) +} diff --git a/mmo/core/Player.go b/mmo/core/Player.go new file mode 100644 index 0000000..26df671 --- /dev/null +++ b/mmo/core/Player.go @@ -0,0 +1,99 @@ +package core + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "math/rand" + "sync" + "wukong/iface" + "wukong/mmo/pb/msg" +) + +type Player struct { + PId int32 + Conn iface.IConnection + X float32 + Y float32 + Z float32 + V float32 +} + +var id int32 = 0 +var idLock sync.Mutex + +func NewPlayer(conn iface.IConnection) *Player { + idLock.Lock() + id++ + idLock.Unlock() + + return &Player{ + PId: id, + Conn: conn, + X: float32(160 + rand.Intn(10)), + Y: 0, + Z: float32(140 + rand.Intn(20)), + V: 0, + } +} + +func (p *Player) SendMsg(msgId uint32, data proto.Message) { + marshalMsg, err := proto.Marshal(data) + if err != nil { + fmt.Println("Marshal msg err :", err) + return + } + + if p.Conn == nil { + fmt.Println("conn in player is nil") + return + } + + if err := p.Conn.SendMsg(msgId, marshalMsg); err != nil { + fmt.Println("player sendMsg error!") + return + } + + return +} + +func (p *Player) SyncPId() { + protoMsg := &msg.SyncPid{ + PId: p.PId, + } + + p.SendMsg(1, protoMsg) +} + +func (p *Player) BroadCastStartPosition() { + protoMsg := &msg.BroadCast{ + PId: p.PId, + Tp: 2, + Data: &msg.BroadCast_P{ + P: &msg.Position{ + X: p.X, + Y: p.Y, + Z: p.Z, + V: p.V, + }, + }, + } + + p.SendMsg(200, protoMsg) +} + +func (p *Player) Talk(content string) { + protoMsg := &msg.BroadCast{ + PId: p.PId, + Tp: 1, + Data: &msg.BroadCast_Content{ + Content: content, + }, + } + + players := WorldManagerObj.GetAllPlayers() + + for _, player := range players { + player.SendMsg(200, protoMsg) + } + +} diff --git a/mmo/core/WorldManager.go b/mmo/core/WorldManager.go new file mode 100644 index 0000000..fd3d364 --- /dev/null +++ b/mmo/core/WorldManager.go @@ -0,0 +1,55 @@ +package core + +import "sync" + +type WorldManager struct { + AoiManager *AoiManager + + Players map[int32]*Player + + pLock sync.RWMutex +} + +var WorldManagerObj *WorldManager + +func init() { + WorldManagerObj = &WorldManager{ + AoiManager: NewAoiManager(AOI_MIN_X, AOI_MAX_X, AOI_CNT_X, AOI_MIN_Y, AOI_MAX_Y, AOI_CNT_Y), + Players: make(map[int32]*Player), + } +} + +func (wm *WorldManager) AddPlayer(player *Player) { + wm.pLock.Lock() + wm.Players[player.PId] = player + wm.pLock.Unlock() + + wm.AoiManager.AddToGridByPos(int(player.PId), player.X, player.Z) +} + +func (wm *WorldManager) RemovePlayer(pId int32) { + player := wm.Players[pId] + wm.AoiManager.RemoveFromGridByPos(int(player.PId), player.X, player.Z) + + wm.pLock.Lock() + delete(wm.Players, pId) + wm.pLock.Unlock() +} + +func (wm *WorldManager) GetPlayerByPId(pId int32) *Player { + wm.pLock.RLock() + defer wm.pLock.RUnlock() + return wm.Players[pId] +} + +func (wm *WorldManager) GetAllPlayers() []*Player { + wm.pLock.RLock() + defer wm.pLock.RUnlock() + + players := make([]*Player, 0) + + for _, value := range wm.Players { + players = append(players, value) + } + return players +} diff --git a/mmo/core/aoi.go b/mmo/core/aoi.go new file mode 100644 index 0000000..dc95fc3 --- /dev/null +++ b/mmo/core/aoi.go @@ -0,0 +1,149 @@ +package core + +import ( + "fmt" +) + +const( + AOI_MIN_X int = 85 + AOI_MAX_X int = 410 + AOI_CNT_X int = 10 + AOI_MIN_Y int = 75 + AOI_MAX_Y int = 400 + AOI_CNT_Y int = 20 +) + +type AoiManager struct { + MinX int + MaxX int + CntX int + + MinY int + MaxY int + CntY int + + GrIds map[int]*Grid +} + +func NewAoiManager(minX, maxX, cntX, minY, maxY, cntY int) *AoiManager { + apiManager := &AoiManager{ + MinX: minX, + MaxX: maxX, + CntX: cntX, + MinY: minY, + MaxY: maxY, + CntY: cntY, + GrIds: make(map[int]*Grid), + } + + for y := 0; y < cntY; y++ { + for x := 0; x < cntX; x++ { + gId := y*cntX + x + + apiManager.GrIds[gId] = NewGrid(gId, + apiManager.MinX+x*apiManager.GrIdWidth(), + apiManager.MinX+(x+1)*apiManager.GrIdWidth(), + apiManager.MinY+y*apiManager.GrIdLength(), + apiManager.MinY+(y+1)*apiManager.GrIdLength()) + } + } + + return apiManager +} + +func (am *AoiManager) GrIdWidth() int { + return (am.MaxX - am.MinX) / am.CntX +} + +func (am *AoiManager) GrIdLength() int { + return (am.MaxY - am.MinY) / am.CntY +} + +func (am *AoiManager) String() string { + s := fmt.Sprintf("AoiManager:\n MinX:%d,MaxX:%d,CntX:%d,MinY:%d,MaxY:%d,CntY:%d\n GrIds in AoiManager", + am.MinX, am.MaxX, am.CntX, am.MinY, am.MaxY, am.CntY) + + for _, grId := range am.GrIds { + s += fmt.Sprintln(grId) + } + return s +} + +func (am *AoiManager) GetSurroundGrIdsByGid(gId int) (grids []*Grid) { + if _, ok := am.GrIds[gId]; !ok { + return + } + + grids = append(grids, am.GrIds[gId]) + + idx := gId % am.CntX + + if idx > 0 { + grids = append(grids, am.GrIds[gId-1]) + } + if idx < am.CntX-1 { + grids = append(grids, am.GrIds[gId+1]) + } + + gIdsX := make([]int, 0, len(grids)) + + for _, value := range grids { + gIdsX = append(gIdsX, value.GId) + } + + for _, value := range gIdsX { + idY := value / am.CntX + if idY > 0 { + grids = append(grids, am.GrIds[value-am.CntX]) + } + + if idY < am.CntY-1 { + grids = append(grids, am.GrIds[value+am.CntX]) + } + } + + return +} + +func (am *AoiManager) GetGIdByPos(x, y float32) int { + idx := (int(x) - am.MinX) / am.GrIdWidth() + idy := (int(y) - am.MinY) / am.GrIdLength() + + return idy*am.CntX + idx +} + +func (am *AoiManager) GetPIdsByPos(x, y float32) (playerIds []int) { + gId := am.GetGIdByPos(x, y) + grIds := am.GetSurroundGrIdsByGid(gId) + + for _, value := range grIds { + playerIds = append(playerIds, value.GetPlayerIds()...) + fmt.Printf("======》 grid id : %d, pids : %v =======\n", value.GId, value.GetPlayerIds()) + } + return +} + +func (am *AoiManager) AddPIdToGrId(pId, gId int) { + am.GrIds[gId].Add(pId) +} + +func (am *AoiManager) RemovePIdFromGrId(pId, gId int) { + am.GrIds[gId].Remove(pId) +} + +func (am *AoiManager) GetPIdByGId(gId int) (playerIds []int) { + playerIds = am.GrIds[gId].GetPlayerIds() + return +} + +func (am *AoiManager) AddToGridByPos(pId int, x, y float32) { + gId := am.GetGIdByPos(x, y) + grId := am.GrIds[gId] + grId.Add(pId) +} + +func (am *AoiManager) RemoveFromGridByPos(pId int, x, y float32) { + gId := am.GetGIdByPos(x, y) + grId := am.GrIds[gId] + grId.Remove(pId) +} diff --git a/mmo/core/aoi_test.go b/mmo/core/aoi_test.go new file mode 100644 index 0000000..fb755a5 --- /dev/null +++ b/mmo/core/aoi_test.go @@ -0,0 +1,29 @@ +package core + +import ( + "fmt" + "testing" +) + +func TestNewAoiManager(t *testing.T) { + aoi := NewAoiManager(0, 300, 5, 0, 300, 5) + + fmt.Println(aoi) +} + +func TestAoiManager_GetSurroundGrIdsByGid(t *testing.T) { + aoi := NewAoiManager(0, 300, 5, 0, 300, 5) + + for k, _ := range aoi.GrIds { + grids := aoi.GetSurroundGrIdsByGid(k) + fmt.Println("gid = ", k, "grids len = ", len(grids)) + + gIds := make([]int, 0, len(grids)) + + for _, value := range grids { + gIds = append(gIds, value.GId) + } + fmt.Println("grId = Ids are", gIds) + } + +} diff --git a/mmo/main.go b/mmo/main.go new file mode 100644 index 0000000..24ccaf8 --- /dev/null +++ b/mmo/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "wukong/iface" + "wukong/mmo/api" + "wukong/mmo/core" + "wukong/net" +) + +func OnConnectionAdd(conn iface.IConnection) { + player := core.NewPlayer(conn) + + player.SyncPId() + + player.BroadCastStartPosition() + + core.WorldManagerObj.AddPlayer(player) + + conn.SetProperty("PId", player.PId) + + fmt.Println("===========》 Player id = ", player.PId, "is arrived ========") +} + +func main() { + s := net.NewServer() + + s.SetOnConnStart(OnConnectionAdd) + + s.AddRouter(2, &api.WorldChatApi{}) + + s.Serve() +} diff --git a/mmo/pb/gen-golang.bat b/mmo/pb/gen-golang.bat new file mode 100644 index 0000000..0c05672 --- /dev/null +++ b/mmo/pb/gen-golang.bat @@ -0,0 +1 @@ +protoc --go_out=. *.proto \ No newline at end of file diff --git a/mmo/pb/gen-golang.sh b/mmo/pb/gen-golang.sh new file mode 100644 index 0000000..f21408f --- /dev/null +++ b/mmo/pb/gen-golang.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +protoc --go_out=. *.proto \ No newline at end of file diff --git a/mmo/pb/msg.proto b/mmo/pb/msg.proto new file mode 100644 index 0000000..83260fb --- /dev/null +++ b/mmo/pb/msg.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; +package pb; +option csharp_namespace = "Pb"; +option go_package = "./msg"; + +//同步玩家id +message SyncPid{ + int32 PId = 1; +} + +//位置信息 +message Position{ + float x = 1; + float y = 2; + float z = 3; + float v = 4; +} + +//广播消息 +message BroadCast{ + int32 PId = 1; + int32 Tp = 2; //1-世界聊天、2-玩家位置、3-动作、4-移动后坐标信息更新 + oneof Data{ + string content = 3; //聊天信息 + Position P = 4; //广播位置 + int32 ActionData = 5;//玩家动作 + } +} + +//世界聊天 +message Talk{ + string content = 1; + string name = 2; +} + + diff --git a/mmo/pb/msg/msg.pb.go b/mmo/pb/msg/msg.pb.go new file mode 100644 index 0000000..6c743d2 --- /dev/null +++ b/mmo/pb/msg/msg.pb.go @@ -0,0 +1,442 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.17.3 +// source: msg.proto + +package msg + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +//同步玩家id +type SyncPid struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PId int32 `protobuf:"varint,1,opt,name=PId,proto3" json:"PId,omitempty"` +} + +func (x *SyncPid) Reset() { + *x = SyncPid{} + if protoimpl.UnsafeEnabled { + mi := &file_msg_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncPid) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncPid) ProtoMessage() {} + +func (x *SyncPid) ProtoReflect() protoreflect.Message { + mi := &file_msg_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncPid.ProtoReflect.Descriptor instead. +func (*SyncPid) Descriptor() ([]byte, []int) { + return file_msg_proto_rawDescGZIP(), []int{0} +} + +func (x *SyncPid) GetPId() int32 { + if x != nil { + return x.PId + } + return 0 +} + +//位置信息 +type Position struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + X float32 `protobuf:"fixed32,1,opt,name=x,proto3" json:"x,omitempty"` + Y float32 `protobuf:"fixed32,2,opt,name=y,proto3" json:"y,omitempty"` + Z float32 `protobuf:"fixed32,3,opt,name=z,proto3" json:"z,omitempty"` + V float32 `protobuf:"fixed32,4,opt,name=v,proto3" json:"v,omitempty"` +} + +func (x *Position) Reset() { + *x = Position{} + if protoimpl.UnsafeEnabled { + mi := &file_msg_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Position) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Position) ProtoMessage() {} + +func (x *Position) ProtoReflect() protoreflect.Message { + mi := &file_msg_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Position.ProtoReflect.Descriptor instead. +func (*Position) Descriptor() ([]byte, []int) { + return file_msg_proto_rawDescGZIP(), []int{1} +} + +func (x *Position) GetX() float32 { + if x != nil { + return x.X + } + return 0 +} + +func (x *Position) GetY() float32 { + if x != nil { + return x.Y + } + return 0 +} + +func (x *Position) GetZ() float32 { + if x != nil { + return x.Z + } + return 0 +} + +func (x *Position) GetV() float32 { + if x != nil { + return x.V + } + return 0 +} + +//广播消息 +type BroadCast struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PId int32 `protobuf:"varint,1,opt,name=PId,proto3" json:"PId,omitempty"` + Tp int32 `protobuf:"varint,2,opt,name=Tp,proto3" json:"Tp,omitempty"` //1-世界聊天、2-玩家位置、3-动作、4-移动后坐标信息更新 + // Types that are assignable to Data: + // *BroadCast_Content + // *BroadCast_P + // *BroadCast_ActionData + Data isBroadCast_Data `protobuf_oneof:"Data"` +} + +func (x *BroadCast) Reset() { + *x = BroadCast{} + if protoimpl.UnsafeEnabled { + mi := &file_msg_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BroadCast) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BroadCast) ProtoMessage() {} + +func (x *BroadCast) ProtoReflect() protoreflect.Message { + mi := &file_msg_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BroadCast.ProtoReflect.Descriptor instead. +func (*BroadCast) Descriptor() ([]byte, []int) { + return file_msg_proto_rawDescGZIP(), []int{2} +} + +func (x *BroadCast) GetPId() int32 { + if x != nil { + return x.PId + } + return 0 +} + +func (x *BroadCast) GetTp() int32 { + if x != nil { + return x.Tp + } + return 0 +} + +func (m *BroadCast) GetData() isBroadCast_Data { + if m != nil { + return m.Data + } + return nil +} + +func (x *BroadCast) GetContent() string { + if x, ok := x.GetData().(*BroadCast_Content); ok { + return x.Content + } + return "" +} + +func (x *BroadCast) GetP() *Position { + if x, ok := x.GetData().(*BroadCast_P); ok { + return x.P + } + return nil +} + +func (x *BroadCast) GetActionData() int32 { + if x, ok := x.GetData().(*BroadCast_ActionData); ok { + return x.ActionData + } + return 0 +} + +type isBroadCast_Data interface { + isBroadCast_Data() +} + +type BroadCast_Content struct { + Content string `protobuf:"bytes,3,opt,name=content,proto3,oneof"` //聊天信息 +} + +type BroadCast_P struct { + P *Position `protobuf:"bytes,4,opt,name=P,proto3,oneof"` //广播位置 +} + +type BroadCast_ActionData struct { + ActionData int32 `protobuf:"varint,5,opt,name=ActionData,proto3,oneof"` //玩家动作 +} + +func (*BroadCast_Content) isBroadCast_Data() {} + +func (*BroadCast_P) isBroadCast_Data() {} + +func (*BroadCast_ActionData) isBroadCast_Data() {} + +//世界聊天 +type Talk struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *Talk) Reset() { + *x = Talk{} + if protoimpl.UnsafeEnabled { + mi := &file_msg_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Talk) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Talk) ProtoMessage() {} + +func (x *Talk) ProtoReflect() protoreflect.Message { + mi := &file_msg_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Talk.ProtoReflect.Descriptor instead. +func (*Talk) Descriptor() ([]byte, []int) { + return file_msg_proto_rawDescGZIP(), []int{3} +} + +func (x *Talk) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +func (x *Talk) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +var File_msg_proto protoreflect.FileDescriptor + +var file_msg_proto_rawDesc = []byte{ + 0x0a, 0x09, 0x6d, 0x73, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, + 0x1b, 0x0a, 0x07, 0x53, 0x79, 0x6e, 0x63, 0x50, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x50, 0x49, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x50, 0x49, 0x64, 0x22, 0x42, 0x0a, 0x08, + 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x02, 0x52, 0x01, 0x79, 0x12, 0x0c, 0x0a, 0x01, 0x7a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, + 0x01, 0x7a, 0x12, 0x0c, 0x0a, 0x01, 0x76, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x01, 0x76, + 0x22, 0x91, 0x01, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x43, 0x61, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x50, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x50, 0x49, 0x64, + 0x12, 0x0e, 0x0a, 0x02, 0x54, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x54, 0x70, + 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x01, + 0x50, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x01, 0x50, 0x12, 0x20, 0x0a, 0x0a, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, + 0x52, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x04, + 0x44, 0x61, 0x74, 0x61, 0x22, 0x34, 0x0a, 0x04, 0x54, 0x61, 0x6c, 0x6b, 0x12, 0x18, 0x0a, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0c, 0x5a, 0x05, 0x2e, 0x2f, + 0x6d, 0x73, 0x67, 0xaa, 0x02, 0x02, 0x50, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_msg_proto_rawDescOnce sync.Once + file_msg_proto_rawDescData = file_msg_proto_rawDesc +) + +func file_msg_proto_rawDescGZIP() []byte { + file_msg_proto_rawDescOnce.Do(func() { + file_msg_proto_rawDescData = protoimpl.X.CompressGZIP(file_msg_proto_rawDescData) + }) + return file_msg_proto_rawDescData +} + +var file_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_msg_proto_goTypes = []interface{}{ + (*SyncPid)(nil), // 0: pb.SyncPid + (*Position)(nil), // 1: pb.Position + (*BroadCast)(nil), // 2: pb.BroadCast + (*Talk)(nil), // 3: pb.Talk +} +var file_msg_proto_depIdxs = []int32{ + 1, // 0: pb.BroadCast.P:type_name -> pb.Position + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_msg_proto_init() } +func file_msg_proto_init() { + if File_msg_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_msg_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SyncPid); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_msg_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Position); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_msg_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BroadCast); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_msg_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Talk); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_msg_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*BroadCast_Content)(nil), + (*BroadCast_P)(nil), + (*BroadCast_ActionData)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_msg_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_msg_proto_goTypes, + DependencyIndexes: file_msg_proto_depIdxs, + MessageInfos: file_msg_proto_msgTypes, + }.Build() + File_msg_proto = out.File + file_msg_proto_rawDesc = nil + file_msg_proto_goTypes = nil + file_msg_proto_depIdxs = nil +} diff --git a/net/MsgHandler.go b/net/MsgHandler.go index 3886eba..b802bdb 100644 --- a/net/MsgHandler.go +++ b/net/MsgHandler.go @@ -25,6 +25,7 @@ func (mh *MsgHandler) DoMsgHandler(request iface.IRequest) { handler, ok := mh.Apis[request.GetMsgId()] if !ok { fmt.Println(" api msgId = ", request.GetMsgId(), "is not found Need Register") + return } handler.PreHandle(request) diff --git a/utils/globalobj.go b/utils/globalobj.go index b2f461e..b8b0d97 100644 --- a/utils/globalobj.go +++ b/utils/globalobj.go @@ -3,6 +3,9 @@ package utils import ( "gopkg.in/yaml.v3" "io/ioutil" + "net" + "net/http" + "time" "wukong/iface" ) @@ -46,3 +49,14 @@ func init() { GlobalObject.Reload() } + +var HTTPTransport = &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, // 连接超时时间 + KeepAlive: 60 * time.Second, // 保持长连接的时间 + }).DialContext, // 设置连接的参数 + MaxIdleConns: 500, // 最大空闲连接 + IdleConnTimeout: 60 * time.Second, // 空闲连接的超时时间 + ExpectContinueTimeout: 30 * time.Second, // 等待服务第一个响应的超时时间 + MaxIdleConnsPerHost: 100, // 每个host保持的空闲连接数 +} \ No newline at end of file