添加了节点服务器,各个服务器之间支持多对多

This commit is contained in:
flswld committed 2022-12-24 04:14:33 +08:00
1 parent 16dd9c1e87
commit 7e86669628
92 files changed
+1429 -287

No files matched your search

+5 -1
View File
@@ -23,6 +23,10 @@ gen:
--go_out=paths=source_relative:gs/api \ --go_out=paths=source_relative:gs/api \
--natsrpc_out=paths=source_relative:gs/api \ --natsrpc_out=paths=source_relative:gs/api \
gs/api/*.proto gs/api/*.proto
protoc \
--proto_path=node/api \
--go_out=paths=source_relative:node/api \
--natsrpc_out=paths=source_relative:node/api \
node/api/*.proto
#cd protocol/proto && make gen #cd protocol/proto && make gen
+9 -8
View File
@@ -4,19 +4,20 @@ hk4e game server
## 开发快速上手 ## 开发快速上手
* Go >= 1.19 * Go >= 1.18
1. 首次需要安装工具 `make dev_tool` 1. 首次需要安装工具 `make dev_tool`
1. 生成协议 `make gen` 2. 生成协议 `make gen`
## 快速运行 ## 快速运行
* mongodb * mongodb
* nats-server * nats-server
1. 启动http登录服务器 `cmd/dispatch && go run .` 1. 启动节点服务器 `cmd/node && go run .`
2. 启动网关服务器 `cd cmd/gate && go run .` 2. 启动http登录服务器 `cmd/dispatch && go run .`
3. 启动游戏服务器 `cd cmd/gs && go run .` 3. 启动网关服务器 `cd cmd/gate && go run .`
4. 启动游戏管理服务器 `cmd/gm && go run .` 4. 启动战斗服务器 `cmd/fight && go run .`
5. 启动战斗服务器 `cmd/fight && go run .` 5. 启动寻路服务器 `cmd/pathfinding && go run .`
6. 启动寻路服务器 `cmd/pathfinding && go run .` 6. 启动游戏服务器 `cd cmd/gs && go run .`
7. 启动游戏管理服务器 `cmd/gm && go run .`
+7 -1
View File
@@ -8,6 +8,7 @@ import (
"os" "os"
"hk4e/dispatch/app" "hk4e/dispatch/app"
"hk4e/pkg/statsviz_serve"
) )
var ( var (
@@ -16,7 +17,12 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
// go statsviz_serve.Serve("0.0.0.0:2345") go func() {
err := statsviz_serve.Serve("0.0.0.0:2345")
if err != nil {
panic(err)
}
}()
err := app.Run(context.TODO(), *config) err := app.Run(context.TODO(), *config)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+4 -1
View File
@@ -8,6 +8,7 @@ import (
"os" "os"
"hk4e/fight/app" "hk4e/fight/app"
"hk4e/pkg/statsviz_serve"
) )
var ( var (
@@ -16,7 +17,9 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
// go statsviz_serve.Serve("0.0.0.0:2345") go func() {
_ = statsviz_serve.Serve("0.0.0.0:5678")
}()
err := app.Run(context.TODO(), *config) err := app.Run(context.TODO(), *config)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+3 -1
View File
@@ -17,7 +17,9 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
go statsviz_serve.Serve("0.0.0.0:2345") go func() {
_ = statsviz_serve.Serve("0.0.0.0:3456")
}()
err := app.Run(context.TODO(), *config) err := app.Run(context.TODO(), *config)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+8
View File
@@ -4,9 +4,11 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
_ "net/http/pprof"
"os" "os"
"hk4e/gm/app" "hk4e/gm/app"
"hk4e/pkg/statsviz_serve"
) )
var ( var (
@@ -15,6 +17,12 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
go func() {
err := statsviz_serve.Serve("0.0.0.0:7890")
if err != nil {
panic(err)
}
}()
err := app.Run(context.TODO(), *config) err := app.Run(context.TODO(), *config)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+3 -1
View File
@@ -17,7 +17,9 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
go statsviz_serve.Serve("0.0.0.0:3456") go func() {
_ = statsviz_serve.Serve("0.0.0.0:4567")
}()
err := app.Run(context.TODO(), *config) err := app.Run(context.TODO(), *config)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+23
View File
@@ -0,0 +1,23 @@
package main
import (
"context"
"hk4e/node/app"
"github.com/spf13/cobra"
)
// NodeCmd 检查配表命令
func NodeCmd() *cobra.Command {
var cfg string
c := &cobra.Command{
Use: "node",
Short: "node server",
RunE: func(cmd *cobra.Command, args []string) error {
return app.Run(context.Background(), cfg)
},
}
c.Flags().StringVar(&cfg, "config", "application.toml", "config file")
return c
}
+12
View File
@@ -0,0 +1,12 @@
[hk4e]
kcp_addr = "127.0.0.1"
kcp_port = 22103
[logger]
level = "DEBUG"
mode = "BOTH"
track = true
max_size = 10485760
[mq]
nats_url = "nats://nats:4222"
+31
View File
@@ -0,0 +1,31 @@
package main
import (
"context"
"flag"
"fmt"
_ "net/http/pprof"
"os"
"hk4e/node/app"
"hk4e/pkg/statsviz_serve"
)
var (
config = flag.String("config", "application.toml", "config file")
)
func main() {
flag.Parse()
go func() {
err := statsviz_serve.Serve("0.0.0.0:1234")
if err != nil {
panic(err)
}
}()
err := app.Run(context.TODO(), *config)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
+4 -1
View File
@@ -8,6 +8,7 @@ import (
"os" "os"
"hk4e/pathfinding/app" "hk4e/pathfinding/app"
"hk4e/pkg/statsviz_serve"
) )
var ( var (
@@ -16,7 +17,9 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
// go statsviz_serve.Serve("0.0.0.0:2345") go func() {
_ = statsviz_serve.Serve("0.0.0.0:6789")
}()
err := app.Run(context.TODO(), *config) err := app.Run(context.TODO(), *config)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+10
View File
@@ -10,12 +10,20 @@ import (
pb "google.golang.org/protobuf/proto" pb "google.golang.org/protobuf/proto"
) )
// 用于服务器之间传输游戏协议
// 仅用于传递数据平面(client<--->server)和控制平面(server<--->server)的消息
// 目前是全部消息都走NATS 之后可以做优化服务器之间socket直连
// 请不要用这个来搞RPC写一大堆异步回调!!!
// 要用RPC有专门的NATSRPC
type MessageQueue struct { type MessageQueue struct {
natsConn *nats.Conn natsConn *nats.Conn
natsMsgChan chan *nats.Msg natsMsgChan chan *nats.Msg
netMsgInput chan *NetMsg netMsgInput chan *NetMsg
netMsgOutput chan *NetMsg netMsgOutput chan *NetMsg
cmdProtoMap *cmd.CmdProtoMap cmdProtoMap *cmd.CmdProtoMap
serverType string
appId string
} }
func NewMessageQueue(serverType string, appId string) (r *MessageQueue) { func NewMessageQueue(serverType string, appId string) (r *MessageQueue) {
@@ -35,6 +43,8 @@ func NewMessageQueue(serverType string, appId string) (r *MessageQueue) {
r.netMsgInput = make(chan *NetMsg, 1000) r.netMsgInput = make(chan *NetMsg, 1000)
r.netMsgOutput = make(chan *NetMsg, 1000) r.netMsgOutput = make(chan *NetMsg, 1000)
r.cmdProtoMap = cmd.NewCmdProtoMap() r.cmdProtoMap = cmd.NewCmdProtoMap()
r.serverType = serverType
r.appId = appId
go r.recvHandler() go r.recvHandler()
go r.sendHandler() go r.sendHandler()
return r return r
+21 -16
View File
@@ -9,12 +9,14 @@ const (
) )
type NetMsg struct { type NetMsg struct {
MsgType uint8 `msgpack:"MsgType"` MsgType uint8 `msgpack:"MsgType"`
EventId uint16 `msgpack:"EventId"` EventId uint16 `msgpack:"EventId"`
Topic string `msgpack:"-"` Topic string `msgpack:"-"`
GameMsg *GameMsg `msgpack:"GameMsg"` GameMsg *GameMsg `msgpack:"GameMsg"`
FightMsg *FightMsg `msgpack:"FightMsg"` FightMsg *FightMsg `msgpack:"FightMsg"`
ConnCtrlMsg *ConnCtrlMsg `msgpack:"ConnCtrlMsg"` ConnCtrlMsg *ConnCtrlMsg `msgpack:"ConnCtrlMsg"`
OriginServerType string `msgpack:"OriginServerType"`
OriginServerAppId string `msgpack:"OriginServerAppId"`
} }
const ( const (
@@ -33,15 +35,17 @@ type GameMsg struct {
const ( const (
ClientRttNotify = iota ClientRttNotify = iota
ClientTimeNotify ClientTimeNotify
FightServerSelectNotify
KickPlayerNotify KickPlayerNotify
) )
type ConnCtrlMsg struct { type ConnCtrlMsg struct {
UserId uint32 `msgpack:"UserId"` UserId uint32 `msgpack:"UserId"`
ClientRtt uint32 `msgpack:"ClientRtt"` ClientRtt uint32 `msgpack:"ClientRtt"`
ClientTime uint32 `msgpack:"ClientTime"` ClientTime uint32 `msgpack:"ClientTime"`
KickUserId uint32 `msgpack:"KickUserId"` FightServerAppId string `msgpack:"FightServerAppId"`
KickReason uint32 `msgpack:"KickReason"` KickUserId uint32 `msgpack:"KickUserId"`
KickReason uint32 `msgpack:"KickReason"`
} }
const ( const (
@@ -52,9 +56,10 @@ const (
) )
type FightMsg struct { type FightMsg struct {
FightRoutineId uint32 `msgpack:"FightRoutineId"` FightRoutineId uint32 `msgpack:"FightRoutineId"`
EntityId uint32 `msgpack:"EntityId"` EntityId uint32 `msgpack:"EntityId"`
FightPropMap map[uint32]float32 `msgpack:"FightPropMap"` FightPropMap map[uint32]float32 `msgpack:"FightPropMap"`
Uid uint32 `msgpack:"Uid"` Uid uint32 `msgpack:"Uid"`
AvatarGuid uint64 `msgpack:"AvatarGuid"` AvatarGuid uint64 `msgpack:"AvatarGuid"`
GateServerAppId string `msgpack:"GateServerAppId"`
} }
+23 -12
View File
@@ -1,37 +1,48 @@
package mq package mq
import ( import (
"strings" "hk4e/node/api"
) )
const ( func (m *MessageQueue) getOriginServer() (originServerType string, originServerAppId string) {
GATE = "GATE_${APPID}_HK4E" originServerType = m.serverType
GS = "GS_${APPID}_HK4E" originServerAppId = m.appId
FIGHT = "FIGHT_${APPID}_HK4E" return originServerType, originServerAppId
PATHFINDING = "PATHFINDING_${APPID}_HK4E" }
)
func (m *MessageQueue) getTopic(serverType string, appId string) string { func (m *MessageQueue) getTopic(serverType string, appId string) string {
topic := strings.ReplaceAll(serverType, "${APPID}", appId) topic := serverType + "_" + appId + "_" + "HK4E"
return topic return topic
} }
func (m *MessageQueue) SendToGate(appId string, netMsg *NetMsg) { func (m *MessageQueue) SendToGate(appId string, netMsg *NetMsg) {
netMsg.Topic = m.getTopic(GATE, appId) netMsg.Topic = m.getTopic(api.GATE, appId)
originServerType, originServerAppId := m.getOriginServer()
netMsg.OriginServerType = originServerType
netMsg.OriginServerAppId = originServerAppId
m.netMsgInput <- netMsg m.netMsgInput <- netMsg
} }
func (m *MessageQueue) SendToGs(appId string, netMsg *NetMsg) { func (m *MessageQueue) SendToGs(appId string, netMsg *NetMsg) {
netMsg.Topic = m.getTopic(GS, appId) netMsg.Topic = m.getTopic(api.GS, appId)
originServerType, originServerAppId := m.getOriginServer()
netMsg.OriginServerType = originServerType
netMsg.OriginServerAppId = originServerAppId
m.netMsgInput <- netMsg m.netMsgInput <- netMsg
} }
func (m *MessageQueue) SendToFight(appId string, netMsg *NetMsg) { func (m *MessageQueue) SendToFight(appId string, netMsg *NetMsg) {
netMsg.Topic = m.getTopic(FIGHT, appId) netMsg.Topic = m.getTopic(api.FIGHT, appId)
originServerType, originServerAppId := m.getOriginServer()
netMsg.OriginServerType = originServerType
netMsg.OriginServerAppId = originServerAppId
m.netMsgInput <- netMsg m.netMsgInput <- netMsg
} }
func (m *MessageQueue) SendToPathfinding(appId string, netMsg *NetMsg) { func (m *MessageQueue) SendToPathfinding(appId string, netMsg *NetMsg) {
netMsg.Topic = m.getTopic(PATHFINDING, appId) netMsg.Topic = m.getTopic(api.PATHFINDING, appId)
originServerType, originServerAppId := m.getOriginServer()
netMsg.OriginServerType = originServerType
netMsg.OriginServerAppId = originServerAppId
m.netMsgInput <- netMsg m.netMsgInput <- netMsg
} }
+4 -1
View File
@@ -33,8 +33,11 @@ func LoadRsaKey() (signRsaKey []byte, encRsaKeyMap map[string][]byte, pwdRsaKey
return signRsaKey, encRsaKeyMap, pwdRsaKey return signRsaKey, encRsaKeyMap, pwdRsaKey
} }
func InitRegion(kcpAddr string, kcpPort int32) (*proto.QueryCurrRegionHttpRsp, *proto.QueryRegionListHttpRsp, *random.Ec2b) { func InitRegion(kcpAddr string, kcpPort int32, ec2b *random.Ec2b) (*proto.QueryCurrRegionHttpRsp, *proto.QueryRegionListHttpRsp, *random.Ec2b) {
dispatchEc2b := random.NewEc2b() dispatchEc2b := random.NewEc2b()
if ec2b != nil {
dispatchEc2b = ec2b
}
dispatchEc2bData := dispatchEc2b.Bytes() dispatchEc2bData := dispatchEc2b.Bytes()
dispatchXorKey := dispatchEc2b.XorKey() dispatchXorKey := dispatchEc2b.XorKey()
// RegionCurr // RegionCurr
+81
View File
@@ -0,0 +1,81 @@
package rpc
import (
"hk4e/common/config"
gsapi "hk4e/gs/api"
nodeapi "hk4e/node/api"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/encoders/protobuf"
)
// Client natsrpc客户端
type Client struct {
conn *nats.Conn
Discovery *DiscoveryClient
GM *GMClient
}
// NewClient 构造
func NewClient() (*Client, error) {
r := new(Client)
conn, err := nats.Connect(config.CONF.MQ.NatsUrl)
if err != nil {
return nil, err
}
r.conn = conn
discoveryClient, err := newDiscoveryClient(conn)
if err != nil {
return nil, err
}
r.Discovery = discoveryClient
gmClient, err := newGmClient(conn)
if err != nil {
return nil, err
}
r.GM = gmClient
return r, nil
}
// Close 销毁
func (c *Client) Close() {
c.conn.Close()
}
// DiscoveryClient node的discovery服务
type DiscoveryClient struct {
nodeapi.DiscoveryNATSRPCClient
}
func newDiscoveryClient(conn *nats.Conn) (*DiscoveryClient, error) {
enc, err := nats.NewEncodedConn(conn, protobuf.PROTOBUF_ENCODER)
if err != nil {
return nil, err
}
cli, err := nodeapi.NewDiscoveryNATSRPCClient(enc)
if err != nil {
return nil, err
}
return &DiscoveryClient{
DiscoveryNATSRPCClient: cli,
}, nil
}
// GMClient gs的gm服务
type GMClient struct {
gsapi.GMNATSRPCClient
}
func newGmClient(conn *nats.Conn) (*GMClient, error) {
enc, err := nats.NewEncodedConn(conn, protobuf.PROTOBUF_ENCODER)
if err != nil {
return nil, err
}
cli, err := gsapi.NewGMNATSRPCClient(enc)
if err != nil {
return nil, err
}
return &GMClient{
GMNATSRPCClient: cli,
}, nil
}
+7 -1
View File
@@ -9,6 +9,7 @@ import (
"time" "time"
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/rpc"
"hk4e/dispatch/controller" "hk4e/dispatch/controller"
"hk4e/dispatch/dao" "hk4e/dispatch/dao"
"hk4e/pkg/logger" "hk4e/pkg/logger"
@@ -23,7 +24,12 @@ func Run(ctx context.Context, configFile string) error {
db := dao.NewDao() db := dao.NewDao()
defer db.CloseDao() defer db.CloseDao()
_ = controller.NewController(db) client, err := rpc.NewClient()
if err != nil {
return err
}
_ = controller.NewController(db, client.Discovery)
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
+17 -5
View File
@@ -1,13 +1,16 @@
package controller package controller
import ( import (
"context"
"encoding/base64" "encoding/base64"
"net/http" "net/http"
"strconv" "strconv"
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/region" "hk4e/common/region"
"hk4e/common/rpc"
"hk4e/dispatch/dao" "hk4e/dispatch/dao"
"hk4e/node/api"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/random" "hk4e/pkg/random"
@@ -17,22 +20,32 @@ import (
type Controller struct { type Controller struct {
dao *dao.Dao dao *dao.Dao
discovery *rpc.DiscoveryClient
regionListBase64 string regionListBase64 string
regionCurrBase64 string regionCurrBase64 string
signRsaKey []byte signRsaKey []byte
encRsaKeyMap map[string][]byte encRsaKeyMap map[string][]byte
pwdRsaKey []byte pwdRsaKey []byte
dispatchEc2b *random.Ec2b
} }
func NewController(dao *dao.Dao) (r *Controller) { func NewController(dao *dao.Dao, discovery *rpc.DiscoveryClient) (r *Controller) {
r = new(Controller) r = new(Controller)
r.dao = dao r.dao = dao
r.discovery = discovery
r.regionListBase64 = "" r.regionListBase64 = ""
r.regionCurrBase64 = "" r.regionCurrBase64 = ""
regionCurr, regionList, dispatchEc2b := region.InitRegion(config.CONF.Hk4e.KcpAddr, config.CONF.Hk4e.KcpPort)
r.dispatchEc2b = dispatchEc2b
r.signRsaKey, r.encRsaKeyMap, r.pwdRsaKey = region.LoadRsaKey() r.signRsaKey, r.encRsaKeyMap, r.pwdRsaKey = region.LoadRsaKey()
rsp, err := r.discovery.GetRegionEc2B(context.TODO(), &api.NullMsg{})
if err != nil {
logger.Error("get region ec2b error: %v", err)
return nil
}
ec2b, err := random.LoadEc2bKey(rsp.Data)
if err != nil {
logger.Error("parse region ec2b error: %v", err)
return nil
}
regionCurr, regionList, _ := region.InitRegion(config.CONF.Hk4e.KcpAddr, config.CONF.Hk4e.KcpPort, ec2b)
regionCurrModify, err := pb.Marshal(regionCurr) regionCurrModify, err := pb.Marshal(regionCurr)
if err != nil { if err != nil {
logger.Error("Marshal QueryCurrRegionHttpRsp error") logger.Error("Marshal QueryCurrRegionHttpRsp error")
@@ -143,7 +156,6 @@ func (c *Controller) registerRouter() {
} }
engine.Use(c.authorize()) engine.Use(c.authorize())
engine.POST("/gate/token/verify", c.gateTokenVerify) engine.POST("/gate/token/verify", c.gateTokenVerify)
engine.GET("/dispatch/ec2b/seed", c.getDispatchEc2bSeed)
port := config.CONF.HttpPort port := config.CONF.HttpPort
addr := ":" + strconv.Itoa(int(port)) addr := ":" + strconv.Itoa(int(port))
err := engine.Run(addr) err := engine.Run(addr)
-11
View File
@@ -49,14 +49,3 @@ func (c *Controller) gateTokenVerify(context *gin.Context) {
PlayerID: uint32(account.PlayerID), PlayerID: uint32(account.PlayerID),
}) })
} }
type DispatchEc2bSeedRsp struct {
Seed string `json:"seed"`
}
func (c *Controller) getDispatchEc2bSeed(context *gin.Context) {
dispatchEc2bSeed := c.dispatchEc2b.Seed()
context.JSON(http.StatusOK, &DispatchEc2bSeedRsp{
Seed: strconv.FormatUint(dispatchEc2bSeed, 10),
})
}
+24 -5
View File
@@ -9,21 +9,40 @@ import (
"time" "time"
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/constant"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/common/rpc"
"hk4e/fight/engine" "hk4e/fight/engine"
"hk4e/gs/constant" "hk4e/node/api"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
var APPID string
func Run(ctx context.Context, configFile string) error { func Run(ctx context.Context, configFile string) error {
config.InitConfig(configFile) config.InitConfig(configFile)
logger.InitLogger("fight") // natsrpc client
logger.Warn("fight start") client, err := rpc.NewClient()
if err != nil {
return err
}
// 注册到节点服务器
rsp, err := client.Discovery.RegisterServer(context.TODO(), &api.RegisterServerReq{
ServerType: api.FIGHT,
})
if err != nil {
return err
}
APPID = rsp.GetAppId()
logger.InitLogger("fight_" + APPID)
logger.Warn("fight start, appid: %v", APPID)
constant.InitConstant() constant.InitConstant()
messageQueue := mq.NewMessageQueue(mq.FIGHT, "1") messageQueue := mq.NewMessageQueue(api.FIGHT, APPID)
defer messageQueue.Close() defer messageQueue.Close()
_ = engine.NewFightEngine(messageQueue) _ = engine.NewFightEngine(messageQueue)
@@ -38,7 +57,7 @@ func Run(ctx context.Context, configFile string) error {
logger.Warn("get a signal %s", s.String()) logger.Warn("get a signal %s", s.String())
switch s { switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
logger.Warn("fight exit") logger.Warn("fight exit, appid: %v", APPID)
time.Sleep(time.Second) time.Sleep(time.Second)
return nil return nil
case syscall.SIGHUP: case syscall.SIGHUP:
+37 -15
View File
@@ -3,8 +3,8 @@ package engine
import ( import (
"time" "time"
"hk4e/common/constant"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/gs/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
"hk4e/protocol/proto" "hk4e/protocol/proto"
@@ -29,16 +29,24 @@ func (f *FightEngine) fightHandle() {
userIdFightRoutineIdMap := make(map[uint32]uint32) userIdFightRoutineIdMap := make(map[uint32]uint32)
for { for {
netMsg := <-f.messageQueue.GetNetMsg() netMsg := <-f.messageQueue.GetNetMsg()
// logger.Debug("recv net msg, netMsg: %v", netMsg) logger.Debug("recv net msg, netMsg: %v", netMsg)
switch netMsg.MsgType { switch netMsg.MsgType {
case mq.MsgTypeGame: case mq.MsgTypeGame:
gameMsg := netMsg.GameMsg gameMsg := netMsg.GameMsg
if netMsg.EventId != mq.NormalMsg { if netMsg.EventId != mq.NormalMsg {
continue continue
} }
// logger.Debug("recv game msg, gameMsg: %v", gameMsg) logger.Debug("recv game msg, gameMsg: %v", gameMsg)
fightRoutineId := userIdFightRoutineIdMap[gameMsg.UserId] fightRoutineId, exist := userIdFightRoutineIdMap[gameMsg.UserId]
fightRoutineMsgChan := fightRoutineMsgChanMap[fightRoutineId] if !exist {
logger.Error("could not found fight routine id by uid: %v", gameMsg.UserId)
continue
}
fightRoutineMsgChan, exist := fightRoutineMsgChanMap[fightRoutineId]
if !exist {
logger.Error("could not found fight routine msg chan by fight routine id: %v", fightRoutineId)
continue
}
fightRoutineMsgChan <- netMsg fightRoutineMsgChan <- netMsg
case mq.MsgTypeFight: case mq.MsgTypeFight:
fightMsg := netMsg.FightMsg fightMsg := netMsg.FightMsg
@@ -49,21 +57,33 @@ func (f *FightEngine) fightHandle() {
fightRoutineMsgChanMap[fightMsg.FightRoutineId] = fightRoutineMsgChan fightRoutineMsgChanMap[fightMsg.FightRoutineId] = fightRoutineMsgChan
fightRoutineCloseChan := make(chan bool, 1) fightRoutineCloseChan := make(chan bool, 1)
fightRoutineCloseChanMap[fightMsg.FightRoutineId] = fightRoutineCloseChan fightRoutineCloseChanMap[fightMsg.FightRoutineId] = fightRoutineCloseChan
go runFightRoutine(fightMsg.FightRoutineId, fightRoutineMsgChan, fightRoutineCloseChan, f.messageQueue) go runFightRoutine(fightMsg.FightRoutineId, fightMsg.GateServerAppId, fightRoutineMsgChan, fightRoutineCloseChan, f.messageQueue)
case mq.DelFightRoutine: case mq.DelFightRoutine:
fightRoutineCloseChan := fightRoutineCloseChanMap[fightMsg.FightRoutineId] fightRoutineCloseChan, exist := fightRoutineCloseChanMap[fightMsg.FightRoutineId]
if !exist {
logger.Error("could not found fight routine close chan by fight routine id: %v", fightMsg.FightRoutineId)
continue
}
fightRoutineCloseChan <- true fightRoutineCloseChan <- true
case mq.FightRoutineAddEntity: case mq.FightRoutineAddEntity:
if fightMsg.Uid != 0 { if fightMsg.Uid != 0 {
userIdFightRoutineIdMap[fightMsg.Uid] = fightMsg.FightRoutineId userIdFightRoutineIdMap[fightMsg.Uid] = fightMsg.FightRoutineId
} }
fightRoutineMsgChan := fightRoutineMsgChanMap[fightMsg.FightRoutineId] fightRoutineMsgChan, exist := fightRoutineMsgChanMap[fightMsg.FightRoutineId]
if !exist {
logger.Error("could not found fight routine msg chan by fight routine id: %v", fightMsg.FightRoutineId)
continue
}
fightRoutineMsgChan <- netMsg fightRoutineMsgChan <- netMsg
case mq.FightRoutineDelEntity: case mq.FightRoutineDelEntity:
if fightMsg.Uid != 0 { if fightMsg.Uid != 0 {
delete(userIdFightRoutineIdMap, fightMsg.Uid) delete(userIdFightRoutineIdMap, fightMsg.Uid)
} }
fightRoutineMsgChan := fightRoutineMsgChanMap[fightMsg.FightRoutineId] fightRoutineMsgChan, exist := fightRoutineMsgChanMap[fightMsg.FightRoutineId]
if !exist {
logger.Error("could not found fight routine msg chan by fight routine id: %v", fightMsg.FightRoutineId)
continue
}
fightRoutineMsgChan <- netMsg fightRoutineMsgChan <- netMsg
} }
} }
@@ -71,7 +91,7 @@ func (f *FightEngine) fightHandle() {
} }
// SendMsg 发送消息给客户端 // SendMsg 发送消息给客户端
func SendMsg(messageQueue *mq.MessageQueue, cmdId uint16, userId uint32, payloadMsg pb.Message) { func SendMsg(messageQueue *mq.MessageQueue, cmdId uint16, userId uint32, gateAppId string, payloadMsg pb.Message) {
if userId < 100000000 || payloadMsg == nil { if userId < 100000000 || payloadMsg == nil {
return return
} }
@@ -86,7 +106,7 @@ func SendMsg(messageQueue *mq.MessageQueue, cmdId uint16, userId uint32, payload
return return
} }
gameMsg.PayloadMessageData = payloadMessageData gameMsg.PayloadMessageData = payloadMessageData
messageQueue.SendToGate("1", &mq.NetMsg{ messageQueue.SendToGate(gateAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg, EventId: mq.NormalMsg,
GameMsg: gameMsg, GameMsg: gameMsg,
@@ -106,14 +126,16 @@ type FightRoutine struct {
entityMap map[uint32]*Entity entityMap map[uint32]*Entity
combatInvokeEntryList []*proto.CombatInvokeEntry combatInvokeEntryList []*proto.CombatInvokeEntry
tickCount uint64 tickCount uint64
gateAppId string
} }
func runFightRoutine(fightRoutineId uint32, fightRoutineMsgChan chan *mq.NetMsg, fightRoutineCloseChan chan bool, messageQueue *mq.MessageQueue) { func runFightRoutine(fightRoutineId uint32, gateAppId string, fightRoutineMsgChan chan *mq.NetMsg, fightRoutineCloseChan chan bool, messageQueue *mq.MessageQueue) {
f := new(FightRoutine) f := new(FightRoutine)
f.messageQueue = messageQueue f.messageQueue = messageQueue
f.entityMap = make(map[uint32]*Entity) f.entityMap = make(map[uint32]*Entity)
f.combatInvokeEntryList = make([]*proto.CombatInvokeEntry, 0) f.combatInvokeEntryList = make([]*proto.CombatInvokeEntry, 0)
f.tickCount = 0 f.tickCount = 0
f.gateAppId = gateAppId
logger.Debug("create fight routine, fightRoutineId: %v", fightRoutineId) logger.Debug("create fight routine, fightRoutineId: %v", fightRoutineId)
ticker := time.NewTicker(time.Millisecond * 10) ticker := time.NewTicker(time.Millisecond * 10)
for { for {
@@ -162,7 +184,7 @@ func (f *FightRoutine) onTick50MilliSecond(now int64) {
combatInvocationsNotifyAll := new(proto.CombatInvocationsNotify) combatInvocationsNotifyAll := new(proto.CombatInvocationsNotify)
combatInvocationsNotifyAll.InvokeList = f.combatInvokeEntryList combatInvocationsNotifyAll.InvokeList = f.combatInvokeEntryList
for _, uid := range f.getAllPlayer(f.entityMap) { for _, uid := range f.getAllPlayer(f.entityMap) {
SendMsg(f.messageQueue, cmd.CombatInvocationsNotify, uid, combatInvocationsNotifyAll) SendMsg(f.messageQueue, cmd.CombatInvocationsNotify, uid, f.gateAppId, combatInvocationsNotifyAll)
} }
f.combatInvokeEntryList = make([]*proto.CombatInvokeEntry, 0) f.combatInvokeEntryList = make([]*proto.CombatInvokeEntry, 0)
} }
@@ -180,7 +202,7 @@ func (f *FightRoutine) onTickSecond(now int64) {
AvatarGuid: entity.avatarGuid, AvatarGuid: entity.avatarGuid,
FightPropMap: entity.fightPropMap, FightPropMap: entity.fightPropMap,
} }
SendMsg(f.messageQueue, cmd.AvatarFightPropNotify, entity.uid, avatarFightPropNotify) SendMsg(f.messageQueue, cmd.AvatarFightPropNotify, entity.uid, f.gateAppId, avatarFightPropNotify)
} }
} }
@@ -231,7 +253,7 @@ func (f *FightRoutine) attackHandle(gameMsg *mq.GameMsg) {
entityFightPropUpdateNotify.FightPropMap = make(map[uint32]float32) entityFightPropUpdateNotify.FightPropMap = make(map[uint32]float32)
entityFightPropUpdateNotify.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = currHp entityFightPropUpdateNotify.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = currHp
for _, uid := range f.getAllPlayer(f.entityMap) { for _, uid := range f.getAllPlayer(f.entityMap) {
SendMsg(f.messageQueue, cmd.EntityFightPropUpdateNotify, uid, entityFightPropUpdateNotify) SendMsg(f.messageQueue, cmd.EntityFightPropUpdateNotify, uid, f.gateAppId, entityFightPropUpdateNotify)
} }
combatData, err := pb.Marshal(hitInfo) combatData, err := pb.Marshal(hitInfo)
if err != nil { if err != nil {
+24 -5
View File
@@ -10,19 +10,38 @@ import (
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/common/rpc"
"hk4e/gate/net" "hk4e/gate/net"
"hk4e/node/api"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
var APPID string
func Run(ctx context.Context, configFile string) error { func Run(ctx context.Context, configFile string) error {
config.InitConfig(configFile) config.InitConfig(configFile)
logger.InitLogger("gate") // natsrpc client
logger.Warn("gate start") client, err := rpc.NewClient()
if err != nil {
return err
}
messageQueue := mq.NewMessageQueue(mq.GATE, "1") // 注册到节点服务器
rsp, err := client.Discovery.RegisterServer(context.TODO(), &api.RegisterServerReq{
ServerType: api.GATE,
})
if err != nil {
return err
}
APPID = rsp.GetAppId()
connectManager := net.NewKcpConnectManager(messageQueue) logger.InitLogger("gate_" + APPID)
logger.Warn("gate start, appid: %v", APPID)
messageQueue := mq.NewMessageQueue(api.GATE, APPID)
connectManager := net.NewKcpConnectManager(messageQueue, client.Discovery)
connectManager.Start() connectManager.Start()
defer connectManager.Stop() defer connectManager.Stop()
@@ -43,7 +62,7 @@ func Run(ctx context.Context, configFile string) error {
logger.Warn("get a signal %s", s.String()) logger.Warn("get a signal %s", s.String())
switch s { switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
logger.Warn("gate exit") logger.Warn("gate exit, appid: %v", APPID)
time.Sleep(time.Second) time.Sleep(time.Second)
return nil return nil
case syscall.SIGHUP: case syscall.SIGHUP:
+46 -15
View File
@@ -2,6 +2,7 @@ package net
import ( import (
"bytes" "bytes"
"context"
"encoding/base64" "encoding/base64"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
@@ -13,6 +14,7 @@ import (
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/dispatch/controller" "hk4e/dispatch/controller"
"hk4e/gate/kcp" "hk4e/gate/kcp"
"hk4e/node/api"
"hk4e/pkg/endec" "hk4e/pkg/endec"
"hk4e/pkg/httpclient" "hk4e/pkg/httpclient"
"hk4e/pkg/logger" "hk4e/pkg/logger"
@@ -80,25 +82,25 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session)
if connState != ConnActive { if connState != ConnActive {
return return
} }
// 通知GS玩家客户端的本地时钟
connCtrlMsg := new(mq.ConnCtrlMsg)
connCtrlMsg.UserId = userId
connCtrlMsg.ClientTime = pingReq.ClientTime
k.messageQueue.SendToGs("1", &mq.NetMsg{
MsgType: mq.MsgTypeConnCtrl,
EventId: mq.ClientTimeNotify,
ConnCtrlMsg: connCtrlMsg,
})
// 通知GS玩家客户端往返时延 // 通知GS玩家客户端往返时延
rtt := session.conn.GetSRTT() rtt := session.conn.GetSRTT()
connCtrlMsg = new(mq.ConnCtrlMsg) connCtrlMsg := new(mq.ConnCtrlMsg)
connCtrlMsg.UserId = userId connCtrlMsg.UserId = userId
connCtrlMsg.ClientRtt = uint32(rtt) connCtrlMsg.ClientRtt = uint32(rtt)
k.messageQueue.SendToGs("1", &mq.NetMsg{ k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeConnCtrl, MsgType: mq.MsgTypeConnCtrl,
EventId: mq.ClientRttNotify, EventId: mq.ClientRttNotify,
ConnCtrlMsg: connCtrlMsg, ConnCtrlMsg: connCtrlMsg,
}) })
// 通知GS玩家客户端的本地时钟
connCtrlMsg = new(mq.ConnCtrlMsg)
connCtrlMsg.UserId = userId
connCtrlMsg.ClientTime = pingReq.ClientTime
k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeConnCtrl,
EventId: mq.ClientTimeNotify,
ConnCtrlMsg: connCtrlMsg,
})
default: default:
if connState != ConnActive && !(protoMsg.CmdId == cmd.PlayerLoginReq || protoMsg.CmdId == cmd.SetPlayerBornDataReq) { if connState != ConnActive && !(protoMsg.CmdId == cmd.PlayerLoginReq || protoMsg.CmdId == cmd.SetPlayerBornDataReq) {
logger.Error("conn not active so drop packet, cmdId: %v, userId: %v, convId: %v", protoMsg.CmdId, userId, protoMsg.ConvId) logger.Error("conn not active so drop packet, cmdId: %v, userId: %v, convId: %v", protoMsg.CmdId, userId, protoMsg.ConvId)
@@ -106,12 +108,15 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session)
} }
// 只转发到寻路服务器 // 只转发到寻路服务器
if protoMsg.CmdId == cmd.QueryPathReq || protoMsg.CmdId == cmd.ObstacleModifyNotify { if protoMsg.CmdId == cmd.QueryPathReq || protoMsg.CmdId == cmd.ObstacleModifyNotify {
if session.pathfindingServerAppId == "" {
return
}
gameMsg := new(mq.GameMsg) gameMsg := new(mq.GameMsg)
gameMsg.UserId = userId gameMsg.UserId = userId
gameMsg.CmdId = protoMsg.CmdId gameMsg.CmdId = protoMsg.CmdId
gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId
gameMsg.PayloadMessage = protoMsg.PayloadMessage gameMsg.PayloadMessage = protoMsg.PayloadMessage
k.messageQueue.SendToPathfinding("1", &mq.NetMsg{ k.messageQueue.SendToPathfinding(session.pathfindingServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg, EventId: mq.NormalMsg,
GameMsg: gameMsg, GameMsg: gameMsg,
@@ -119,13 +124,13 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session)
return return
} }
// 同时转发到战斗服务器 // 同时转发到战斗服务器
if protoMsg.CmdId == cmd.CombatInvocationsNotify { if protoMsg.CmdId == cmd.CombatInvocationsNotify && session.fightServerAppId != "" {
gameMsg := new(mq.GameMsg) gameMsg := new(mq.GameMsg)
gameMsg.UserId = userId gameMsg.UserId = userId
gameMsg.CmdId = protoMsg.CmdId gameMsg.CmdId = protoMsg.CmdId
gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId
gameMsg.PayloadMessage = protoMsg.PayloadMessage gameMsg.PayloadMessage = protoMsg.PayloadMessage
k.messageQueue.SendToFight("1", &mq.NetMsg{ k.messageQueue.SendToFight(session.fightServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg, EventId: mq.NormalMsg,
GameMsg: gameMsg, GameMsg: gameMsg,
@@ -137,7 +142,7 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session)
gameMsg.CmdId = protoMsg.CmdId gameMsg.CmdId = protoMsg.CmdId
gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId
gameMsg.PayloadMessage = protoMsg.PayloadMessage gameMsg.PayloadMessage = protoMsg.PayloadMessage
k.messageQueue.SendToGs("1", &mq.NetMsg{ k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg, EventId: mq.NormalMsg,
GameMsg: gameMsg, GameMsg: gameMsg,
@@ -269,6 +274,32 @@ func (k *KcpConnectManager) getPlayerToken(req *proto.GetPlayerTokenReq, session
session.userId = tokenVerifyRsp.PlayerID session.userId = tokenVerifyRsp.PlayerID
k.SetSession(session, session.conn.GetConv(), session.userId) k.SetSession(session, session.conn.GetConv(), session.userId)
k.createSessionChan <- session k.createSessionChan <- session
// 绑定各个服务器appid
gsServerAppId, err := k.discovery.GetServerAppId(context.TODO(), &api.GetServerAppIdReq{
ServerType: api.GS,
})
if err != nil {
logger.Error("get gs server appid error: %v", err)
return nil
}
session.gsServerAppId = gsServerAppId.AppId
fightServerAppId, err := k.discovery.GetServerAppId(context.TODO(), &api.GetServerAppIdReq{
ServerType: api.FIGHT,
})
if err != nil {
logger.Error("get fight server appid error: %v", err)
}
session.fightServerAppId = fightServerAppId.AppId
pathfindingServerAppId, err := k.discovery.GetServerAppId(context.TODO(), &api.GetServerAppIdReq{
ServerType: api.PATHFINDING,
})
if err != nil {
logger.Error("get pathfinding server appid error: %v", err)
}
session.pathfindingServerAppId = pathfindingServerAppId.AppId
logger.Debug("session gs appid: %v", session.gsServerAppId)
logger.Debug("session fight appid: %v", session.fightServerAppId)
logger.Debug("session pathfinding appid: %v", session.pathfindingServerAppId)
// 返回响应 // 返回响应
rsp = new(proto.GetPlayerTokenRsp) rsp = new(proto.GetPlayerTokenRsp)
rsp.Uid = tokenVerifyRsp.PlayerID rsp.Uid = tokenVerifyRsp.PlayerID
+33 -19
View File
@@ -2,6 +2,7 @@ package net
import ( import (
"bytes" "bytes"
"context"
"encoding/binary" "encoding/binary"
"strconv" "strconv"
"sync" "sync"
@@ -10,9 +11,9 @@ import (
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/common/region" "hk4e/common/region"
"hk4e/dispatch/controller" "hk4e/common/rpc"
"hk4e/gate/kcp" "hk4e/gate/kcp"
"hk4e/pkg/httpclient" "hk4e/node/api"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/random" "hk4e/pkg/random"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
@@ -21,6 +22,7 @@ import (
const PacketFreqLimit = 1000 const PacketFreqLimit = 1000
type KcpConnectManager struct { type KcpConnectManager struct {
discovery *rpc.DiscoveryClient
openState bool openState bool
sessionConvIdMap map[uint64]*Session sessionConvIdMap map[uint64]*Session
sessionUserIdMap map[uint32]*Session sessionUserIdMap map[uint32]*Session
@@ -38,8 +40,9 @@ type KcpConnectManager struct {
encRsaKeyMap map[string][]byte encRsaKeyMap map[string][]byte
} }
func NewKcpConnectManager(messageQueue *mq.MessageQueue) (r *KcpConnectManager) { func NewKcpConnectManager(messageQueue *mq.MessageQueue, discovery *rpc.DiscoveryClient) (r *KcpConnectManager) {
r = new(KcpConnectManager) r = new(KcpConnectManager)
r.discovery = discovery
r.openState = true r.openState = true
r.sessionConvIdMap = make(map[uint64]*Session) r.sessionConvIdMap = make(map[uint64]*Session)
r.sessionUserIdMap = make(map[uint32]*Session) r.sessionUserIdMap = make(map[uint32]*Session)
@@ -57,20 +60,19 @@ func (k *KcpConnectManager) Start() {
// 读取密钥相关文件 // 读取密钥相关文件
k.signRsaKey, k.encRsaKeyMap, _ = region.LoadRsaKey() k.signRsaKey, k.encRsaKeyMap, _ = region.LoadRsaKey()
// key // key
dispatchEc2bSeedRsp, err := httpclient.Get[controller.DispatchEc2bSeedRsp]("http://127.0.0.1:8080/dispatch/ec2b/seed", "") rsp, err := k.discovery.GetRegionEc2B(context.TODO(), &api.NullMsg{})
if err != nil { if err != nil {
logger.Error("get dispatch ec2b seed error: %v", err) logger.Error("get region ec2b error: %v", err)
return return
} }
dispatchEc2bSeed, err := strconv.ParseUint(dispatchEc2bSeedRsp.Seed, 10, 64) ec2b, err := random.LoadEc2bKey(rsp.Data)
if err != nil { if err != nil {
logger.Error("parse dispatch ec2b seed error: %v", err) logger.Error("parse region ec2b error: %v", err)
return return
} }
logger.Debug("get dispatch ec2b seed: %v", dispatchEc2bSeed) regionEc2b := random.NewEc2b()
gateDispatchEc2b := random.NewEc2b() regionEc2b.SetSeed(ec2b.Seed())
gateDispatchEc2b.SetSeed(dispatchEc2bSeed) k.dispatchKey = regionEc2b.XorKey()
k.dispatchKey = gateDispatchEc2b.XorKey()
// kcp // kcp
port := strconv.Itoa(int(config.CONF.Hk4e.KcpPort)) port := strconv.Itoa(int(config.CONF.Hk4e.KcpPort))
listener, err := kcp.ListenWithOptions(config.CONF.Hk4e.KcpAddr+":"+port, nil, 0, 0) listener, err := kcp.ListenWithOptions(config.CONF.Hk4e.KcpAddr+":"+port, nil, 0, 0)
@@ -201,13 +203,16 @@ func (k *KcpConnectManager) enetHandle(listener *kcp.Listener) {
} }
type Session struct { type Session struct {
conn *kcp.UDPSession conn *kcp.UDPSession
connState uint8 connState uint8
userId uint32 userId uint32
kcpRawSendChan chan *ProtoMsg kcpRawSendChan chan *ProtoMsg
seed uint64 seed uint64
xorKey []byte xorKey []byte
changeXorKeyFin bool changeXorKeyFin bool
gsServerAppId string
fightServerAppId string
pathfindingServerAppId string
} }
// 接收 // 接收
@@ -288,6 +293,15 @@ func (k *KcpConnectManager) sendHandle(session *Session) {
if protoMsg.CmdId == cmd.PlayerLoginRsp { if protoMsg.CmdId == cmd.PlayerLoginRsp {
logger.Debug("session active, convId: %v", convId) logger.Debug("session active, convId: %v", convId)
session.connState = ConnActive session.connState = ConnActive
// 通知GS玩家战斗服务器的appid
connCtrlMsg := new(mq.ConnCtrlMsg)
connCtrlMsg.UserId = session.userId
connCtrlMsg.FightServerAppId = session.fightServerAppId
k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeConnCtrl,
EventId: mq.FightServerSelectNotify,
ConnCtrlMsg: connCtrlMsg,
})
} }
} }
} }
@@ -328,7 +342,7 @@ func (k *KcpConnectManager) closeKcpConn(session *Session, enetType uint32) {
// 通知GS玩家下线 // 通知GS玩家下线
gameMsg := new(mq.GameMsg) gameMsg := new(mq.GameMsg)
gameMsg.UserId = session.userId gameMsg.UserId = session.userId
k.messageQueue.SendToGs("1", &mq.NetMsg{ k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.UserOfflineNotify, EventId: mq.UserOfflineNotify,
GameMsg: gameMsg, GameMsg: gameMsg,
+3 -11
View File
@@ -8,11 +8,9 @@ import (
"time" "time"
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/rpc"
"hk4e/gm/controller" "hk4e/gm/controller"
"hk4e/gm/rpc_client"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"github.com/nats-io/nats.go"
) )
func Run(ctx context.Context, configFile string) error { func Run(ctx context.Context, configFile string) error {
@@ -21,18 +19,12 @@ func Run(ctx context.Context, configFile string) error {
logger.InitLogger("gm") logger.InitLogger("gm")
logger.Warn("gm start") logger.Warn("gm start")
conn, err := nats.Connect(config.CONF.MQ.NatsUrl) client, err := rpc.NewClient()
if err != nil { if err != nil {
logger.Error("connect nats error: %v", err)
return err return err
} }
defer conn.Close()
rpc, err := rpc_client.New(conn) _ = controller.NewController(client.GM)
if err != nil {
return err
}
_ = controller.NewController(rpc)
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
+4 -4
View File
@@ -5,19 +5,19 @@ import (
"strconv" "strconv"
"hk4e/common/config" "hk4e/common/config"
"hk4e/gm/rpc_client" "hk4e/common/rpc"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type Controller struct { type Controller struct {
rpc *rpc_client.Client gm *rpc.GMClient
} }
func NewController(rpc *rpc_client.Client) (r *Controller) { func NewController(gm *rpc.GMClient) (r *Controller) {
r = new(Controller) r = new(Controller)
r.rpc = rpc r.gm = gm
go r.registerRouter() go r.registerRouter()
return r return r
} }
+1 -1
View File
@@ -20,7 +20,7 @@ func (c *Controller) gmCmd(context *gin.Context) {
if err != nil { if err != nil {
return return
} }
rep, err := c.rpc.Cmd(context.Request.Context(), &api.CmdRequest{ rep, err := c.gm.Cmd(context.Request.Context(), &api.CmdRequest{
FuncName: gmCmdReq.FuncName, FuncName: gmCmdReq.FuncName,
Param: gmCmdReq.Param, Param: gmCmdReq.Param,
}) })
-29
View File
@@ -1,29 +0,0 @@
// Package rpc_client rpc客户端
package rpc_client
import (
"hk4e/gs/api"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/encoders/protobuf"
)
// Client rpc客户端
type Client struct {
api.GMNATSRPCClient
}
// New 构造
func New(conn *nats.Conn) (*Client, error) {
enc, err := nats.NewEncodedConn(conn, protobuf.PROTOBUF_ENCODER)
if err != nil {
return nil, err
}
cli, err := api.NewGMNATSRPCClient(enc)
if err != nil {
return nil, err
}
return &Client{
GMNATSRPCClient: cli,
}, nil
}
+6 -5
View File
@@ -1,6 +1,6 @@
module hk4e module hk4e
go 1.19 go 1.18
// toml // toml
require github.com/BurntSushi/toml v0.3.1 require github.com/BurntSushi/toml v0.3.1
@@ -44,10 +44,11 @@ require github.com/jszwec/csvutil v1.7.1
// hjson // hjson
require github.com/hjson/hjson-go/v4 v4.2.0 require github.com/hjson/hjson-go/v4 v4.2.0
require ( // natsrpc
github.com/byebyebruce/natsrpc v0.5.5-0.20221125150611-56cd29a4e335 require github.com/byebyebruce/natsrpc v0.5.5-0.20221125150611-56cd29a4e335
github.com/spf13/cobra v1.6.1
) // cobra
require github.com/spf13/cobra v1.6.1
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
+1 -1
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.14.0 // protoc v3.7.0
// source: api.proto // source: api.proto
package api package api
+33 -15
View File
@@ -9,57 +9,75 @@ import (
"time" "time"
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/constant"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/common/rpc"
"hk4e/gdconf" "hk4e/gdconf"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/dao" "hk4e/gs/dao"
"hk4e/gs/game" "hk4e/gs/game"
"hk4e/gs/service" "hk4e/gs/service"
"hk4e/node/api"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"github.com/nats-io/nats.go" "github.com/nats-io/nats.go"
) )
var APPID string
func Run(ctx context.Context, configFile string) error { func Run(ctx context.Context, configFile string) error {
config.InitConfig(configFile) config.InitConfig(configFile)
logger.InitLogger("gs") // natsrpc client
logger.Warn("gs start") client, err := rpc.NewClient()
if err != nil {
return err
}
// 注册到节点服务器
rsp, err := client.Discovery.RegisterServer(context.TODO(), &api.RegisterServerReq{
ServerType: api.GS,
})
if err != nil {
return err
}
APPID = rsp.GetAppId()
logger.InitLogger("gs_" + APPID)
logger.Warn("gs start, appid: %v", APPID)
constant.InitConstant() constant.InitConstant()
gdc.InitGameDataConfig() gdc.InitGameDataConfig()
gdconf.InitGameDataConfig() gdconf.InitGameDataConfig()
conn, err := nats.Connect(config.CONF.MQ.NatsUrl)
if err != nil {
logger.Error("connect nats error: %v", err)
return err
}
defer conn.Close()
db, err := dao.NewDao() db, err := dao.NewDao()
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer db.CloseDao() defer db.CloseDao()
messageQueue := mq.NewMessageQueue(mq.GS, "1") messageQueue := mq.NewMessageQueue(api.GS, APPID)
defer messageQueue.Close() defer messageQueue.Close()
gameManager := game.NewGameManager(db, messageQueue) gameManager := game.NewGameManager(db, messageQueue)
defer gameManager.Stop() defer gameManager.Stop()
c := make(chan os.Signal, 1) // natsrpc server
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) conn, err := nats.Connect(config.CONF.MQ.NatsUrl)
if err != nil {
logger.Error("connect nats error: %v", err)
return err
}
defer conn.Close()
s, err := service.NewService(conn) s, err := service.NewService(conn)
if err != nil { if err != nil {
return err return err
} }
defer s.Close() defer s.Close()
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
@@ -68,7 +86,7 @@ func Run(ctx context.Context, configFile string) error {
logger.Warn("get a signal %s", s.String()) logger.Warn("get a signal %s", s.String())
switch s { switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
logger.Warn("gs exit") logger.Warn("gs exit, appid: %v", APPID)
time.Sleep(time.Second) time.Sleep(time.Second)
return nil return nil
case syscall.SIGHUP: case syscall.SIGHUP:
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/pkg/endec" "hk4e/pkg/endec"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
+1 -1
View File
@@ -1,7 +1,7 @@
package game package game
import ( import (
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
+2 -1
View File
@@ -47,7 +47,8 @@ func NewCommandManager() *CommandManager {
r := new(CommandManager) r := new(CommandManager)
// 创建AI世界 // 创建AI世界
GAME_MANAGER.OnRegOk(false, &proto.SetPlayerBornDataReq{AvatarId: 10000007, NickName: "System"}, 1, 0) GAME_MANAGER.OnRegOk(false, &proto.SetPlayerBornDataReq{AvatarId: 10000007, NickName: "System"}, 1, 0, "")
GAME_MANAGER.FightServerSelectNotify(1, "")
r.system = USER_MANAGER.GetOnlineUser(1) r.system = USER_MANAGER.GetOnlineUser(1)
r.system.DbState = model.DbNormal r.system.DbState = model.DbNormal
r.system.SceneLoadState = model.SceneEnterDone r.system.SceneLoadState = model.SceneEnterDone
+39 -5
View File
@@ -134,17 +134,47 @@ func (g *GameManager) Stop() {
for _, player := range userList { for _, player := range userList {
g.DisconnectPlayer(player.PlayerID, kcp.EnetServerShutdown) g.DisconnectPlayer(player.PlayerID, kcp.EnetServerShutdown)
} }
time.Sleep(time.Second * 5) time.Sleep(time.Second * 3)
// 保存玩家数据 // 保存玩家数据
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{ LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
EventId: RunUserCopyAndSave, EventId: RunUserCopyAndSave,
} }
time.Sleep(time.Second * 5) time.Sleep(time.Second * 3)
}
func (g *GameManager) SendMsgEx(cmdId uint16, userId uint32, clientSeq uint32, gateAppId string, payloadMsg pb.Message) {
if userId < 100000000 {
return
}
if payloadMsg == nil {
logger.Error("payload msg is nil")
return
}
gameMsg := &mq.GameMsg{
UserId: userId,
CmdId: cmdId,
ClientSeq: clientSeq,
PayloadMessage: payloadMsg,
}
g.messageQueue.SendToGate(gateAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg,
GameMsg: gameMsg,
})
} }
// SendMsg 发送消息给客户端 // SendMsg 发送消息给客户端
func (g *GameManager) SendMsg(cmdId uint16, userId uint32, clientSeq uint32, payloadMsg pb.Message) { func (g *GameManager) SendMsg(cmdId uint16, userId uint32, clientSeq uint32, payloadMsg pb.Message) {
if userId < 100000000 || payloadMsg == nil { if userId < 100000000 {
return
}
if payloadMsg == nil {
logger.Error("payload msg is nil")
return
}
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
logger.Error("player not exist, uid: %v", userId)
return return
} }
gameMsg := new(mq.GameMsg) gameMsg := new(mq.GameMsg)
@@ -158,7 +188,7 @@ func (g *GameManager) SendMsg(cmdId uint16, userId uint32, clientSeq uint32, pay
return return
} }
gameMsg.PayloadMessageData = payloadMessageData gameMsg.PayloadMessageData = payloadMessageData
g.messageQueue.SendToGate("1", &mq.NetMsg{ g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg, EventId: mq.NormalMsg,
GameMsg: gameMsg, GameMsg: gameMsg,
@@ -222,7 +252,11 @@ func (g *GameManager) ReconnectPlayer(userId uint32) {
} }
func (g *GameManager) DisconnectPlayer(userId uint32, reason uint32) { func (g *GameManager) DisconnectPlayer(userId uint32, reason uint32) {
g.messageQueue.SendToGate("1", &mq.NetMsg{ player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
return
}
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
MsgType: mq.MsgTypeConnCtrl, MsgType: mq.MsgTypeConnCtrl,
EventId: mq.KickPlayerNotify, EventId: mq.KickPlayerNotify,
ConnCtrlMsg: &mq.ConnCtrlMsg{ ConnCtrlMsg: &mq.ConnCtrlMsg{
+2 -2
View File
@@ -38,10 +38,10 @@ func (l *LocalEventManager) LocalEventHandle(localEvent *LocalEvent) {
if playerLoginInfo.Player != nil { if playerLoginInfo.Player != nil {
USER_MANAGER.playerMap[playerLoginInfo.Player.PlayerID] = playerLoginInfo.Player USER_MANAGER.playerMap[playerLoginInfo.Player.PlayerID] = playerLoginInfo.Player
} }
GAME_MANAGER.OnLoginOk(playerLoginInfo.UserId, playerLoginInfo.Player, playerLoginInfo.ClientSeq) GAME_MANAGER.OnLoginOk(playerLoginInfo.UserId, playerLoginInfo.Player, playerLoginInfo.ClientSeq, playerLoginInfo.GateAppId)
case CheckUserExistOnRegFromDbFinish: case CheckUserExistOnRegFromDbFinish:
playerRegInfo := localEvent.Msg.(*PlayerRegInfo) playerRegInfo := localEvent.Msg.(*PlayerRegInfo)
GAME_MANAGER.OnRegOk(playerRegInfo.Exist, playerRegInfo.Req, playerRegInfo.UserId, playerRegInfo.ClientSeq) GAME_MANAGER.OnRegOk(playerRegInfo.Exist, playerRegInfo.Req, playerRegInfo.UserId, playerRegInfo.ClientSeq, playerRegInfo.GateAppId)
case RunUserCopyAndSave: case RunUserCopyAndSave:
startTime := time.Now().UnixNano() startTime := time.Now().UnixNano()
// 拷贝一份数据避免并发访问 // 拷贝一份数据避免并发访问
+11 -2
View File
@@ -4,6 +4,7 @@ import (
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/gate/kcp" "hk4e/gate/kcp"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/node/api"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
@@ -120,15 +121,18 @@ func (r *RouteManager) InitRoute() {
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) { func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
switch netMsg.MsgType { switch netMsg.MsgType {
case mq.MsgTypeGame: case mq.MsgTypeGame:
if netMsg.OriginServerType != api.GATE {
return
}
gameMsg := netMsg.GameMsg gameMsg := netMsg.GameMsg
switch netMsg.EventId { switch netMsg.EventId {
case mq.NormalMsg: case mq.NormalMsg:
if gameMsg.CmdId == cmd.PlayerLoginReq { if gameMsg.CmdId == cmd.PlayerLoginReq {
GAME_MANAGER.PlayerLoginReq(gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage) GAME_MANAGER.PlayerLoginReq(gameMsg.UserId, gameMsg.ClientSeq, netMsg.OriginServerAppId, gameMsg.PayloadMessage)
return return
} }
if gameMsg.CmdId == cmd.SetPlayerBornDataReq { if gameMsg.CmdId == cmd.SetPlayerBornDataReq {
GAME_MANAGER.SetPlayerBornDataReq(gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage) GAME_MANAGER.SetPlayerBornDataReq(gameMsg.UserId, gameMsg.ClientSeq, netMsg.OriginServerAppId, gameMsg.PayloadMessage)
return return
} }
r.doRoute(gameMsg.CmdId, gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage) r.doRoute(gameMsg.CmdId, gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
@@ -136,12 +140,17 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
GAME_MANAGER.OnUserOffline(gameMsg.UserId) GAME_MANAGER.OnUserOffline(gameMsg.UserId)
} }
case mq.MsgTypeConnCtrl: case mq.MsgTypeConnCtrl:
if netMsg.OriginServerType != api.GATE {
return
}
connCtrlMsg := netMsg.ConnCtrlMsg connCtrlMsg := netMsg.ConnCtrlMsg
switch netMsg.EventId { switch netMsg.EventId {
case mq.ClientRttNotify: case mq.ClientRttNotify:
GAME_MANAGER.ClientRttNotify(connCtrlMsg.UserId, connCtrlMsg.ClientRtt) GAME_MANAGER.ClientRttNotify(connCtrlMsg.UserId, connCtrlMsg.ClientRtt)
case mq.ClientTimeNotify: case mq.ClientTimeNotify:
GAME_MANAGER.ClientTimeNotify(connCtrlMsg.UserId, connCtrlMsg.ClientTime) GAME_MANAGER.ClientTimeNotify(connCtrlMsg.UserId, connCtrlMsg.ClientTime)
case mq.FightServerSelectNotify:
GAME_MANAGER.FightServerSelectNotify(connCtrlMsg.UserId, connCtrlMsg.FightServerAppId)
} }
} }
} }
+1 -1
View File
@@ -3,7 +3,7 @@ package game
import ( import (
"time" "time"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/random" "hk4e/pkg/random"
+1 -1
View File
@@ -1,8 +1,8 @@
package game package game
import ( import (
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/object" "hk4e/pkg/object"
+29 -3
View File
@@ -3,6 +3,7 @@ package game
import ( import (
"time" "time"
"hk4e/common/mq"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
@@ -56,6 +57,16 @@ func (g *GameManager) EntityAiSyncNotify(player *model.Player, payloadMsg pb.Mes
g.SendMsg(cmd.EntityAiSyncNotify, player.PlayerID, player.ClientSeq, entityAiSyncNotify) g.SendMsg(cmd.EntityAiSyncNotify, player.PlayerID, player.ClientSeq, entityAiSyncNotify)
} }
func (g *GameManager) ClientRttNotify(userId uint32, clientRtt uint32) {
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
logger.Error("player is nil, uid: %v", userId)
return
}
logger.Debug("client rtt notify, uid: %v, rtt: %v", userId, clientRtt)
player.ClientRTT = clientRtt
}
func (g *GameManager) ClientTimeNotify(userId uint32, clientTime uint32) { func (g *GameManager) ClientTimeNotify(userId uint32, clientTime uint32) {
player := USER_MANAGER.GetOnlineUser(userId) player := USER_MANAGER.GetOnlineUser(userId)
if player == nil { if player == nil {
@@ -66,14 +77,29 @@ func (g *GameManager) ClientTimeNotify(userId uint32, clientTime uint32) {
player.ClientTime = clientTime player.ClientTime = clientTime
} }
func (g *GameManager) ClientRttNotify(userId uint32, clientRtt uint32) { func (g *GameManager) FightServerSelectNotify(userId uint32, fightAppId string) {
player := USER_MANAGER.GetOnlineUser(userId) player := USER_MANAGER.GetOnlineUser(userId)
if player == nil { if player == nil {
logger.Error("player is nil, uid: %v", userId) logger.Error("player is nil, uid: %v", userId)
return return
} }
logger.Debug("client rtt notify, uid: %v, rtt: %v", userId, clientRtt) logger.Debug("fight server select notify, uid: %v, fightAppId: %v", userId, fightAppId)
player.ClientRTT = clientRtt player.FightAppId = fightAppId
// 创建世界
world := WORLD_MANAGER.CreateWorld(player)
GAME_MANAGER.messageQueue.SendToFight(fightAppId, &mq.NetMsg{
MsgType: mq.MsgTypeFight,
EventId: mq.AddFightRoutine,
FightMsg: &mq.FightMsg{
FightRoutineId: world.id,
GateServerAppId: player.GateAppId,
},
})
world.AddPlayer(player, player.SceneId)
player.WorldId = world.id
// 进入场景
player.SceneLoadState = model.SceneNone
g.SendMsg(cmd.PlayerEnterSceneNotify, userId, player.ClientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_SELF))
} }
func (g *GameManager) ServerAnnounceNotify(announceId uint32, announceMsg string) { func (g *GameManager) ServerAnnounceNotify(announceId uint32, announceMsg string) {
+1 -1
View File
@@ -1,8 +1,8 @@
package game package game
import ( import (
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
"hk4e/protocol/proto" "hk4e/protocol/proto"
+20 -26
View File
@@ -3,8 +3,8 @@ package game
import ( import (
"time" "time"
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/reflection" "hk4e/pkg/reflection"
@@ -14,36 +14,38 @@ import (
pb "google.golang.org/protobuf/proto" pb "google.golang.org/protobuf/proto"
) )
func (g *GameManager) PlayerLoginReq(userId uint32, clientSeq uint32, payloadMsg pb.Message) { func (g *GameManager) PlayerLoginReq(userId uint32, clientSeq uint32, gateAppId string, payloadMsg pb.Message) {
logger.Info("user login req, uid: %v", userId) logger.Info("user login req, uid: %v, gateAppId: %v", userId, gateAppId)
req := payloadMsg.(*proto.PlayerLoginReq) req := payloadMsg.(*proto.PlayerLoginReq)
logger.Debug("login data: %v", req) logger.Debug("login data: %v", req)
g.OnLogin(userId, clientSeq) g.OnLogin(userId, clientSeq, gateAppId)
} }
func (g *GameManager) SetPlayerBornDataReq(userId uint32, clientSeq uint32, payloadMsg pb.Message) { func (g *GameManager) SetPlayerBornDataReq(userId uint32, clientSeq uint32, gateAppId string, payloadMsg pb.Message) {
logger.Info("user reg req, uid: %v", userId) logger.Info("user reg req, uid: %v, gateAppId: %v", userId, gateAppId)
req := payloadMsg.(*proto.SetPlayerBornDataReq) req := payloadMsg.(*proto.SetPlayerBornDataReq)
logger.Debug("reg data: %v", req) logger.Debug("reg data: %v", req)
g.OnReg(userId, clientSeq, req) g.OnReg(userId, clientSeq, gateAppId, req)
} }
func (g *GameManager) OnLogin(userId uint32, clientSeq uint32) { func (g *GameManager) OnLogin(userId uint32, clientSeq uint32, gateAppId string) {
logger.Info("user login, uid: %v", userId) logger.Info("user login, uid: %v", userId)
player, asyncWait := USER_MANAGER.OnlineUser(userId, clientSeq) player, asyncWait := USER_MANAGER.OnlineUser(userId, clientSeq, gateAppId)
if !asyncWait { if !asyncWait {
g.OnLoginOk(userId, player, clientSeq) g.OnLoginOk(userId, player, clientSeq, gateAppId)
} }
} }
func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq uint32) { func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq uint32, gateAppId string) {
if player == nil { if player == nil {
g.SendMsg(cmd.DoSetPlayerBornDataNotify, userId, clientSeq, new(proto.DoSetPlayerBornDataNotify)) g.SendMsgEx(cmd.DoSetPlayerBornDataNotify, userId, clientSeq, gateAppId, new(proto.DoSetPlayerBornDataNotify))
return return
} }
player.OnlineTime = uint32(time.Now().UnixMilli()) player.OnlineTime = uint32(time.Now().UnixMilli())
player.Online = true player.Online = true
player.GateAppId = gateAppId
// 初始化 // 初始化
player.InitAll() player.InitAll()
// player.TeamConfig.UpdateTeam() // player.TeamConfig.UpdateTeam()
@@ -53,32 +55,24 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u
player.Pos.Y = player.SafePos.Y player.Pos.Y = player.SafePos.Y
player.Pos.Z = player.SafePos.Z player.Pos.Z = player.SafePos.Z
// 创建世界
world := WORLD_MANAGER.CreateWorld(player)
world.AddPlayer(player, player.SceneId)
player.WorldId = world.id
player.CombatInvokeHandler = model.NewInvokeHandler[proto.CombatInvokeEntry]() player.CombatInvokeHandler = model.NewInvokeHandler[proto.CombatInvokeEntry]()
player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]() player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]()
g.LoginNotify(userId, player, clientSeq) g.LoginNotify(userId, player, clientSeq)
player.SceneLoadState = model.SceneNone
g.SendMsg(cmd.PlayerEnterSceneNotify, userId, clientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_SELF))
} }
func (g *GameManager) OnReg(userId uint32, clientSeq uint32, payloadMsg pb.Message) { func (g *GameManager) OnReg(userId uint32, clientSeq uint32, gateAppId string, payloadMsg pb.Message) {
logger.Debug("user reg, uid: %v", userId) logger.Debug("user reg, uid: %v", userId)
req := payloadMsg.(*proto.SetPlayerBornDataReq) req := payloadMsg.(*proto.SetPlayerBornDataReq)
logger.Debug("avatar id: %v, nickname: %v", req.AvatarId, req.NickName) logger.Debug("avatar id: %v, nickname: %v", req.AvatarId, req.NickName)
exist, asyncWait := USER_MANAGER.CheckUserExistOnReg(userId, req, clientSeq) exist, asyncWait := USER_MANAGER.CheckUserExistOnReg(userId, req, clientSeq, gateAppId)
if !asyncWait { if !asyncWait {
g.OnRegOk(exist, req, userId, clientSeq) g.OnRegOk(exist, req, userId, clientSeq, gateAppId)
} }
} }
func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userId uint32, clientSeq uint32) { func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userId uint32, clientSeq uint32, gateAppId string) {
if exist { if exist {
logger.Error("recv reg req, but user is already exist, userId: %v", userId) logger.Error("recv reg req, but user is already exist, userId: %v", userId)
return return
@@ -98,8 +92,8 @@ func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userI
} }
USER_MANAGER.AddUser(player) USER_MANAGER.AddUser(player)
g.SendMsg(cmd.SetPlayerBornDataRsp, userId, clientSeq, new(proto.SetPlayerBornDataRsp)) g.SendMsgEx(cmd.SetPlayerBornDataRsp, userId, clientSeq, gateAppId, new(proto.SetPlayerBornDataRsp))
g.OnLogin(userId, clientSeq) g.OnLogin(userId, clientSeq, gateAppId)
} }
func (g *GameManager) OnUserOffline(userId uint32) { func (g *GameManager) OnUserOffline(userId uint32) {
+6 -2
View File
@@ -66,9 +66,10 @@ type PlayerRegInfo struct {
Req *proto.SetPlayerBornDataReq Req *proto.SetPlayerBornDataReq
UserId uint32 UserId uint32
ClientSeq uint32 ClientSeq uint32
GateAppId string
} }
func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBornDataReq, clientSeq uint32) (exist bool, asyncWait bool) { func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBornDataReq, clientSeq uint32, gateAppId string) (exist bool, asyncWait bool) {
_, exist = u.playerMap[userId] _, exist = u.playerMap[userId]
if exist { if exist {
return true, false return true, false
@@ -86,6 +87,7 @@ func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBor
Req: req, Req: req,
UserId: userId, UserId: userId,
ClientSeq: clientSeq, ClientSeq: clientSeq,
GateAppId: gateAppId,
}, },
} }
}() }()
@@ -137,9 +139,10 @@ type PlayerLoginInfo struct {
UserId uint32 UserId uint32
Player *model.Player Player *model.Player
ClientSeq uint32 ClientSeq uint32
GateAppId string
} }
func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32) (*model.Player, bool) { func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId string) (*model.Player, bool) {
player, exist := u.playerMap[userId] player, exist := u.playerMap[userId]
if exist { if exist {
u.ChangeUserDbState(player, model.DbNormal) u.ChangeUserDbState(player, model.DbNormal)
@@ -158,6 +161,7 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32) (*model.Player
UserId: userId, UserId: userId,
Player: player, Player: player,
ClientSeq: clientSeq, ClientSeq: clientSeq,
GateAppId: gateAppId,
}, },
} }
}() }()
+1 -2
View File
@@ -3,8 +3,7 @@ package game
import ( import (
"strconv" "strconv"
"hk4e/gs/constant" "hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
+9 -1
View File
@@ -3,7 +3,8 @@ package game
import ( import (
"time" "time"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/common/mq"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/object" "hk4e/pkg/object"
@@ -320,6 +321,13 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player)
if world.owner.PlayerID == player.PlayerID { if world.owner.PlayerID == player.PlayerID {
// 房主离开销毁世界 // 房主离开销毁世界
WORLD_MANAGER.DestroyWorld(world.id) WORLD_MANAGER.DestroyWorld(world.id)
GAME_MANAGER.messageQueue.SendToFight(world.owner.FightAppId, &mq.NetMsg{
MsgType: mq.MsgTypeFight,
EventId: mq.DelFightRoutine,
FightMsg: &mq.FightMsg{
FightRoutineId: world.id,
},
})
return return
} }
if world.multiplayer && world.GetWorldPlayerNum() > 0 { if world.multiplayer && world.GetWorldPlayerNum() > 0 {
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"strconv" "strconv"
"time" "time"
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/object" "hk4e/pkg/object"
+1 -1
View File
@@ -3,7 +3,7 @@ package game
import ( import (
"time" "time"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/pkg/object" "hk4e/pkg/object"
+3 -3
View File
@@ -4,8 +4,8 @@ import (
"strings" "strings"
"time" "time"
"hk4e/common/constant"
"hk4e/gdconf" "hk4e/gdconf"
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/endec" "hk4e/pkg/endec"
"hk4e/pkg/logger" "hk4e/pkg/logger"
@@ -462,7 +462,7 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
} }
// 获取最近角色实体的锚点 // 获取最近角色实体的锚点
// TODO 阻塞优化 16ms我感觉有点慢 // TODO 阻塞优化 16ms我感觉有点慢
//for _, entry := range gdc.CONF.ScenePointEntries { // for _, entry := range gdc.CONF.ScenePointEntries {
// if entry.PointData == nil || entry.PointData.TranPos == nil { // if entry.PointData == nil || entry.PointData.TranPos == nil {
// continue // continue
// } // }
@@ -475,7 +475,7 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
// if player.SafePos.Distance(pointPos) < player.SafePos.Distance(pos) { // if player.SafePos.Distance(pointPos) < player.SafePos.Distance(pos) {
// pos = pointPos // pos = pointPos
// } // }
//} // }
// 传送玩家至安全位置 // 传送玩家至安全位置
g.TeleportPlayer(player, uint32(constant.EnterReasonConst.Revival), player.SceneId, pos) g.TeleportPlayer(player, uint32(constant.EnterReasonConst.Revival), player.SceneId, pos)
} }
+1 -1
View File
@@ -1,8 +1,8 @@
package game package game
import ( import (
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/endec" "hk4e/pkg/endec"
"hk4e/pkg/logger" "hk4e/pkg/logger"
+1 -1
View File
@@ -1,8 +1,8 @@
package game package game
import ( import (
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
"hk4e/protocol/proto" "hk4e/protocol/proto"
+4 -18
View File
@@ -4,10 +4,10 @@ import (
"math" "math"
"time" "time"
"hk4e/common/constant"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/gs/constant"
"hk4e/gs/game/aoi" "hk4e/gs/game/aoi"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/alg" "hk4e/pkg/alg"
@@ -71,13 +71,6 @@ func (w *WorldManager) CreateWorld(owner *model.Player) *World {
} }
world.mpLevelEntityId = world.GetNextWorldEntityId(constant.EntityIdTypeConst.MPLEVEL) world.mpLevelEntityId = world.GetNextWorldEntityId(constant.EntityIdTypeConst.MPLEVEL)
w.worldMap[worldId] = world w.worldMap[worldId] = world
GAME_MANAGER.messageQueue.SendToFight("1", &mq.NetMsg{
MsgType: mq.MsgTypeFight,
EventId: mq.AddFightRoutine,
FightMsg: &mq.FightMsg{
FightRoutineId: world.id,
},
})
return world return world
} }
@@ -88,13 +81,6 @@ func (w *WorldManager) DestroyWorld(worldId uint32) {
player.WorldId = 0 player.WorldId = 0
} }
delete(w.worldMap, worldId) delete(w.worldMap, worldId)
GAME_MANAGER.messageQueue.SendToFight("1", &mq.NetMsg{
MsgType: mq.MsgTypeFight,
EventId: mq.DelFightRoutine,
FightMsg: &mq.FightMsg{
FightRoutineId: world.id,
},
})
} }
// GetBigWorld 获取本服务器的AI世界 // GetBigWorld 获取本服务器的AI世界
@@ -715,7 +701,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
if avatarId == s.world.GetPlayerActiveAvatarId(player) { if avatarId == s.world.GetPlayerActiveAvatarId(player) {
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z)) s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
} }
GAME_MANAGER.messageQueue.SendToFight("1", &mq.NetMsg{ GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
MsgType: mq.MsgTypeFight, MsgType: mq.MsgTypeFight,
EventId: mq.FightRoutineAddEntity, EventId: mq.FightRoutineAddEntity,
FightMsg: &mq.FightMsg{ FightMsg: &mq.FightMsg{
@@ -765,7 +751,7 @@ func (s *Scene) CreateEntityMonster(pos *model.Vector, level uint8, fightProp ma
} }
s.entityMap[entity.id] = entity s.entityMap[entity.id] = entity
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z)) s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
GAME_MANAGER.messageQueue.SendToFight("1", &mq.NetMsg{ GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
MsgType: mq.MsgTypeFight, MsgType: mq.MsgTypeFight,
EventId: mq.FightRoutineAddEntity, EventId: mq.FightRoutineAddEntity,
FightMsg: &mq.FightMsg{ FightMsg: &mq.FightMsg{
@@ -915,7 +901,7 @@ func (s *Scene) DestroyEntity(entityId uint32) {
} }
s.world.aoiManager.RemoveEntityIdFromGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z)) s.world.aoiManager.RemoveEntityIdFromGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
delete(s.entityMap, entityId) delete(s.entityMap, entityId)
GAME_MANAGER.messageQueue.SendToFight("1", &mq.NetMsg{ GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
MsgType: mq.MsgTypeFight, MsgType: mq.MsgTypeFight,
EventId: mq.FightRoutineDelEntity, EventId: mq.FightRoutineDelEntity,
FightMsg: &mq.FightMsg{ FightMsg: &mq.FightMsg{
+1 -1
View File
@@ -1,7 +1,7 @@
package model package model
import ( import (
"hk4e/gs/constant" "hk4e/common/constant"
) )
type Item struct { type Item struct {
+1 -1
View File
@@ -3,8 +3,8 @@ package model
import ( import (
"time" "time"
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
+2
View File
@@ -71,6 +71,8 @@ type Player struct {
ClientSeq uint32 `bson:"-" msgpack:"-"` // 客户端发包请求的序号 ClientSeq uint32 `bson:"-" msgpack:"-"` // 客户端发包请求的序号
CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] `bson:"-" msgpack:"-"` // combat转发器 CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] `bson:"-" msgpack:"-"` // combat转发器
AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] `bson:"-" msgpack:"-"` // ability转发器 AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] `bson:"-" msgpack:"-"` // ability转发器
GateAppId string `bson:"-" msgpack:"-"` // 网关服务器的appid
FightAppId string `bson:"-" msgpack:"-"` // 战斗服务器的appid
} }
func (p *Player) GetNextGameObjectGuid() uint64 { func (p *Player) GetNextGameObjectGuid() uint64 {
+1 -1
View File
@@ -1,7 +1,7 @@
package model package model
import ( import (
"hk4e/gs/constant" "hk4e/common/constant"
"hk4e/protocol/proto" "hk4e/protocol/proto"
) )
+1 -1
View File
@@ -1,8 +1,8 @@
package model package model
import ( import (
"hk4e/common/constant"
gdc "hk4e/gs/config" gdc "hk4e/gs/config"
"hk4e/gs/constant"
) )
type Team struct { type Team struct {
-1
View File
@@ -30,5 +30,4 @@ func NewService(conn *nats.Conn) (*Service, error) {
// Close 关闭 // Close 关闭
func (s *Service) Close() { func (s *Service) Close() {
// TODO // TODO
} }
+70
View File
@@ -0,0 +1,70 @@
// Code generated by protoc-gen-natsrpc. DO NOT EDIT.
// versions:
// - protoc-gen-natsrpc v0.5.0
// source: api.proto
package api
import (
context "context"
fmt "fmt"
natsrpc "github.com/byebyebruce/natsrpc"
nats_go "github.com/nats-io/nats.go"
proto "google.golang.org/protobuf/proto"
)
var _ = new(context.Context)
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = natsrpc.Version
var _ = nats_go.Version
// 节点服务器注册发现服务
type DiscoveryNATSRPCServer interface {
RegisterServer(ctx context.Context, req *RegisterServerReq) (*RegisterServerRsp, error)
GetServerAppId(ctx context.Context, req *GetServerAppIdReq) (*GetServerAppIdRsp, error)
GetRegionEc2B(ctx context.Context, req *NullMsg) (*RegionEc2B, error)
}
// RegisterDiscoveryNATSRPCServer register Discovery service
func RegisterDiscoveryNATSRPCServer(server *natsrpc.Server, s DiscoveryNATSRPCServer, opts ...natsrpc.ServiceOption) (natsrpc.IService, error) {
return server.Register("hk4e.node.api.Discovery", s, opts...)
}
// 节点服务器注册发现服务
type DiscoveryNATSRPCClient interface {
RegisterServer(ctx context.Context, req *RegisterServerReq, opt ...natsrpc.CallOption) (*RegisterServerRsp, error)
GetServerAppId(ctx context.Context, req *GetServerAppIdReq, opt ...natsrpc.CallOption) (*GetServerAppIdRsp, error)
GetRegionEc2B(ctx context.Context, req *NullMsg, opt ...natsrpc.CallOption) (*RegionEc2B, error)
}
type _DiscoveryNATSRPCClient struct {
c *natsrpc.Client
}
// NewDiscoveryNATSRPCClient
func NewDiscoveryNATSRPCClient(enc *nats_go.EncodedConn, opts ...natsrpc.ClientOption) (DiscoveryNATSRPCClient, error) {
c, err := natsrpc.NewClient(enc, "hk4e.node.api.Discovery", opts...)
if err != nil {
return nil, err
}
ret := &_DiscoveryNATSRPCClient{
c: c,
}
return ret, nil
}
func (c *_DiscoveryNATSRPCClient) RegisterServer(ctx context.Context, req *RegisterServerReq, opt ...natsrpc.CallOption) (*RegisterServerRsp, error) {
rep := &RegisterServerRsp{}
err := c.c.Request(ctx, "RegisterServer", req, rep, opt...)
return rep, err
}
func (c *_DiscoveryNATSRPCClient) GetServerAppId(ctx context.Context, req *GetServerAppIdReq, opt ...natsrpc.CallOption) (*GetServerAppIdRsp, error) {
rep := &GetServerAppIdRsp{}
err := c.c.Request(ctx, "GetServerAppId", req, rep, opt...)
return rep, err
}
func (c *_DiscoveryNATSRPCClient) GetRegionEc2B(ctx context.Context, req *NullMsg, opt ...natsrpc.CallOption) (*RegionEc2B, error) {
rep := &RegionEc2B{}
err := c.c.Request(ctx, "GetRegionEc2B", req, rep, opt...)
return rep, err
}
+466
View File
@@ -0,0 +1,466 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.7.0
// source: api.proto
package api
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)
)
type NullMsg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *NullMsg) Reset() {
*x = NullMsg{}
if protoimpl.UnsafeEnabled {
mi := &file_api_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *NullMsg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NullMsg) ProtoMessage() {}
func (x *NullMsg) ProtoReflect() protoreflect.Message {
mi := &file_api_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 NullMsg.ProtoReflect.Descriptor instead.
func (*NullMsg) Descriptor() ([]byte, []int) {
return file_api_proto_rawDescGZIP(), []int{0}
}
type GetServerAppIdReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ServerType string `protobuf:"bytes,1,opt,name=server_type,json=serverType,proto3" json:"server_type,omitempty"`
}
func (x *GetServerAppIdReq) Reset() {
*x = GetServerAppIdReq{}
if protoimpl.UnsafeEnabled {
mi := &file_api_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetServerAppIdReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetServerAppIdReq) ProtoMessage() {}
func (x *GetServerAppIdReq) ProtoReflect() protoreflect.Message {
mi := &file_api_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 GetServerAppIdReq.ProtoReflect.Descriptor instead.
func (*GetServerAppIdReq) Descriptor() ([]byte, []int) {
return file_api_proto_rawDescGZIP(), []int{1}
}
func (x *GetServerAppIdReq) GetServerType() string {
if x != nil {
return x.ServerType
}
return ""
}
type GetServerAppIdRsp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
AppId string `protobuf:"bytes,1,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"`
}
func (x *GetServerAppIdRsp) Reset() {
*x = GetServerAppIdRsp{}
if protoimpl.UnsafeEnabled {
mi := &file_api_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetServerAppIdRsp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetServerAppIdRsp) ProtoMessage() {}
func (x *GetServerAppIdRsp) ProtoReflect() protoreflect.Message {
mi := &file_api_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 GetServerAppIdRsp.ProtoReflect.Descriptor instead.
func (*GetServerAppIdRsp) Descriptor() ([]byte, []int) {
return file_api_proto_rawDescGZIP(), []int{2}
}
func (x *GetServerAppIdRsp) GetAppId() string {
if x != nil {
return x.AppId
}
return ""
}
type RegisterServerReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ServerType string `protobuf:"bytes,1,opt,name=server_type,json=serverType,proto3" json:"server_type,omitempty"`
}
func (x *RegisterServerReq) Reset() {
*x = RegisterServerReq{}
if protoimpl.UnsafeEnabled {
mi := &file_api_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RegisterServerReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RegisterServerReq) ProtoMessage() {}
func (x *RegisterServerReq) ProtoReflect() protoreflect.Message {
mi := &file_api_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 RegisterServerReq.ProtoReflect.Descriptor instead.
func (*RegisterServerReq) Descriptor() ([]byte, []int) {
return file_api_proto_rawDescGZIP(), []int{3}
}
func (x *RegisterServerReq) GetServerType() string {
if x != nil {
return x.ServerType
}
return ""
}
type RegisterServerRsp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
AppId string `protobuf:"bytes,1,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"`
}
func (x *RegisterServerRsp) Reset() {
*x = RegisterServerRsp{}
if protoimpl.UnsafeEnabled {
mi := &file_api_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RegisterServerRsp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RegisterServerRsp) ProtoMessage() {}
func (x *RegisterServerRsp) ProtoReflect() protoreflect.Message {
mi := &file_api_proto_msgTypes[4]
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 RegisterServerRsp.ProtoReflect.Descriptor instead.
func (*RegisterServerRsp) Descriptor() ([]byte, []int) {
return file_api_proto_rawDescGZIP(), []int{4}
}
func (x *RegisterServerRsp) GetAppId() string {
if x != nil {
return x.AppId
}
return ""
}
type RegionEc2B struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *RegionEc2B) Reset() {
*x = RegionEc2B{}
if protoimpl.UnsafeEnabled {
mi := &file_api_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RegionEc2B) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RegionEc2B) ProtoMessage() {}
func (x *RegionEc2B) ProtoReflect() protoreflect.Message {
mi := &file_api_proto_msgTypes[5]
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 RegionEc2B.ProtoReflect.Descriptor instead.
func (*RegionEc2B) Descriptor() ([]byte, []int) {
return file_api_proto_rawDescGZIP(), []int{5}
}
func (x *RegionEc2B) GetData() []byte {
if x != nil {
return x.Data
}
return nil
}
var File_api_proto protoreflect.FileDescriptor
var file_api_proto_rawDesc = []byte{
0x0a, 0x09, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x6e, 0x6f, 0x64,
0x65, 0x2e, 0x61, 0x70, 0x69, 0x22, 0x09, 0x0a, 0x07, 0x4e, 0x75, 0x6c, 0x6c, 0x4d, 0x73, 0x67,
0x22, 0x34, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x70, 0x70,
0x49, 0x64, 0x52, 0x65, 0x71, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2a, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x73, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x61,
0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70,
0x49, 0x64, 0x22, 0x34, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65,
0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2a, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69,
0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x73, 0x70, 0x12, 0x15, 0x0a,
0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61,
0x70, 0x70, 0x49, 0x64, 0x22, 0x20, 0x0a, 0x0a, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x45, 0x63,
0x32, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xe3, 0x01, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x79, 0x12, 0x4c, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x73, 0x70,
0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41,
0x70, 0x70, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x65,
0x71, 0x1a, 0x1b, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74,
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x73, 0x70, 0x22, 0x00,
0x12, 0x3a, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x45, 0x63, 0x32,
0x62, 0x12, 0x11, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x75, 0x6c,
0x6c, 0x4d, 0x73, 0x67, 0x1a, 0x14, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x45, 0x63, 0x32, 0x62, 0x22, 0x00, 0x42, 0x13, 0x5a, 0x11,
0x68, 0x6b, 0x34, 0x65, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70,
0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_api_proto_rawDescOnce sync.Once
file_api_proto_rawDescData = file_api_proto_rawDesc
)
func file_api_proto_rawDescGZIP() []byte {
file_api_proto_rawDescOnce.Do(func() {
file_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_proto_rawDescData)
})
return file_api_proto_rawDescData
}
var file_api_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_api_proto_goTypes = []interface{}{
(*NullMsg)(nil), // 0: node.api.NullMsg
(*GetServerAppIdReq)(nil), // 1: node.api.GetServerAppIdReq
(*GetServerAppIdRsp)(nil), // 2: node.api.GetServerAppIdRsp
(*RegisterServerReq)(nil), // 3: node.api.RegisterServerReq
(*RegisterServerRsp)(nil), // 4: node.api.RegisterServerRsp
(*RegionEc2B)(nil), // 5: node.api.RegionEc2b
}
var file_api_proto_depIdxs = []int32{
3, // 0: node.api.Discovery.RegisterServer:input_type -> node.api.RegisterServerReq
1, // 1: node.api.Discovery.GetServerAppId:input_type -> node.api.GetServerAppIdReq
0, // 2: node.api.Discovery.GetRegionEc2b:input_type -> node.api.NullMsg
4, // 3: node.api.Discovery.RegisterServer:output_type -> node.api.RegisterServerRsp
2, // 4: node.api.Discovery.GetServerAppId:output_type -> node.api.GetServerAppIdRsp
5, // 5: node.api.Discovery.GetRegionEc2b:output_type -> node.api.RegionEc2b
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_api_proto_init() }
func file_api_proto_init() {
if File_api_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NullMsg); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetServerAppIdReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetServerAppIdRsp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterServerReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterServerRsp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegionEc2B); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_api_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_api_proto_goTypes,
DependencyIndexes: file_api_proto_depIdxs,
MessageInfos: file_api_proto_msgTypes,
}.Build()
File_api_proto = out.File
file_api_proto_rawDesc = nil
file_api_proto_goTypes = nil
file_api_proto_depIdxs = nil
}
+34
View File
@@ -0,0 +1,34 @@
syntax = "proto3";
package node.api;
option go_package = "hk4e/node/api;api";
// 节点服务器注册发现服务
service Discovery {
rpc RegisterServer (RegisterServerReq) returns (RegisterServerRsp) {} // 服务器启动注册获取appid
rpc GetServerAppId (GetServerAppIdReq) returns (GetServerAppIdRsp) {} // 随机获取某服务器的appid
rpc GetRegionEc2b (NullMsg) returns (RegionEc2b) {} // 获取区服密钥信息
}
message NullMsg {
}
message GetServerAppIdReq {
string server_type = 1;
}
message GetServerAppIdRsp {
string app_id = 1;
}
message RegisterServerReq {
string server_type = 1;
}
message RegisterServerRsp {
string app_id = 1;
}
message RegionEc2b {
bytes data = 1;
}
+8
View File
@@ -0,0 +1,8 @@
package api
const (
GATE = "GATE"
GS = "GS"
FIGHT = "FIGHT"
PATHFINDING = "PATHFINDING"
)
+56
View File
@@ -0,0 +1,56 @@
package app
import (
"context"
_ "net/http/pprof"
"os"
"os/signal"
"syscall"
"time"
"hk4e/common/config"
"hk4e/node/service"
"hk4e/pkg/logger"
"github.com/nats-io/nats.go"
)
func Run(ctx context.Context, configFile string) error {
config.InitConfig(configFile)
logger.InitLogger("node")
logger.Warn("node start")
// natsrpc server
conn, err := nats.Connect(config.CONF.MQ.NatsUrl)
if err != nil {
logger.Error("connect nats error: %v", err)
return err
}
defer conn.Close()
s, err := service.NewService(conn)
if err != nil {
return err
}
defer s.Close()
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
select {
case <-ctx.Done():
return nil
case s := <-c:
logger.Warn("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
logger.Warn("node exit")
time.Sleep(time.Second)
return nil
case syscall.SIGHUP:
default:
return nil
}
}
}
}
+94
View File
@@ -0,0 +1,94 @@
package service
import (
"context"
"strings"
"hk4e/common/config"
"hk4e/common/region"
"hk4e/node/api"
"hk4e/pkg/logger"
"hk4e/pkg/random"
"github.com/pkg/errors"
)
var _ api.DiscoveryNATSRPCServer = (*DiscoveryService)(nil)
type ServerInstance struct {
serverType string
appId string
}
type DiscoveryService struct {
regionEc2b *random.Ec2b
// TODO 加锁
serverInstanceMap map[string]map[string]*ServerInstance
serverAppIdMap map[string]bool
}
func NewDiscoveryService() *DiscoveryService {
r := new(DiscoveryService)
_, _, r.regionEc2b = region.InitRegion(config.CONF.Hk4e.KcpAddr, config.CONF.Hk4e.KcpPort, nil)
logger.Info("region ec2b create ok, seed: %v", r.regionEc2b.Seed())
r.serverInstanceMap = map[string]map[string]*ServerInstance{
api.GATE: make(map[string]*ServerInstance),
api.GS: make(map[string]*ServerInstance),
api.FIGHT: make(map[string]*ServerInstance),
api.PATHFINDING: make(map[string]*ServerInstance),
}
r.serverAppIdMap = make(map[string]bool)
return r
}
func (s *DiscoveryService) RegisterServer(ctx context.Context, req *api.RegisterServerReq) (*api.RegisterServerRsp, error) {
logger.Info("register new server, server type: %v", req.ServerType)
instMap, exist := s.serverInstanceMap[req.ServerType]
if !exist {
return nil, errors.New("server type not exist")
}
var appId string
for {
appId = strings.ToLower(random.GetRandomStr(8))
_, exist := s.serverAppIdMap[appId]
if !exist {
s.serverAppIdMap[appId] = true
break
}
}
instMap[appId] = &ServerInstance{
serverType: req.ServerType,
appId: appId,
}
logger.Info("new server appid is: %v", appId)
return &api.RegisterServerRsp{
AppId: appId,
}, nil
}
func (s *DiscoveryService) GetServerAppId(ctx context.Context, req *api.GetServerAppIdReq) (*api.GetServerAppIdRsp, error) {
logger.Info("get server instance, server type: %v", req.ServerType)
instMap, exist := s.serverInstanceMap[req.ServerType]
if !exist {
return nil, errors.New("server type not exist")
}
if len(instMap) == 0 {
return nil, errors.New("no server found")
}
var inst *ServerInstance = nil
for _, v := range instMap {
inst = v
break
}
logger.Info("get server appid is: %v", inst.appId)
return &api.GetServerAppIdRsp{
AppId: inst.appId,
}, nil
}
func (s *DiscoveryService) GetRegionEc2B(ctx context.Context, req *api.NullMsg) (*api.RegionEc2B, error) {
logger.Info("get region ec2b ok")
return &api.RegionEc2B{
Data: s.regionEc2b.Bytes(),
}, nil
}
+32
View File
@@ -0,0 +1,32 @@
package service
import (
"hk4e/node/api"
"github.com/byebyebruce/natsrpc"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/encoders/protobuf"
)
type Service struct {
}
func NewService(conn *nats.Conn) (*Service, error) {
enc, err := nats.NewEncodedConn(conn, protobuf.PROTOBUF_ENCODER)
if err != nil {
return nil, err
}
svr, err := natsrpc.NewServer(enc)
if err != nil {
return nil, err
}
discoveryService := NewDiscoveryService()
_, err = api.RegisterDiscoveryNATSRPCServer(svr, discoveryService)
if err != nil {
return nil, err
}
return &Service{}, nil
}
func (s *Service) Close() {
}
+23 -4
View File
@@ -10,17 +10,36 @@ import (
"hk4e/common/config" "hk4e/common/config"
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/common/rpc"
"hk4e/node/api"
"hk4e/pathfinding/handle" "hk4e/pathfinding/handle"
"hk4e/pkg/logger" "hk4e/pkg/logger"
) )
var APPID string
func Run(ctx context.Context, configFile string) error { func Run(ctx context.Context, configFile string) error {
config.InitConfig(configFile) config.InitConfig(configFile)
logger.InitLogger("pathfinding") // natsrpc client
logger.Warn("pathfinding start") client, err := rpc.NewClient()
if err != nil {
return err
}
messageQueue := mq.NewMessageQueue(mq.PATHFINDING, "1") // 注册到节点服务器
rsp, err := client.Discovery.RegisterServer(context.TODO(), &api.RegisterServerReq{
ServerType: api.PATHFINDING,
})
if err != nil {
return err
}
APPID = rsp.GetAppId()
logger.InitLogger("pathfinding_" + APPID)
logger.Warn("pathfinding start, appid: %v", APPID)
messageQueue := mq.NewMessageQueue(api.PATHFINDING, APPID)
defer messageQueue.Close() defer messageQueue.Close()
_ = handle.NewHandle(messageQueue) _ = handle.NewHandle(messageQueue)
@@ -35,7 +54,7 @@ func Run(ctx context.Context, configFile string) error {
logger.Warn("get a signal %s", s.String()) logger.Warn("get a signal %s", s.String())
switch s { switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
logger.Warn("pathfinding exit") logger.Warn("pathfinding exit, appid: %v", APPID)
time.Sleep(time.Second) time.Sleep(time.Second)
return nil return nil
case syscall.SIGHUP: case syscall.SIGHUP:
+8 -4
View File
@@ -2,6 +2,7 @@ package handle
import ( import (
"hk4e/common/mq" "hk4e/common/mq"
"hk4e/node/api"
"hk4e/pathfinding/world" "hk4e/pathfinding/world"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
@@ -34,12 +35,15 @@ func (h *Handle) run() {
if netMsg.EventId != mq.NormalMsg { if netMsg.EventId != mq.NormalMsg {
continue continue
} }
if netMsg.OriginServerType != api.GATE {
continue
}
gameMsg := netMsg.GameMsg gameMsg := netMsg.GameMsg
switch gameMsg.CmdId { switch gameMsg.CmdId {
case cmd.QueryPathReq: case cmd.QueryPathReq:
h.QueryPath(gameMsg.UserId, gameMsg.PayloadMessage) h.QueryPath(gameMsg.UserId, netMsg.OriginServerAppId, gameMsg.PayloadMessage)
case cmd.ObstacleModifyNotify: case cmd.ObstacleModifyNotify:
h.ObstacleModifyNotify(gameMsg.UserId, gameMsg.PayloadMessage) h.ObstacleModifyNotify(gameMsg.UserId, netMsg.OriginServerAppId, gameMsg.PayloadMessage)
} }
} }
}() }()
@@ -47,7 +51,7 @@ func (h *Handle) run() {
} }
// SendMsg 发送消息给客户端 // SendMsg 发送消息给客户端
func (h *Handle) SendMsg(cmdId uint16, userId uint32, payloadMsg pb.Message) { func (h *Handle) SendMsg(cmdId uint16, userId uint32, gateAppId string, payloadMsg pb.Message) {
if userId < 100000000 || payloadMsg == nil { if userId < 100000000 || payloadMsg == nil {
return return
} }
@@ -62,7 +66,7 @@ func (h *Handle) SendMsg(cmdId uint16, userId uint32, payloadMsg pb.Message) {
return return
} }
gameMsg.PayloadMessageData = payloadMessageData gameMsg.PayloadMessageData = payloadMessageData
h.messageQueue.SendToGate("1", &mq.NetMsg{ h.messageQueue.SendToGate(gateAppId, &mq.NetMsg{
MsgType: mq.MsgTypeGame, MsgType: mq.MsgTypeGame,
EventId: mq.NormalMsg, EventId: mq.NormalMsg,
GameMsg: gameMsg, GameMsg: gameMsg,
+6 -6
View File
@@ -41,9 +41,9 @@ func (h *Handle) ConvMeshVecListToPbVecList(meshVecList []pfalg.MeshVector) []*p
return ret return ret
} }
func (h *Handle) QueryPath(userId uint32, payloadMsg pb.Message) { func (h *Handle) QueryPath(userId uint32, gateAppId string, payloadMsg pb.Message) {
req := payloadMsg.(*proto.QueryPathReq) req := payloadMsg.(*proto.QueryPathReq)
logger.Debug("query path req: %v, uid: %v", req, userId) logger.Debug("query path req: %v, uid: %v, gateAppId: %v", req, userId, gateAppId)
var ok = false var ok = false
var path []pfalg.MeshVector = nil var path []pfalg.MeshVector = nil
for _, destinationPos := range req.DestinationPos { for _, destinationPos := range req.DestinationPos {
@@ -57,7 +57,7 @@ func (h *Handle) QueryPath(userId uint32, payloadMsg pb.Message) {
QueryId: req.QueryId, QueryId: req.QueryId,
QueryStatus: proto.QueryPathRsp_PATH_STATUS_TYPE_FAIL, QueryStatus: proto.QueryPathRsp_PATH_STATUS_TYPE_FAIL,
} }
h.SendMsg(cmd.QueryPathRsp, userId, queryPathRsp) h.SendMsg(cmd.QueryPathRsp, userId, gateAppId, queryPathRsp)
return return
} }
queryPathRsp := &proto.QueryPathRsp{ queryPathRsp := &proto.QueryPathRsp{
@@ -65,10 +65,10 @@ func (h *Handle) QueryPath(userId uint32, payloadMsg pb.Message) {
QueryStatus: proto.QueryPathRsp_PATH_STATUS_TYPE_SUCC, QueryStatus: proto.QueryPathRsp_PATH_STATUS_TYPE_SUCC,
Corners: h.ConvMeshVecListToPbVecList(path), Corners: h.ConvMeshVecListToPbVecList(path),
} }
h.SendMsg(cmd.QueryPathRsp, userId, queryPathRsp) h.SendMsg(cmd.QueryPathRsp, userId, gateAppId, queryPathRsp)
} }
func (h *Handle) ObstacleModifyNotify(userId uint32, payloadMsg pb.Message) { func (h *Handle) ObstacleModifyNotify(userId uint32, gateAppId string, payloadMsg pb.Message) {
req := payloadMsg.(*proto.ObstacleModifyNotify) req := payloadMsg.(*proto.ObstacleModifyNotify)
logger.Debug("obstacle modify req: %v, uid: %v", req, userId) logger.Debug("obstacle modify req: %v, uid: %v, gateAppId: %v", req, userId, gateAppId)
} }
+3 -5
View File
@@ -3,21 +3,19 @@ package statsviz_serve
import ( import (
"net/http" "net/http"
"hk4e/pkg/logger"
"github.com/arl/statsviz" "github.com/arl/statsviz"
) )
// Serve 性能检测
// 原生pprof /debug/pprof
// 可视化图表 /debug/statsviz
func Serve(addr string) error { func Serve(addr string) error {
// 性能检测
err := statsviz.RegisterDefault() err := statsviz.RegisterDefault()
if err != nil { if err != nil {
logger.Error("statsviz init error: %v", err)
return err return err
} }
err = http.ListenAndServe(addr, nil) err = http.ListenAndServe(addr, nil)
if err != nil { if err != nil {
logger.Error("perf debug http start error: %v", err)
return err return err
} }
return nil return nil