mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 14:12:27 +08:00
玩家管理模块接入redis,已完整实现好友、多人世界的跨服交互功能
This commit is contained in:
@@ -13,5 +13,9 @@ max_size = 10485760
|
||||
[database]
|
||||
url = "mongodb://mongo:27017"
|
||||
|
||||
[redis]
|
||||
addr = "redis:6379"
|
||||
password = ""
|
||||
|
||||
[mq]
|
||||
nats_url = "nats://nats:4222"
|
||||
|
||||
@@ -13,6 +13,7 @@ type Config struct {
|
||||
HttpPort int32 `toml:"http_port"`
|
||||
Logger Logger `toml:"logger"`
|
||||
Database Database `toml:"database"`
|
||||
Redis Redis `toml:"redis"`
|
||||
Hk4e Hk4e `toml:"hk4e"`
|
||||
MQ MQ `toml:"mq"`
|
||||
}
|
||||
@@ -30,6 +31,11 @@ type Database struct {
|
||||
Url string `toml:"url"`
|
||||
}
|
||||
|
||||
type Redis struct {
|
||||
Addr string `toml:"addr"`
|
||||
Password string `toml:"password"`
|
||||
}
|
||||
|
||||
// Hk4e 原神相关
|
||||
type Hk4e struct {
|
||||
KcpPort int32 `toml:"kcp_port"`
|
||||
|
||||
@@ -3,10 +3,10 @@ package mq
|
||||
import pb "google.golang.org/protobuf/proto"
|
||||
|
||||
const (
|
||||
MsgTypeGame = iota
|
||||
MsgTypeFight
|
||||
MsgTypeConnCtrl
|
||||
MsgTypeServer
|
||||
MsgTypeGame = iota // 来自客户端的游戏消息
|
||||
MsgTypeFight // 战斗服务器消息
|
||||
MsgTypeConnCtrl // GATE客户端连接信息消息
|
||||
MsgTypeServer // 服务器之间转发的消息
|
||||
)
|
||||
|
||||
type NetMsg struct {
|
||||
@@ -22,8 +22,7 @@ type NetMsg struct {
|
||||
}
|
||||
|
||||
const (
|
||||
NormalMsg = iota
|
||||
UserOfflineNotify
|
||||
NormalMsg = iota // 正常的游戏消息
|
||||
)
|
||||
|
||||
type GameMsg struct {
|
||||
@@ -35,9 +34,10 @@ type GameMsg struct {
|
||||
}
|
||||
|
||||
const (
|
||||
ClientRttNotify = iota
|
||||
ClientTimeNotify
|
||||
KickPlayerNotify
|
||||
ClientRttNotify = iota // 客户端网络时延上报
|
||||
ClientTimeNotify // 客户端本地时间上报
|
||||
KickPlayerNotify // 通知GATE剔除玩家
|
||||
UserOfflineNotify // 玩家离线通知GS
|
||||
)
|
||||
|
||||
type ConnCtrlMsg struct {
|
||||
@@ -49,10 +49,10 @@ type ConnCtrlMsg struct {
|
||||
}
|
||||
|
||||
const (
|
||||
AddFightRoutine = iota
|
||||
DelFightRoutine
|
||||
FightRoutineAddEntity
|
||||
FightRoutineDelEntity
|
||||
AddFightRoutine = iota // 添加战斗实例
|
||||
DelFightRoutine // 删除战斗实例
|
||||
FightRoutineAddEntity // 战斗实例添加实体
|
||||
FightRoutineDelEntity // 战斗实例删除实体
|
||||
)
|
||||
|
||||
type FightMsg struct {
|
||||
@@ -65,20 +65,27 @@ type FightMsg struct {
|
||||
}
|
||||
|
||||
const (
|
||||
ServerAppidBindNotify = iota
|
||||
ServerUserOnlineStateChangeNotify
|
||||
ServerGetUserBaseInfoReq
|
||||
ServerGetUserBaseInfoRsp
|
||||
ServerUserGsChangeNotify
|
||||
ServerAppidBindNotify = iota // 玩家连接绑定的各个服务器appid通知
|
||||
ServerUserOnlineStateChangeNotify // 广播玩家上线和离线状态以及所在GS的appid
|
||||
ServerUserBaseInfoReq // 跨服玩家基础数据请求
|
||||
ServerUserBaseInfoRsp // 跨服玩家基础数据响应
|
||||
ServerUserGsChangeNotify // 跨服玩家迁移通知
|
||||
ServerUserMpReq // 跨服多人世界相关请求
|
||||
ServerUserMpRsp // 跨服多人世界相关响应
|
||||
ServerChatMsgNotify // 跨服玩家聊天消息通知
|
||||
ServerAddFriendNotify // 跨服添加好友通知
|
||||
)
|
||||
|
||||
type ServerMsg struct {
|
||||
FightServerAppId string `msgpack:"FightServerAppId"`
|
||||
UserId uint32 `msgpack:"UserId"`
|
||||
IsOnline bool `msgpack:"IsOnline"`
|
||||
UserBaseInfo *UserBaseInfo `msgpack:"UserBaseInfo"`
|
||||
GameServerAppId string `msgpack:"GameServerAppId"`
|
||||
JoinHostUserId uint32 `msgpack:"JoinHostUserId"`
|
||||
FightServerAppId string `msgpack:"FightServerAppId"`
|
||||
UserId uint32 `msgpack:"UserId"`
|
||||
IsOnline bool `msgpack:"IsOnline"`
|
||||
UserBaseInfo *UserBaseInfo `msgpack:"UserBaseInfo"`
|
||||
GameServerAppId string `msgpack:"GameServerAppId"`
|
||||
JoinHostUserId uint32 `msgpack:"JoinHostUserId"`
|
||||
UserMpInfo *UserMpInfo `msgpack:"UserMpInfo"`
|
||||
ChatMsgInfo *ChatMsgInfo `msgpack:"ChatMsgInfo"`
|
||||
AddFriendInfo *AddFriendInfo `msgpack:"AddFriendInfo"`
|
||||
}
|
||||
|
||||
type OriginInfo struct {
|
||||
@@ -96,4 +103,32 @@ type UserBaseInfo struct {
|
||||
Signature string `msgpack:"Signature"`
|
||||
HeadImageId uint32 `msgpack:"HeadImageId"`
|
||||
WorldPlayerNum uint32 `msgpack:"WorldPlayerNum"`
|
||||
WorldLevel uint32 `msgpack:"WorldLevel"`
|
||||
Birthday []uint8 `msgpack:"Birthday"`
|
||||
}
|
||||
|
||||
type UserMpInfo struct {
|
||||
OriginInfo *OriginInfo `msgpack:"OriginInfo"`
|
||||
HostUserId uint32 `msgpack:"HostUserId"`
|
||||
ApplyUserId uint32 `msgpack:"ApplyUserId"`
|
||||
ApplyPlayerOnlineInfo *UserBaseInfo `msgpack:"ApplyPlayerOnlineInfo"`
|
||||
ApplyOk bool `msgpack:"ApplyOk"`
|
||||
Agreed bool `msgpack:"Agreed"`
|
||||
HostNickname string `msgpack:"HostNickname"`
|
||||
}
|
||||
|
||||
type ChatMsgInfo struct {
|
||||
Time uint32 `msgpack:"Time"`
|
||||
ToUid uint32 `msgpack:"ToUid"`
|
||||
Uid uint32 `msgpack:"Uid"`
|
||||
IsRead bool `msgpack:"IsRead"`
|
||||
MsgType uint8 `msgpack:"MsgType"`
|
||||
Text string `msgpack:"Text"`
|
||||
Icon uint32 `msgpack:"Icon"`
|
||||
}
|
||||
|
||||
type AddFriendInfo struct {
|
||||
OriginInfo *OriginInfo `msgpack:"OriginInfo"`
|
||||
TargetUserId uint32 `msgpack:"TargetUserId"`
|
||||
ApplyPlayerOnlineInfo *UserBaseInfo `msgpack:"ApplyPlayerOnlineInfo"`
|
||||
}
|
||||
|
||||
@@ -8,28 +8,34 @@ import (
|
||||
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
)
|
||||
|
||||
type Dao struct {
|
||||
client *mongo.Client
|
||||
db *mongo.Database
|
||||
mongo *mongo.Client
|
||||
db *mongo.Database
|
||||
}
|
||||
|
||||
func NewDao() (r *Dao) {
|
||||
r = new(Dao)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url).SetMinPoolSize(10).SetMaxPoolSize(100)
|
||||
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||
if err != nil {
|
||||
logger.Error("mongo connect error: %v", err)
|
||||
return nil
|
||||
}
|
||||
r.client = client
|
||||
err = client.Ping(context.TODO(), readpref.Primary())
|
||||
if err != nil {
|
||||
logger.Error("mongo ping error: %v", err)
|
||||
return nil
|
||||
}
|
||||
r.mongo = client
|
||||
r.db = client.Database("dispatch_hk4e")
|
||||
return r
|
||||
}
|
||||
|
||||
func (d *Dao) CloseDao() {
|
||||
err := d.client.Disconnect(context.TODO())
|
||||
err := d.mongo.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
logger.Error("mongo close error: %v", err)
|
||||
}
|
||||
|
||||
@@ -361,14 +361,14 @@ func (k *KcpConnectManager) closeKcpConn(session *Session, enetType uint32) {
|
||||
EventId: KcpConnCloseNotify,
|
||||
}
|
||||
// 通知GS玩家下线
|
||||
gameMsg := new(mq.GameMsg)
|
||||
gameMsg.UserId = session.userId
|
||||
connCtrlMsg := new(mq.ConnCtrlMsg)
|
||||
connCtrlMsg.UserId = session.userId
|
||||
k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeGame,
|
||||
EventId: mq.UserOfflineNotify,
|
||||
GameMsg: gameMsg,
|
||||
MsgType: mq.MsgTypeConnCtrl,
|
||||
EventId: mq.UserOfflineNotify,
|
||||
ConnCtrlMsg: connCtrlMsg,
|
||||
})
|
||||
logger.Info("send to gs user offline, ConvId: %v, UserId: %v", convId, gameMsg.UserId)
|
||||
logger.Info("send to gs user offline, ConvId: %v, UserId: %v", convId, connCtrlMsg.UserId)
|
||||
k.destroySessionChan <- session
|
||||
}
|
||||
|
||||
|
||||
7
go.mod
7
go.mod
@@ -50,8 +50,13 @@ require github.com/byebyebruce/natsrpc v0.5.5-0.20221125150611-56cd29a4e335
|
||||
// cobra
|
||||
require github.com/spf13/cobra v1.6.1
|
||||
|
||||
// redis
|
||||
require github.com/go-redis/redis/v8 v8.11.5
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
@@ -83,6 +88,6 @@ require (
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
14
go.sum
14
go.sum
@@ -6,15 +6,20 @@ github.com/arl/statsviz v0.5.1/go.mod h1:zDnjgRblGm1Dyd7J5YlbH7gM1/+HRC+SfkhZhQb
|
||||
github.com/byebyebruce/natsrpc v0.5.5-0.20221125150611-56cd29a4e335 h1:V5qahA5kDL/TBnlwvYjemR5du/uQ7q75qkBBlTc4rXI=
|
||||
github.com/byebyebruce/natsrpc v0.5.5-0.20221125150611-56cd29a4e335/go.mod h1:w61gLVOQWr/Tq/1wxSOMLxDPbH66rEo8jEHMh7j3qjo=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
@@ -27,6 +32,8 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.0 h1:EmVIxB5jzbllGIjiCV5JG4VylbK3KE400tLGLI1cdfU=
|
||||
@@ -96,6 +103,9 @@ github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
|
||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -212,9 +222,11 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -6,31 +6,55 @@ import (
|
||||
"hk4e/common/config"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
)
|
||||
|
||||
type Dao struct {
|
||||
client *mongo.Client
|
||||
db *mongo.Database
|
||||
mongo *mongo.Client
|
||||
db *mongo.Database
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewDao() (r *Dao, err error) {
|
||||
r = new(Dao)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url).SetMinPoolSize(1).SetMaxPoolSize(10)
|
||||
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||
if err != nil {
|
||||
logger.Error("mongo connect error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
r.client = client
|
||||
err = client.Ping(context.TODO(), readpref.Primary())
|
||||
if err != nil {
|
||||
logger.Error("mongo ping error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
r.mongo = client
|
||||
r.db = client.Database("gs_hk4e")
|
||||
r.redis = redis.NewClient(&redis.Options{
|
||||
Addr: config.CONF.Redis.Addr,
|
||||
Password: config.CONF.Redis.Password,
|
||||
DB: 0,
|
||||
PoolSize: 10,
|
||||
MinIdleConns: 1,
|
||||
})
|
||||
err = r.redis.Ping(context.TODO()).Err()
|
||||
if err != nil {
|
||||
logger.Error("redis ping error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (d *Dao) CloseDao() {
|
||||
err := d.client.Disconnect(context.TODO())
|
||||
err := d.mongo.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
logger.Error("mongo close error: %v", err)
|
||||
}
|
||||
err = d.redis.Close()
|
||||
if err != nil {
|
||||
logger.Error("redis close error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
53
gs/dao/player_redis.go
Normal file
53
gs/dao/player_redis.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
const RedisPlayerKeyPrefix = "HK4E"
|
||||
|
||||
func (d *Dao) GetRedisPlayerKey(userId uint32) string {
|
||||
return RedisPlayerKeyPrefix + ":USER:" + strconv.Itoa(int(userId))
|
||||
}
|
||||
|
||||
func (d *Dao) GetRedisPlayer(userId uint32) *model.Player {
|
||||
playerData, err := d.redis.Get(context.TODO(), d.GetRedisPlayerKey(userId)).Result()
|
||||
if err != nil {
|
||||
logger.Error("get player from redis error: %v", err)
|
||||
return nil
|
||||
}
|
||||
player := new(model.Player)
|
||||
err = msgpack.Unmarshal([]byte(playerData), player)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (d *Dao) SetRedisPlayer(player *model.Player) {
|
||||
playerData, err := msgpack.Marshal(player)
|
||||
if err != nil {
|
||||
logger.Error("marshal player error: %v", err)
|
||||
return
|
||||
}
|
||||
err = d.redis.Set(context.TODO(), d.GetRedisPlayerKey(player.PlayerID), playerData, time.Hour*24*30).Err()
|
||||
if err != nil {
|
||||
logger.Error("set player from redis error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dao) SetRedisPlayerList(playerList []*model.Player) {
|
||||
// TODO 换成redis批量命令执行
|
||||
for _, player := range playerList {
|
||||
d.SetRedisPlayer(player)
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func (c *CommandManager) SendMessage(executor any, msg string, param ...any) {
|
||||
case *model.Player:
|
||||
// 玩家类型
|
||||
player := executor.(*model.Player)
|
||||
GAME_MANAGER.SendPrivateChat(c.system, player, fmt.Sprintf(msg, param...))
|
||||
GAME_MANAGER.SendPrivateChat(c.system, player.PlayerID, fmt.Sprintf(msg, param...))
|
||||
case string:
|
||||
// GM接口等
|
||||
// str := executor.(string)
|
||||
|
||||
@@ -26,12 +26,12 @@ var USER_MANAGER *UserManager = nil
|
||||
var WORLD_MANAGER *WorldManager = nil
|
||||
var TICK_MANAGER *TickManager = nil
|
||||
var COMMAND_MANAGER *CommandManager = nil
|
||||
var MESSAGE_QUEUE *mq.MessageQueue
|
||||
|
||||
var SELF *model.Player
|
||||
|
||||
type GameManager struct {
|
||||
dao *dao.Dao
|
||||
messageQueue *mq.MessageQueue
|
||||
snowflake *alg.SnowflakeWorker
|
||||
clientCmdProtoMap *client_proto.ClientCmdProtoMap
|
||||
clientCmdProtoMapRefValue reflect.Value
|
||||
@@ -40,7 +40,7 @@ type GameManager struct {
|
||||
func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue, gsId uint32) (r *GameManager) {
|
||||
r = new(GameManager)
|
||||
r.dao = dao
|
||||
r.messageQueue = messageQueue
|
||||
MESSAGE_QUEUE = messageQueue
|
||||
r.snowflake = alg.NewSnowflakeWorker(int64(gsId))
|
||||
if appConfig.CONF.Hk4e.ClientProtoProxyEnable {
|
||||
r.clientCmdProtoMap = client_proto.NewClientCmdProtoMap()
|
||||
@@ -115,7 +115,7 @@ func (g *GameManager) gameMainLoop() {
|
||||
commandCost = 0
|
||||
}
|
||||
select {
|
||||
case netMsg := <-g.messageQueue.GetNetMsg():
|
||||
case netMsg := <-MESSAGE_QUEUE.GetNetMsg():
|
||||
// 接收客户端消息
|
||||
start := time.Now().UnixNano()
|
||||
ROUTE_MANAGER.RouteHandle(netMsg)
|
||||
@@ -171,7 +171,7 @@ func (g *GameManager) SendMsgEx(cmdId uint16, userId uint32, clientSeq uint32, g
|
||||
ClientSeq: clientSeq,
|
||||
PayloadMessage: payloadMsg,
|
||||
}
|
||||
g.messageQueue.SendToGate(gateAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGate(gateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeGame,
|
||||
EventId: mq.NormalMsg,
|
||||
GameMsg: gameMsg,
|
||||
@@ -203,7 +203,7 @@ func (g *GameManager) SendMsg(cmdId uint16, userId uint32, clientSeq uint32, pay
|
||||
return
|
||||
}
|
||||
gameMsg.PayloadMessageData = payloadMessageData
|
||||
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeGame,
|
||||
EventId: mq.NormalMsg,
|
||||
GameMsg: gameMsg,
|
||||
@@ -271,7 +271,7 @@ func (g *GameManager) DisconnectPlayer(userId uint32, reason uint32) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeConnCtrl,
|
||||
EventId: mq.KickPlayerNotify,
|
||||
ConnCtrlMsg: &mq.ConnCtrlMsg{
|
||||
|
||||
@@ -3,6 +3,7 @@ package game
|
||||
import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
@@ -11,9 +12,10 @@ import (
|
||||
// 本地事件队列管理器
|
||||
|
||||
const (
|
||||
LoadLoginUserFromDbFinish = iota
|
||||
CheckUserExistOnRegFromDbFinish
|
||||
RunUserCopyAndSave
|
||||
LoadLoginUserFromDbFinish = iota // 玩家登录从数据库加载完成回调
|
||||
CheckUserExistOnRegFromDbFinish // 玩家注册从数据库查询是否已存在完成回调
|
||||
RunUserCopyAndSave // 执行一次在线玩家内存数据复制到数据库写入协程
|
||||
UserOfflineSaveToDbFinish
|
||||
)
|
||||
|
||||
type LocalEvent struct {
|
||||
@@ -89,5 +91,30 @@ func (l *LocalEventManager) LocalEventHandle(localEvent *LocalEvent) {
|
||||
endTime := time.Now().UnixNano()
|
||||
costTime := endTime - startTime
|
||||
logger.Info("run save user copy cost time: %v ns", costTime)
|
||||
case UserOfflineSaveToDbFinish:
|
||||
playerOfflineInfo := localEvent.Msg.(*PlayerOfflineInfo)
|
||||
USER_MANAGER.DeleteUser(playerOfflineInfo.Player.PlayerID)
|
||||
MESSAGE_QUEUE.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: playerOfflineInfo.Player.PlayerID,
|
||||
IsOnline: false,
|
||||
},
|
||||
})
|
||||
if playerOfflineInfo.ChangeGsInfo.IsChangeGs {
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(playerOfflineInfo.ChangeGsInfo.JoinHostUserId)
|
||||
MESSAGE_QUEUE.SendToGate(playerOfflineInfo.Player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserGsChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: playerOfflineInfo.Player.PlayerID,
|
||||
GameServerAppId: gsAppId,
|
||||
JoinHostUserId: playerOfflineInfo.ChangeGsInfo.JoinHostUserId,
|
||||
},
|
||||
})
|
||||
logger.Info("user change gs notify to gate, uid: %v, gate appid: %v, gs appid: %v, host uid: %v",
|
||||
playerOfflineInfo.Player.PlayerID, playerOfflineInfo.Player.GateAppId, gsAppId, playerOfflineInfo.ChangeGsInfo.JoinHostUserId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa
|
||||
GAME_MANAGER.DisconnectPlayer(userId, kcp.EnetNotFoundSession)
|
||||
return
|
||||
}
|
||||
if !player.Online {
|
||||
logger.Error("player not online, uid: %v", userId)
|
||||
return
|
||||
}
|
||||
player.ClientSeq = clientSeq
|
||||
SELF = player
|
||||
handlerFunc(player, payloadMsg)
|
||||
@@ -139,8 +143,6 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
return
|
||||
}
|
||||
r.doRoute(gameMsg.CmdId, gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
case mq.UserOfflineNotify:
|
||||
GAME_MANAGER.OnUserOffline(gameMsg.UserId)
|
||||
}
|
||||
case mq.MsgTypeConnCtrl:
|
||||
if netMsg.OriginServerType != api.GATE {
|
||||
@@ -152,6 +154,10 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
GAME_MANAGER.ClientRttNotify(connCtrlMsg.UserId, connCtrlMsg.ClientRtt)
|
||||
case mq.ClientTimeNotify:
|
||||
GAME_MANAGER.ClientTimeNotify(connCtrlMsg.UserId, connCtrlMsg.ClientTime)
|
||||
case mq.UserOfflineNotify:
|
||||
GAME_MANAGER.OnUserOffline(connCtrlMsg.UserId, &ChangeGsInfo{
|
||||
IsChangeGs: false,
|
||||
})
|
||||
}
|
||||
case mq.MsgTypeServer:
|
||||
serverMsg := netMsg.ServerMsg
|
||||
@@ -161,10 +167,18 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
USER_MANAGER.SetRemoteUserOnlineState(serverMsg.UserId, serverMsg.IsOnline, netMsg.OriginServerAppId)
|
||||
case mq.ServerAppidBindNotify:
|
||||
GAME_MANAGER.ServerAppidBindNotify(serverMsg.UserId, serverMsg.FightServerAppId, serverMsg.JoinHostUserId)
|
||||
case mq.ServerGetUserBaseInfoReq:
|
||||
GAME_MANAGER.ServerGetUserBaseInfoReq(serverMsg.UserBaseInfo, netMsg.OriginServerAppId)
|
||||
case mq.ServerGetUserBaseInfoRsp:
|
||||
GAME_MANAGER.ServerGetUserBaseInfoRsp(serverMsg.UserBaseInfo)
|
||||
case mq.ServerUserBaseInfoReq:
|
||||
GAME_MANAGER.ServerUserBaseInfoReq(serverMsg.UserBaseInfo, netMsg.OriginServerAppId)
|
||||
case mq.ServerUserBaseInfoRsp:
|
||||
GAME_MANAGER.ServerUserBaseInfoRsp(serverMsg.UserBaseInfo)
|
||||
case mq.ServerUserMpReq:
|
||||
GAME_MANAGER.ServerUserMpReq(serverMsg.UserMpInfo, netMsg.OriginServerAppId)
|
||||
case mq.ServerUserMpRsp:
|
||||
GAME_MANAGER.ServerUserMpRsp(serverMsg.UserMpInfo)
|
||||
case mq.ServerChatMsgNotify:
|
||||
GAME_MANAGER.ServerChatMsgNotify(serverMsg.ChatMsgInfo)
|
||||
case mq.ServerAddFriendNotify:
|
||||
GAME_MANAGER.ServerAddFriendNotify(serverMsg.AddFriendInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package game
|
||||
import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/protocol/cmd"
|
||||
@@ -78,15 +79,14 @@ func (g *GameManager) PullPrivateChatReq(player *model.Player, payloadMsg pb.Mes
|
||||
}
|
||||
|
||||
// SendPrivateChat 发送私聊文本消息给玩家
|
||||
func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, content any) {
|
||||
func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, content any) {
|
||||
chatInfo := &proto.ChatInfo{
|
||||
Time: uint32(time.Now().Unix()),
|
||||
Sequence: 101,
|
||||
ToUid: targetPlayer.PlayerID,
|
||||
ToUid: targetUid,
|
||||
Uid: player.PlayerID,
|
||||
IsRead: false,
|
||||
}
|
||||
|
||||
// 根据传入的值判断消息类型
|
||||
switch content.(type) {
|
||||
case string:
|
||||
@@ -100,21 +100,52 @@ func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, conten
|
||||
Icon: content.(uint32),
|
||||
}
|
||||
}
|
||||
|
||||
chatMsg := g.ConvChatInfoToChatMsg(chatInfo)
|
||||
// 消息加入自己的队列
|
||||
msgList, exist := player.ChatMsgMap[targetPlayer.PlayerID]
|
||||
msgList, exist := player.ChatMsgMap[targetUid]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
player.ChatMsgMap[targetPlayer.PlayerID] = msgList
|
||||
msgList = append(msgList, chatMsg)
|
||||
player.ChatMsgMap[targetUid] = msgList
|
||||
|
||||
privateChatNotify := &proto.PrivateChatNotify{
|
||||
ChatInfo: chatInfo,
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, player.PlayerID, player.ClientSeq, privateChatNotify)
|
||||
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 目标玩家在别的服在线
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerChatMsgNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
ChatMsgInfo: &mq.ChatMsgInfo{
|
||||
Time: chatMsg.Time,
|
||||
ToUid: chatMsg.ToUid,
|
||||
Uid: chatMsg.Uid,
|
||||
IsRead: chatMsg.IsRead,
|
||||
MsgType: chatMsg.MsgType,
|
||||
Text: chatMsg.Text,
|
||||
Icon: chatMsg.Icon,
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// 目标玩家全服离线
|
||||
// TODO 接入redis直接同步写入数据
|
||||
}
|
||||
return
|
||||
}
|
||||
// 消息加入目标玩家的队列
|
||||
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
msgList = append(msgList, chatMsg)
|
||||
targetPlayer.ChatMsgMap[player.PlayerID] = msgList
|
||||
|
||||
// 如果目标玩家在线发送消息
|
||||
@@ -124,11 +155,6 @@ func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, conten
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, targetPlayer.PlayerID, player.ClientSeq, privateChatNotify)
|
||||
}
|
||||
|
||||
privateChatNotify := &proto.PrivateChatNotify{
|
||||
ChatInfo: chatInfo,
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, player.PlayerID, player.ClientSeq, privateChatNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -137,12 +163,6 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
targetUid := req.TargetUid
|
||||
content := req.Content
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 根据发送的类型发送消息
|
||||
switch content.(type) {
|
||||
case *proto.PrivateChatReq_Text:
|
||||
@@ -150,25 +170,14 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
if len(text) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 发送私聊文本消息
|
||||
g.SendPrivateChat(player, targetPlayer, text)
|
||||
|
||||
g.SendPrivateChat(player, targetUid, text)
|
||||
// 输入命令 会检测是否为命令的
|
||||
COMMAND_MANAGER.InputCommand(player, text)
|
||||
|
||||
if text == "VPU" {
|
||||
g.VideoPlayerUpdate(false)
|
||||
} else if text == "VPUR" {
|
||||
g.VideoPlayerUpdate(true)
|
||||
}
|
||||
|
||||
case *proto.PrivateChatReq_Icon:
|
||||
icon := content.(*proto.PrivateChatReq_Icon).Icon
|
||||
|
||||
// 发送私聊图标消息
|
||||
g.SendPrivateChat(player, targetPlayer, icon)
|
||||
|
||||
g.SendPrivateChat(player, targetUid, icon)
|
||||
default:
|
||||
return
|
||||
}
|
||||
@@ -281,3 +290,37 @@ func (g *GameManager) ConvChatMsgToChatInfo(chatMsg *model.ChatMsg) (chatInfo *p
|
||||
}
|
||||
return chatInfo
|
||||
}
|
||||
|
||||
// 跨服玩家聊天通知
|
||||
|
||||
func (g *GameManager) ServerChatMsgNotify(chatMsgInfo *mq.ChatMsgInfo) {
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(chatMsgInfo.ToUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", chatMsgInfo.ToUid)
|
||||
return
|
||||
}
|
||||
chatMsg := &model.ChatMsg{
|
||||
Time: chatMsgInfo.Time,
|
||||
ToUid: chatMsgInfo.ToUid,
|
||||
Uid: chatMsgInfo.Uid,
|
||||
IsRead: chatMsgInfo.IsRead,
|
||||
MsgType: chatMsgInfo.MsgType,
|
||||
Text: chatMsgInfo.Text,
|
||||
Icon: chatMsgInfo.Icon,
|
||||
}
|
||||
// 消息加入目标玩家的队列
|
||||
msgList, exist := targetPlayer.ChatMsgMap[chatMsgInfo.Uid]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, chatMsg)
|
||||
targetPlayer.ChatMsgMap[chatMsgInfo.Uid] = msgList
|
||||
|
||||
// 如果目标玩家在线发送消息
|
||||
if targetPlayer.Online {
|
||||
privateChatNotify := &proto.PrivateChatNotify{
|
||||
ChatInfo: g.ConvChatMsgToChatInfo(chatMsg),
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, privateChatNotify)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package game
|
||||
import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/constant"
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
@@ -131,7 +130,10 @@ func (g *GameManager) ServerAppidBindNotify(userId uint32, fightAppId string, jo
|
||||
}
|
||||
if joinHostUserId != 0 {
|
||||
hostPlayer := USER_MANAGER.GetOnlineUser(joinHostUserId)
|
||||
g.HostEnterMpWorld(hostPlayer, player.PlayerID)
|
||||
if hostPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", joinHostUserId)
|
||||
return
|
||||
}
|
||||
g.JoinOtherWorld(player, hostPlayer)
|
||||
return
|
||||
}
|
||||
@@ -139,7 +141,7 @@ func (g *GameManager) ServerAppidBindNotify(userId uint32, fightAppId string, jo
|
||||
player.FightAppId = fightAppId
|
||||
// 创建世界
|
||||
world := WORLD_MANAGER.CreateWorld(player)
|
||||
GAME_MANAGER.messageQueue.SendToFight(fightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(fightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.AddFightRoutine,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -153,53 +155,3 @@ func (g *GameManager) ServerAppidBindNotify(userId uint32, fightAppId string, jo
|
||||
player.SceneLoadState = model.SceneNone
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, userId, player.ClientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_SELF))
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerGetUserBaseInfoReq(userBaseInfo *mq.UserBaseInfo, gsAppId string) {
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.UserId)
|
||||
return
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
g.messageQueue.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerGetUserBaseInfoRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: userBaseInfo.OriginInfo,
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: uint8(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldPlayerNum: uint32(world.GetWorldPlayerNum()),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerGetUserBaseInfoRsp(userBaseInfo *mq.UserBaseInfo) {
|
||||
switch userBaseInfo.OriginInfo.CmdName {
|
||||
case "GetOnlinePlayerInfoReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
g.SendMsg(cmd.GetOnlinePlayerInfoRsp, player.PlayerID, player.ClientSeq, &proto.GetOnlinePlayerInfoRsp{
|
||||
TargetUid: userBaseInfo.UserId,
|
||||
TargetPlayerInfo: &proto.OnlinePlayerInfo{
|
||||
Uid: userBaseInfo.UserId,
|
||||
Nickname: userBaseInfo.Nickname,
|
||||
PlayerLevel: userBaseInfo.PlayerLevel,
|
||||
MpSettingType: proto.MpSettingType(userBaseInfo.MpSettingType),
|
||||
NameCardId: userBaseInfo.NameCardId,
|
||||
Signature: userBaseInfo.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userBaseInfo.HeadImageId},
|
||||
CurPlayerNumInWorld: userBaseInfo.WorldPlayerNum,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,14 +61,16 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u
|
||||
|
||||
g.LoginNotify(userId, player, clientSeq)
|
||||
|
||||
g.messageQueue.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: userId,
|
||||
IsOnline: true,
|
||||
},
|
||||
})
|
||||
if userId >= 100000000 {
|
||||
MESSAGE_QUEUE.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: userId,
|
||||
IsOnline: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) OnReg(userId uint32, clientSeq uint32, gateAppId string, payloadMsg pb.Message) {
|
||||
@@ -106,7 +108,7 @@ func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userI
|
||||
g.OnLogin(userId, clientSeq, gateAppId)
|
||||
}
|
||||
|
||||
func (g *GameManager) OnUserOffline(userId uint32) {
|
||||
func (g *GameManager) OnUserOffline(userId uint32, changeGsInfo *ChangeGsInfo) {
|
||||
logger.Info("user offline, uid: %v", userId)
|
||||
player := USER_MANAGER.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
@@ -120,16 +122,7 @@ func (g *GameManager) OnUserOffline(userId uint32) {
|
||||
player.OfflineTime = uint32(time.Now().Unix())
|
||||
player.Online = false
|
||||
player.TotalOnlineTime += uint32(time.Now().UnixMilli()) - player.OnlineTime
|
||||
USER_MANAGER.DeleteUser(player)
|
||||
|
||||
g.messageQueue.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: userId,
|
||||
IsOnline: false,
|
||||
},
|
||||
})
|
||||
USER_MANAGER.OfflineUser(player, changeGsInfo)
|
||||
}
|
||||
|
||||
func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq uint32) {
|
||||
|
||||
@@ -6,56 +6,36 @@ import (
|
||||
"hk4e/gs/dao"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
"hk4e/protocol/proto"
|
||||
)
|
||||
|
||||
type SaveUserData struct {
|
||||
insertPlayerList []*model.Player
|
||||
updatePlayerList []*model.Player
|
||||
}
|
||||
// 玩家管理器
|
||||
|
||||
// 玩家注册 从db查询对应uid是否存在并异步回调返回结果
|
||||
// 玩家登录 从db查询出来然后写入redis并异步回调返回玩家对象
|
||||
// 玩家离线 写入db和redis
|
||||
// 玩家定时保存 写入db和redis
|
||||
|
||||
type UserManager struct {
|
||||
dao *dao.Dao
|
||||
playerMap map[uint32]*model.Player
|
||||
saveUserChan chan *SaveUserData
|
||||
remotePlayerMap map[uint32]string // 远程玩家 key:userId value:玩家所在gs的appid
|
||||
dao *dao.Dao // db对象
|
||||
playerMap map[uint32]*model.Player // 内存玩家数据
|
||||
saveUserChan chan *SaveUserData // 用于主协程发送玩家数据给定时保存协程
|
||||
remotePlayerMap map[uint32]string // 远程玩家 key:userId value:玩家所在gs的appid
|
||||
}
|
||||
|
||||
func NewUserManager(dao *dao.Dao) (r *UserManager) {
|
||||
r = new(UserManager)
|
||||
r.dao = dao
|
||||
r.playerMap = make(map[uint32]*model.Player)
|
||||
r.saveUserChan = make(chan *SaveUserData)
|
||||
r.saveUserChan = make(chan *SaveUserData) // 无缓冲区chan 避免主协程在写入时被迫加锁
|
||||
r.remotePlayerMap = make(map[uint32]string)
|
||||
return r
|
||||
}
|
||||
|
||||
func (u *UserManager) GetRemoteUserOnlineState(userId uint32) bool {
|
||||
_, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) GetRemoteUserGsAppId(userId uint32) string {
|
||||
appId, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return ""
|
||||
} else {
|
||||
return appId
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) SetRemoteUserOnlineState(userId uint32, isOnline bool, appId string) {
|
||||
if isOnline {
|
||||
u.remotePlayerMap[userId] = appId
|
||||
} else {
|
||||
delete(u.remotePlayerMap, userId)
|
||||
}
|
||||
}
|
||||
// 在线玩家相关操作
|
||||
|
||||
// GetUserOnlineState 获取玩家在线状态
|
||||
func (u *UserManager) GetUserOnlineState(userId uint32) bool {
|
||||
player, exist := u.playerMap[userId]
|
||||
if !exist {
|
||||
@@ -65,6 +45,7 @@ func (u *UserManager) GetUserOnlineState(userId uint32) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// GetOnlineUser 获取在线玩家对象
|
||||
func (u *UserManager) GetOnlineUser(userId uint32) *model.Player {
|
||||
player, exist := u.playerMap[userId]
|
||||
if !exist {
|
||||
@@ -78,6 +59,7 @@ func (u *UserManager) GetOnlineUser(userId uint32) *model.Player {
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllOnlineUserList 获取全部在线玩家
|
||||
func (u *UserManager) GetAllOnlineUserList() map[uint32]*model.Player {
|
||||
onlinePlayerMap := make(map[uint32]*model.Player)
|
||||
for userId, player := range u.playerMap {
|
||||
@@ -97,13 +79,14 @@ type PlayerRegInfo struct {
|
||||
GateAppId string
|
||||
}
|
||||
|
||||
// CheckUserExistOnReg 玩家注册检查是否已存在
|
||||
func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBornDataReq, clientSeq uint32, gateAppId string) (exist bool, asyncWait bool) {
|
||||
_, exist = u.playerMap[userId]
|
||||
if exist {
|
||||
return true, false
|
||||
} else {
|
||||
go func() {
|
||||
player := u.loadUserFromDb(userId)
|
||||
player := u.LoadUserFromDbSync(userId)
|
||||
exist = false
|
||||
if player != nil {
|
||||
exist = true
|
||||
@@ -123,38 +106,7 @@ func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBor
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadTempOfflineUserSync(userId uint32) *model.Player {
|
||||
player, exist := u.playerMap[userId]
|
||||
if exist {
|
||||
return player
|
||||
} else {
|
||||
player = u.loadUserFromDb(userId)
|
||||
if player == nil {
|
||||
return nil
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMap[player.PlayerID] = player
|
||||
return player
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) loadUserFromDb(userId uint32) *model.Player {
|
||||
player, err := u.dao.QueryPlayerByID(userId)
|
||||
if err != nil {
|
||||
logger.Error("query player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) saveUserToDb(player *model.Player) {
|
||||
err := u.dao.UpdatePlayer(player)
|
||||
if err != nil {
|
||||
logger.Error("update player error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// AddUser 向内存玩家数据里添加一个玩家
|
||||
func (u *UserManager) AddUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
@@ -163,12 +115,9 @@ func (u *UserManager) AddUser(player *model.Player) {
|
||||
u.playerMap[player.PlayerID] = player
|
||||
}
|
||||
|
||||
func (u *UserManager) DeleteUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMap[player.PlayerID] = player
|
||||
// DeleteUser 从内存玩家数据里删除一个玩家
|
||||
func (u *UserManager) DeleteUser(userId uint32) {
|
||||
delete(u.playerMap, userId)
|
||||
}
|
||||
|
||||
type PlayerLoginInfo struct {
|
||||
@@ -178,6 +127,7 @@ type PlayerLoginInfo struct {
|
||||
GateAppId string
|
||||
}
|
||||
|
||||
// OnlineUser 玩家上线
|
||||
func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId string) (*model.Player, bool) {
|
||||
player, exist := u.playerMap[userId]
|
||||
if exist {
|
||||
@@ -185,8 +135,9 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId stri
|
||||
return player, false
|
||||
} else {
|
||||
go func() {
|
||||
player = u.loadUserFromDb(userId)
|
||||
player = u.LoadUserFromDbSync(userId)
|
||||
if player != nil {
|
||||
u.SaveUserToRedisSync(player)
|
||||
u.ChangeUserDbState(player, model.DbNormal)
|
||||
} else {
|
||||
logger.Error("can not find user from db, uid: %v", userId)
|
||||
@@ -205,6 +156,38 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId stri
|
||||
}
|
||||
}
|
||||
|
||||
type ChangeGsInfo struct {
|
||||
IsChangeGs bool
|
||||
JoinHostUserId uint32
|
||||
}
|
||||
|
||||
type PlayerOfflineInfo struct {
|
||||
Player *model.Player
|
||||
ChangeGsInfo *ChangeGsInfo
|
||||
}
|
||||
|
||||
// OfflineUser 玩家离线
|
||||
func (u *UserManager) OfflineUser(player *model.Player, changeGsInfo *ChangeGsInfo) {
|
||||
playerCopy := new(model.Player)
|
||||
err := object.FastDeepCopy(playerCopy, player)
|
||||
if err != nil {
|
||||
logger.Error("deep copy player error: %v", err)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
u.SaveUserToDbSync(playerCopy)
|
||||
u.SaveUserToRedisSync(playerCopy)
|
||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||
EventId: UserOfflineSaveToDbFinish,
|
||||
Msg: &PlayerOfflineInfo{
|
||||
Player: player,
|
||||
ChangeGsInfo: changeGsInfo,
|
||||
},
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// ChangeUserDbState 玩家存档状态机 主要用于玩家定时保存时进行分类处理
|
||||
func (u *UserManager) ChangeUserDbState(player *model.Player, state int) {
|
||||
if player == nil {
|
||||
return
|
||||
@@ -238,8 +221,140 @@ func (u *UserManager) ChangeUserDbState(player *model.Player, state int) {
|
||||
}
|
||||
}
|
||||
|
||||
// 用户数据库定时同步
|
||||
// 远程玩家相关操作
|
||||
|
||||
func (u *UserManager) GetRemoteUserOnlineState(userId uint32) bool {
|
||||
_, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) GetRemoteUserGsAppId(userId uint32) string {
|
||||
appId, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return ""
|
||||
} else {
|
||||
return appId
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) SetRemoteUserOnlineState(userId uint32, isOnline bool, appId string) {
|
||||
if isOnline {
|
||||
u.remotePlayerMap[userId] = appId
|
||||
} else {
|
||||
delete(u.remotePlayerMap, userId)
|
||||
u.DeleteUser(userId)
|
||||
}
|
||||
}
|
||||
|
||||
// GetRemoteOnlineUserList 获取指定数量的远程在线玩家
|
||||
func (u *UserManager) GetRemoteOnlineUserList(total int) map[uint32]*model.Player {
|
||||
if total > 50 {
|
||||
return nil
|
||||
}
|
||||
onlinePlayerMap := make(map[uint32]*model.Player)
|
||||
count := 0
|
||||
for userId := range u.remotePlayerMap {
|
||||
player := u.LoadTempOfflineUser(userId)
|
||||
if player == nil {
|
||||
continue
|
||||
}
|
||||
onlinePlayerMap[player.PlayerID] = player
|
||||
count++
|
||||
if count >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return onlinePlayerMap
|
||||
}
|
||||
|
||||
// LoadGlobalPlayer 加载并返回一个全服玩家及其在线状态
|
||||
// 参见LoadTempOfflineUser说明
|
||||
func (u *UserManager) LoadGlobalPlayer(userId uint32) (player *model.Player, online bool, remote bool) {
|
||||
online = u.GetUserOnlineState(userId)
|
||||
remote = false
|
||||
if !online {
|
||||
// 本地不在线就看看远程在不在线
|
||||
online = u.GetRemoteUserOnlineState(userId)
|
||||
if online {
|
||||
remote = true
|
||||
}
|
||||
}
|
||||
if online {
|
||||
if remote {
|
||||
// 远程在线玩家 为了简化实现流程 直接加载数据库临时档
|
||||
player = u.LoadTempOfflineUser(userId)
|
||||
} else {
|
||||
// 本地在线玩家
|
||||
player = u.GetOnlineUser(userId)
|
||||
}
|
||||
} else {
|
||||
// 全服离线玩家
|
||||
player = u.LoadTempOfflineUser(userId)
|
||||
}
|
||||
return player, online, remote
|
||||
}
|
||||
|
||||
// 离线玩家相关操作
|
||||
|
||||
// LoadTempOfflineUser 加载临时离线玩家
|
||||
// 正常情况速度较快可以同步阻塞调用
|
||||
func (u *UserManager) LoadTempOfflineUser(userId uint32) *model.Player {
|
||||
player := u.GetOnlineUser(userId)
|
||||
if player != nil && player.Online {
|
||||
logger.Error("not allow get a online player as offline player, uid: %v", userId)
|
||||
return nil
|
||||
}
|
||||
player = u.LoadUserFromRedisSync(userId)
|
||||
if player == nil {
|
||||
// 玩家可能不存在于redis 尝试从db查询出来然后写入redis
|
||||
// 大多数情况下活跃玩家都在redis 所以不会走到下面
|
||||
// TODO 布隆过滤器防止恶意攻击造成redis缓存穿透
|
||||
if userId < 100000000 || userId > 200000000 {
|
||||
logger.Error("try to load a not exist uid, uid: %v", userId)
|
||||
return nil
|
||||
}
|
||||
player = u.LoadUserFromDbSync(userId)
|
||||
if player == nil {
|
||||
// 玩家根本就不存在
|
||||
logger.Error("try to load a not exist player from db, uid: %v", userId)
|
||||
return nil
|
||||
}
|
||||
u.SaveUserToRedisSync(player)
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMap[player.PlayerID] = player
|
||||
return player
|
||||
}
|
||||
|
||||
// SaveTempOfflineUser 保存临时离线玩家
|
||||
// 如果在调用LoadTempOfflineUser后修改了离线玩家数据 则必须立即调用此函数回写
|
||||
func (u *UserManager) SaveTempOfflineUser(player *model.Player) {
|
||||
// 主协程同步写入redis
|
||||
u.SaveUserToRedisSync(player)
|
||||
// 另一个协程异步的写回db
|
||||
playerCopy := new(model.Player)
|
||||
err := object.FastDeepCopy(playerCopy, player)
|
||||
if err != nil {
|
||||
logger.Error("deep copy player error: %v", err)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
u.SaveUserToDbSync(playerCopy)
|
||||
}()
|
||||
}
|
||||
|
||||
// db和redis相关操作
|
||||
|
||||
type SaveUserData struct {
|
||||
insertPlayerList []*model.Player
|
||||
updatePlayerList []*model.Player
|
||||
}
|
||||
|
||||
// StartAutoSaveUser 玩家定时保存
|
||||
func (u *UserManager) StartAutoSaveUser() {
|
||||
go func() {
|
||||
ticker := time.NewTicker(time.Minute * 5)
|
||||
@@ -253,12 +368,30 @@ func (u *UserManager) StartAutoSaveUser() {
|
||||
go func() {
|
||||
for {
|
||||
saveUserData := <-u.saveUserChan
|
||||
u.SaveUser(saveUserData)
|
||||
u.SaveUserListToDbSync(saveUserData)
|
||||
u.SaveUserListToRedisSync(saveUserData)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUser(saveUserData *SaveUserData) {
|
||||
func (u *UserManager) LoadUserFromDbSync(userId uint32) *model.Player {
|
||||
player, err := u.dao.QueryPlayerByID(userId)
|
||||
if err != nil {
|
||||
logger.Error("query player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserToDbSync(player *model.Player) {
|
||||
err := u.dao.UpdatePlayer(player)
|
||||
if err != nil {
|
||||
logger.Error("update player error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserListToDbSync(saveUserData *SaveUserData) {
|
||||
err := u.dao.InsertPlayerList(saveUserData.insertPlayerList)
|
||||
if err != nil {
|
||||
logger.Error("insert player list error: %v", err)
|
||||
@@ -271,3 +404,23 @@ func (u *UserManager) SaveUser(saveUserData *SaveUserData) {
|
||||
}
|
||||
logger.Info("save user finish, insert user count: %v, update user count: %v", len(saveUserData.insertPlayerList), len(saveUserData.updatePlayerList))
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadUserFromRedisSync(userId uint32) *model.Player {
|
||||
player := u.dao.GetRedisPlayer(userId)
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserToRedisSync(player *model.Player) {
|
||||
u.dao.SetRedisPlayer(player)
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserListToRedisSync(saveUserData *SaveUserData) {
|
||||
setPlayerList := make([]*model.Player, 0, len(saveUserData.insertPlayerList)+len(saveUserData.updatePlayerList))
|
||||
for _, player := range saveUserData.insertPlayerList {
|
||||
setPlayerList = append(setPlayerList, player)
|
||||
}
|
||||
for _, player := range saveUserData.updatePlayerList {
|
||||
setPlayerList = append(setPlayerList, player)
|
||||
}
|
||||
u.dao.SetRedisPlayerList(setPlayerList)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"hk4e/common/constant"
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gate/kcp"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
@@ -27,16 +26,7 @@ func (g *GameManager) PlayerApplyEnterMpReq(player *model.Player, payloadMsg pb.
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpRsp, player.PlayerID, player.ClientSeq, playerApplyEnterMpRsp)
|
||||
|
||||
ok := g.UserApplyEnterWorld(player, targetUid)
|
||||
if !ok {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: targetUid,
|
||||
TargetNickname: "",
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
g.UserApplyEnterWorld(player, targetUid)
|
||||
}
|
||||
|
||||
func (g *GameManager) PlayerApplyEnterMpResultReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -73,22 +63,12 @@ func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Mes
|
||||
if !USER_MANAGER.GetRemoteUserOnlineState(req.TargetUid) {
|
||||
// 全服不存在该在线玩家
|
||||
logger.Error("target user not online in any game server, uid: %v", req.TargetUid)
|
||||
g.DisconnectPlayer(player.PlayerID, kcp.EnetServerKick)
|
||||
return
|
||||
}
|
||||
// 走玩家在线跨服迁移流程
|
||||
g.OnUserOffline(player.PlayerID)
|
||||
// TODO 改成异步写入数据库
|
||||
USER_MANAGER.saveUserToDb(player)
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(req.TargetUid)
|
||||
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserGsChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: player.PlayerID,
|
||||
GameServerAppId: gsAppId,
|
||||
JoinHostUserId: req.TargetUid,
|
||||
},
|
||||
g.OnUserOffline(player.PlayerID, &ChangeGsInfo{
|
||||
IsChangeGs: true,
|
||||
JoinHostUserId: req.TargetUid,
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -98,13 +78,7 @@ func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Mes
|
||||
|
||||
func (g *GameManager) JoinOtherWorld(player *model.Player, hostPlayer *model.Player) {
|
||||
hostWorld := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId)
|
||||
_, exist := hostWorld.waitEnterPlayerMap[player.PlayerID]
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
|
||||
if hostPlayer.SceneLoadState == model.SceneEnterDone {
|
||||
delete(hostWorld.waitEnterPlayerMap, player.PlayerID)
|
||||
player.Pos.X = hostPlayer.Pos.X
|
||||
player.Pos.Y = hostPlayer.Pos.Y
|
||||
player.Pos.Z = hostPlayer.Pos.Z
|
||||
@@ -112,11 +86,13 @@ func (g *GameManager) JoinOtherWorld(player *model.Player, hostPlayer *model.Pla
|
||||
player.Rot.Y = hostPlayer.Rot.Y
|
||||
player.Rot.Z = hostPlayer.Rot.Z
|
||||
player.SceneId = hostPlayer.SceneId
|
||||
|
||||
g.UserWorldAddPlayer(hostWorld, player)
|
||||
|
||||
player.SceneLoadState = model.SceneNone
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_OTHER))
|
||||
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_OTHER)
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
|
||||
} else {
|
||||
hostWorld.waitEnterPlayerMap[player.PlayerID] = time.Now().UnixMilli()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +149,10 @@ func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Mes
|
||||
}
|
||||
targetUid := req.TargetUid
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", targetUid)
|
||||
return
|
||||
}
|
||||
ok := g.UserLeaveWorld(targetPlayer)
|
||||
if !ok {
|
||||
g.CommonRetError(cmd.SceneKickPlayerRsp, player, &proto.SceneKickPlayerRsp{}, proto.Retcode_RET_MP_TARGET_PLAYER_IN_TRANSFER)
|
||||
@@ -193,41 +173,112 @@ func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Mes
|
||||
g.SendMsg(cmd.SceneKickPlayerRsp, player.PlayerID, player.ClientSeq, sceneKickPlayerRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) UserApplyEnterWorld(player *model.Player, targetUid uint32) bool {
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return false
|
||||
func (g *GameManager) UserApplyEnterWorld(player *model.Player, targetUid uint32) {
|
||||
applyFailNotify := func() {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: targetUid,
|
||||
TargetNickname: "",
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
if world.multiplayer {
|
||||
return false
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
if !USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 全服不存在该在线玩家
|
||||
logger.Error("target user not online in any game server, uid: %v", targetUid)
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "PlayerApplyEnterMpReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
HostUserId: targetUid,
|
||||
ApplyUserId: player.PlayerID,
|
||||
ApplyPlayerOnlineInfo: &mq.UserBaseInfo{
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: uint8(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldPlayerNum: uint32(world.GetWorldPlayerNum()),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
applyTime, exist := targetPlayer.CoopApplyMap[player.PlayerID]
|
||||
if exist && time.Now().UnixNano() < applyTime+int64(10*time.Second) {
|
||||
return false
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
targetPlayer.CoopApplyMap[player.PlayerID] = time.Now().UnixNano()
|
||||
targetWorld := WORLD_MANAGER.GetWorldByID(targetPlayer.WorldId)
|
||||
if targetWorld.multiplayer && targetWorld.owner.PlayerID != targetPlayer.PlayerID {
|
||||
return false
|
||||
// 向同一世界内的非房主玩家申请时直接拒绝
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
|
||||
playerApplyEnterMpNotify := new(proto.PlayerApplyEnterMpNotify)
|
||||
playerApplyEnterMpNotify.SrcPlayerInfo = g.PacketOnlinePlayerInfo(player)
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, playerApplyEnterMpNotify)
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint32, agree bool) {
|
||||
otherPlayer := USER_MANAGER.GetOnlineUser(otherUid)
|
||||
if otherPlayer == nil {
|
||||
return
|
||||
}
|
||||
applyTime, exist := hostPlayer.CoopApplyMap[otherUid]
|
||||
if !exist || time.Now().UnixNano() > applyTime+int64(10*time.Second) {
|
||||
return
|
||||
}
|
||||
delete(hostPlayer.CoopApplyMap, otherUid)
|
||||
if !agree {
|
||||
return
|
||||
}
|
||||
g.HostEnterMpWorld(hostPlayer, otherUid)
|
||||
|
||||
otherPlayer := USER_MANAGER.GetOnlineUser(otherUid)
|
||||
if otherPlayer == nil {
|
||||
if !USER_MANAGER.GetRemoteUserOnlineState(otherUid) {
|
||||
// 全服不存在该在线玩家
|
||||
logger.Error("target user not online in any game server, uid: %v", otherUid)
|
||||
return
|
||||
}
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(otherUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "PlayerApplyEnterMpResultReq",
|
||||
UserId: hostPlayer.PlayerID,
|
||||
},
|
||||
HostUserId: hostPlayer.PlayerID,
|
||||
ApplyUserId: otherUid,
|
||||
Agreed: agree,
|
||||
HostNickname: hostPlayer.NickName,
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
otherPlayerWorld := WORLD_MANAGER.GetWorldByID(otherPlayer.WorldId)
|
||||
if otherPlayerWorld.multiplayer {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
@@ -247,15 +298,10 @@ func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_JUDGE,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
|
||||
if agree {
|
||||
g.HostEnterMpWorld(hostPlayer, otherPlayer.PlayerID)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) HostEnterMpWorld(hostPlayer *model.Player, otherPlayerId uint32) {
|
||||
func (g *GameManager) HostEnterMpWorld(hostPlayer *model.Player, otherUid uint32) {
|
||||
world := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId)
|
||||
world.waitEnterPlayerMap[otherPlayerId] = time.Now().UnixMilli()
|
||||
if world.multiplayer {
|
||||
return
|
||||
}
|
||||
@@ -286,7 +332,7 @@ func (g *GameManager) HostEnterMpWorld(hostPlayer *model.Player, otherPlayerId u
|
||||
|
||||
guestBeginEnterSceneNotify := &proto.GuestBeginEnterSceneNotify{
|
||||
SceneId: hostPlayer.SceneId,
|
||||
Uid: otherPlayerId,
|
||||
Uid: otherUid,
|
||||
}
|
||||
g.SendMsg(cmd.GuestBeginEnterSceneNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, guestBeginEnterSceneNotify)
|
||||
|
||||
@@ -357,7 +403,7 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player)
|
||||
if world.owner.PlayerID == player.PlayerID {
|
||||
// 房主离开销毁世界
|
||||
WORLD_MANAGER.DestroyWorld(world.id)
|
||||
GAME_MANAGER.messageQueue.SendToFight(world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.DelFightRoutine,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -462,3 +508,112 @@ func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *mod
|
||||
g.SendMsg(cmd.SyncScenePlayTeamEntityNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, syncScenePlayTeamEntityNotify)
|
||||
}
|
||||
}
|
||||
|
||||
// 跨服玩家多人世界相关请求
|
||||
|
||||
func (g *GameManager) ServerUserMpReq(userMpInfo *mq.UserMpInfo, gsAppId string) {
|
||||
switch userMpInfo.OriginInfo.CmdName {
|
||||
case "PlayerApplyEnterMpReq":
|
||||
applyFailNotify := func() {
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: userMpInfo.OriginInfo,
|
||||
HostUserId: userMpInfo.HostUserId,
|
||||
ApplyOk: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
hostPlayer := USER_MANAGER.GetOnlineUser(userMpInfo.HostUserId)
|
||||
if hostPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", userMpInfo.HostUserId)
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
applyTime, exist := hostPlayer.CoopApplyMap[userMpInfo.ApplyUserId]
|
||||
if exist && time.Now().UnixNano() < applyTime+int64(10*time.Second) {
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
hostPlayer.CoopApplyMap[userMpInfo.ApplyUserId] = time.Now().UnixNano()
|
||||
hostWorld := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId)
|
||||
if hostWorld.multiplayer && hostWorld.owner.PlayerID != hostPlayer.PlayerID {
|
||||
// 向同一世界内的非房主玩家申请时直接拒绝
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
|
||||
playerApplyEnterMpNotify := new(proto.PlayerApplyEnterMpNotify)
|
||||
playerApplyEnterMpNotify.SrcPlayerInfo = &proto.OnlinePlayerInfo{
|
||||
Uid: userMpInfo.ApplyPlayerOnlineInfo.UserId,
|
||||
Nickname: userMpInfo.ApplyPlayerOnlineInfo.Nickname,
|
||||
PlayerLevel: userMpInfo.ApplyPlayerOnlineInfo.PlayerLevel,
|
||||
MpSettingType: proto.MpSettingType(userMpInfo.ApplyPlayerOnlineInfo.MpSettingType),
|
||||
NameCardId: userMpInfo.ApplyPlayerOnlineInfo.NameCardId,
|
||||
Signature: userMpInfo.ApplyPlayerOnlineInfo.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userMpInfo.ApplyPlayerOnlineInfo.HeadImageId},
|
||||
CurPlayerNumInWorld: userMpInfo.ApplyPlayerOnlineInfo.WorldPlayerNum,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, playerApplyEnterMpNotify)
|
||||
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: userMpInfo.OriginInfo,
|
||||
HostUserId: userMpInfo.HostUserId,
|
||||
ApplyOk: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
case "PlayerApplyEnterMpResultReq":
|
||||
applyPlayer := USER_MANAGER.GetOnlineUser(userMpInfo.ApplyUserId)
|
||||
if applyPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", userMpInfo.ApplyUserId)
|
||||
return
|
||||
}
|
||||
applyPlayerWorld := WORLD_MANAGER.GetWorldByID(applyPlayer.WorldId)
|
||||
if applyPlayerWorld.multiplayer {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: userMpInfo.HostUserId,
|
||||
TargetNickname: userMpInfo.HostNickname,
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, applyPlayer.PlayerID, applyPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
return
|
||||
}
|
||||
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: userMpInfo.HostUserId,
|
||||
TargetNickname: userMpInfo.HostNickname,
|
||||
IsAgreed: userMpInfo.Agreed,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_JUDGE,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, applyPlayer.PlayerID, applyPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerUserMpRsp(userMpInfo *mq.UserMpInfo) {
|
||||
switch userMpInfo.OriginInfo.CmdName {
|
||||
case "PlayerApplyEnterMpReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userMpInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userMpInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
if !userMpInfo.ApplyOk {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: userMpInfo.HostUserId,
|
||||
TargetNickname: "",
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,21 +263,14 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
|
||||
world.PlayerEnter(player)
|
||||
|
||||
for otherPlayerId := range world.waitEnterPlayerMap {
|
||||
// 房主第一次进入多人世界场景完成 开始通知等待列表中的玩家进入场景
|
||||
delete(world.waitEnterPlayerMap, otherPlayerId)
|
||||
otherPlayer := USER_MANAGER.GetOnlineUser(otherPlayerId)
|
||||
otherPlayer.Pos.X = player.Pos.X
|
||||
otherPlayer.Pos.Y = player.Pos.Y
|
||||
otherPlayer.Pos.Z = player.Pos.Z
|
||||
otherPlayer.Rot.X = player.Rot.X
|
||||
otherPlayer.Rot.Y = player.Rot.Y
|
||||
otherPlayer.Rot.Z = player.Rot.Z
|
||||
otherPlayer.SceneId = player.SceneId
|
||||
|
||||
g.UserWorldAddPlayer(world, otherPlayer)
|
||||
|
||||
otherPlayer.SceneLoadState = model.SceneNone
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyLogin(otherPlayer, proto.EnterType_ENTER_TYPE_OTHER)
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerEnterSceneNotify)
|
||||
if otherPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", otherPlayerId)
|
||||
continue
|
||||
}
|
||||
g.JoinOtherWorld(otherPlayer, player)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,28 @@ func (g *GameManager) GetPlayerSocialDetailReq(player *model.Player, payloadMsg
|
||||
req := payloadMsg.(*proto.GetPlayerSocialDetailReq)
|
||||
targetUid := req.Uid
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
targetPlayer, _, remote := USER_MANAGER.LoadGlobalPlayer(targetUid)
|
||||
if targetPlayer == nil {
|
||||
g.CommonRetError(cmd.GetPlayerSocialDetailRsp, player, &proto.GetPlayerSocialDetailRsp{}, proto.Retcode_RET_PLAYER_NOT_EXIST)
|
||||
return
|
||||
}
|
||||
if remote {
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserBaseInfoReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "GetPlayerSocialDetailReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
UserId: targetUid,
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
_, exist := player.FriendList[targetPlayer.PlayerID]
|
||||
socialDetail := &proto.SocialDetail{
|
||||
Uid: targetPlayer.PlayerID,
|
||||
@@ -160,19 +176,18 @@ func (g *GameManager) GetPlayerFriendListReq(player *model.Player, payloadMsg pb
|
||||
// 用于实现好友列表内的系统且不更改原先的内容
|
||||
tempFriendList := COMMAND_MANAGER.GetFriendList(player.FriendList)
|
||||
for uid := range tempFriendList {
|
||||
// TODO 同步阻塞待优化
|
||||
var onlineState proto.FriendOnlineState
|
||||
online := USER_MANAGER.GetUserOnlineState(uid)
|
||||
|
||||
friendPlayer, online, _ := USER_MANAGER.LoadGlobalPlayer(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
var onlineState proto.FriendOnlineState = 0
|
||||
if online {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE
|
||||
} else {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_DISCONNECT
|
||||
}
|
||||
friendPlayer := USER_MANAGER.LoadTempOfflineUserSync(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
friendBrief := &proto.FriendBrief{
|
||||
Uid: friendPlayer.PlayerID,
|
||||
Nickname: friendPlayer.NickName,
|
||||
@@ -200,19 +215,17 @@ func (g *GameManager) GetPlayerAskFriendListReq(player *model.Player, payloadMsg
|
||||
AskFriendList: make([]*proto.FriendBrief, 0),
|
||||
}
|
||||
for uid := range player.FriendApplyList {
|
||||
// TODO 同步阻塞待优化
|
||||
friendPlayer, online, _ := USER_MANAGER.LoadGlobalPlayer(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
var onlineState proto.FriendOnlineState
|
||||
online := USER_MANAGER.GetUserOnlineState(uid)
|
||||
if online {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE
|
||||
} else {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_DISCONNECT
|
||||
}
|
||||
friendPlayer := USER_MANAGER.LoadTempOfflineUserSync(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
friendBrief := &proto.FriendBrief{
|
||||
Uid: friendPlayer.PlayerID,
|
||||
Nickname: friendPlayer.NickName,
|
||||
@@ -238,13 +251,58 @@ func (g *GameManager) AskAddFriendReq(player *model.Player, payloadMsg pb.Messag
|
||||
req := payloadMsg.(*proto.AskAddFriendReq)
|
||||
targetUid := req.TargetUid
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayerOnline := USER_MANAGER.GetUserOnlineState(targetUid)
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
askAddFriendRsp := &proto.AskAddFriendRsp{
|
||||
TargetUid: targetUid,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendRsp, player.PlayerID, player.ClientSeq, askAddFriendRsp)
|
||||
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("apply add friend target player is nil, uid: %v", player.PlayerID)
|
||||
// 非本地玩家
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 远程在线玩家
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerAddFriendNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
AddFriendInfo: &mq.AddFriendInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "AskAddFriendReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
TargetUserId: targetUid,
|
||||
ApplyPlayerOnlineInfo: &mq.UserBaseInfo{
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// 全服离线玩家
|
||||
targetPlayer, _, _ := USER_MANAGER.LoadGlobalPlayer(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("apply add friend target player is nil, uid: %v", targetUid)
|
||||
return
|
||||
}
|
||||
_, applyExist := targetPlayer.FriendApplyList[player.PlayerID]
|
||||
_, friendExist := targetPlayer.FriendList[player.PlayerID]
|
||||
if applyExist || friendExist {
|
||||
logger.Error("friend or apply already exist, uid: %v", player.PlayerID)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendApplyList[player.PlayerID] = true
|
||||
USER_MANAGER.SaveTempOfflineUser(targetPlayer)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
_, applyExist := targetPlayer.FriendApplyList[player.PlayerID]
|
||||
_, friendExist := targetPlayer.FriendList[player.PlayerID]
|
||||
if applyExist || friendExist {
|
||||
@@ -253,43 +311,26 @@ func (g *GameManager) AskAddFriendReq(player *model.Player, payloadMsg pb.Messag
|
||||
}
|
||||
targetPlayer.FriendApplyList[player.PlayerID] = true
|
||||
|
||||
if targetPlayerOnline {
|
||||
askAddFriendNotify := &proto.AskAddFriendNotify{
|
||||
TargetUid: player.PlayerID,
|
||||
}
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
Level: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: player.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: player.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
// 目标玩家在线则通知
|
||||
askAddFriendNotify := &proto.AskAddFriendNotify{
|
||||
TargetUid: player.PlayerID,
|
||||
}
|
||||
|
||||
askAddFriendRsp := &proto.AskAddFriendRsp{
|
||||
TargetUid: targetUid,
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
Level: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: player.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: player.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendRsp, player.PlayerID, player.ClientSeq, askAddFriendRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) AddFriend(player *model.Player, targetUid uint32) {
|
||||
player.FriendList[targetUid] = true
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("agree friend apply target player is nil, uid: %v", player.PlayerID)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
g.SendMsg(cmd.AskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) DealAddFriendReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -298,8 +339,12 @@ func (g *GameManager) DealAddFriendReq(player *model.Player, payloadMsg pb.Messa
|
||||
targetUid := req.TargetUid
|
||||
result := req.DealAddFriendResult
|
||||
|
||||
agree := false
|
||||
if result == proto.DealAddFriendResultType_DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT {
|
||||
g.AddFriend(player, targetUid)
|
||||
agree = true
|
||||
}
|
||||
if agree {
|
||||
player.FriendList[targetUid] = true
|
||||
}
|
||||
delete(player.FriendApplyList, targetUid)
|
||||
|
||||
@@ -308,6 +353,44 @@ func (g *GameManager) DealAddFriendReq(player *model.Player, payloadMsg pb.Messa
|
||||
DealAddFriendResult: result,
|
||||
}
|
||||
g.SendMsg(cmd.DealAddFriendRsp, player.PlayerID, player.ClientSeq, dealAddFriendRsp)
|
||||
|
||||
if agree {
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
// 非本地玩家
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 远程在线玩家
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerAddFriendNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
AddFriendInfo: &mq.AddFriendInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "DealAddFriendReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
TargetUserId: targetUid,
|
||||
ApplyPlayerOnlineInfo: &mq.UserBaseInfo{
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// 全服离线玩家
|
||||
targetPlayer, _, _ := USER_MANAGER.LoadGlobalPlayer(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("apply add friend target player is nil, uid: %v", targetUid)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
USER_MANAGER.SaveTempOfflineUser(targetPlayer)
|
||||
}
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) GetOnlinePlayerListReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -315,6 +398,7 @@ func (g *GameManager) GetOnlinePlayerListReq(player *model.Player, payloadMsg pb
|
||||
|
||||
count := 0
|
||||
onlinePlayerList := make([]*model.Player, 0)
|
||||
// 优先获取本地的在线玩家
|
||||
for _, onlinePlayer := range USER_MANAGER.GetAllOnlineUserList() {
|
||||
if onlinePlayer.PlayerID == player.PlayerID {
|
||||
continue
|
||||
@@ -325,6 +409,19 @@ func (g *GameManager) GetOnlinePlayerListReq(player *model.Player, payloadMsg pb
|
||||
break
|
||||
}
|
||||
}
|
||||
if count < 50 {
|
||||
// 本地不够时获取远程的在线玩家
|
||||
for _, onlinePlayer := range USER_MANAGER.GetRemoteOnlineUserList(50 - count) {
|
||||
if onlinePlayer.PlayerID == player.PlayerID {
|
||||
continue
|
||||
}
|
||||
onlinePlayerList = append(onlinePlayerList, onlinePlayer)
|
||||
count++
|
||||
if count >= 50 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getOnlinePlayerListRsp := &proto.GetOnlinePlayerListRsp{
|
||||
PlayerInfoList: make([]*proto.OnlinePlayerInfo, 0),
|
||||
@@ -344,11 +441,6 @@ func (g *GameManager) GetOnlinePlayerInfoReq(player *model.Player, payloadMsg pb
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 删除我
|
||||
g.JoinPlayerSceneReq(player, &proto.JoinPlayerSceneReq{
|
||||
TargetUid: targetUid.TargetUid,
|
||||
})
|
||||
|
||||
if USER_MANAGER.GetUserOnlineState(targetUid.TargetUid) {
|
||||
g.SendMsg(cmd.GetOnlinePlayerInfoRsp, player.PlayerID, player.ClientSeq, &proto.GetOnlinePlayerInfoRsp{
|
||||
TargetUid: targetUid.TargetUid,
|
||||
@@ -358,9 +450,9 @@ func (g *GameManager) GetOnlinePlayerInfoReq(player *model.Player, payloadMsg pb
|
||||
}
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid.TargetUid) {
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid.TargetUid)
|
||||
g.messageQueue.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerGetUserBaseInfoReq,
|
||||
EventId: mq.ServerUserBaseInfoReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
@@ -378,6 +470,11 @@ func (g *GameManager) GetOnlinePlayerInfoReq(player *model.Player, payloadMsg pb
|
||||
|
||||
func (g *GameManager) PacketOnlinePlayerInfo(player *model.Player) *proto.OnlinePlayerInfo {
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
worldPlayerNum := uint32(1)
|
||||
// TODO 远程玩家的世界内人数
|
||||
if world != nil {
|
||||
worldPlayerNum = uint32(world.GetWorldPlayerNum())
|
||||
}
|
||||
onlinePlayerInfo := &proto.OnlinePlayerInfo{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
@@ -386,7 +483,138 @@ func (g *GameManager) PacketOnlinePlayerInfo(player *model.Player) *proto.Online
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
CurPlayerNumInWorld: uint32(world.GetWorldPlayerNum()),
|
||||
CurPlayerNumInWorld: worldPlayerNum,
|
||||
}
|
||||
return onlinePlayerInfo
|
||||
}
|
||||
|
||||
// 跨服玩家基础数据请求
|
||||
|
||||
func (g *GameManager) ServerUserBaseInfoReq(userBaseInfo *mq.UserBaseInfo, gsAppId string) {
|
||||
switch userBaseInfo.OriginInfo.CmdName {
|
||||
case "GetOnlinePlayerInfoReq":
|
||||
fallthrough
|
||||
case "GetPlayerSocialDetailReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.UserId)
|
||||
return
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserBaseInfoRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: userBaseInfo.OriginInfo,
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: uint8(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldPlayerNum: uint32(world.GetWorldPlayerNum()),
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Birthday: player.Birthday,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerUserBaseInfoRsp(userBaseInfo *mq.UserBaseInfo) {
|
||||
switch userBaseInfo.OriginInfo.CmdName {
|
||||
case "GetOnlinePlayerInfoReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
g.SendMsg(cmd.GetOnlinePlayerInfoRsp, player.PlayerID, player.ClientSeq, &proto.GetOnlinePlayerInfoRsp{
|
||||
TargetUid: userBaseInfo.UserId,
|
||||
TargetPlayerInfo: &proto.OnlinePlayerInfo{
|
||||
Uid: userBaseInfo.UserId,
|
||||
Nickname: userBaseInfo.Nickname,
|
||||
PlayerLevel: userBaseInfo.PlayerLevel,
|
||||
MpSettingType: proto.MpSettingType(userBaseInfo.MpSettingType),
|
||||
NameCardId: userBaseInfo.NameCardId,
|
||||
Signature: userBaseInfo.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userBaseInfo.HeadImageId},
|
||||
CurPlayerNumInWorld: userBaseInfo.WorldPlayerNum,
|
||||
},
|
||||
})
|
||||
case "GetPlayerSocialDetailReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
_, exist := player.FriendList[userBaseInfo.UserId]
|
||||
socialDetail := &proto.SocialDetail{
|
||||
Uid: userBaseInfo.UserId,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userBaseInfo.HeadImageId},
|
||||
Nickname: userBaseInfo.Nickname,
|
||||
Signature: userBaseInfo.Signature,
|
||||
Level: userBaseInfo.PlayerLevel,
|
||||
Birthday: &proto.Birthday{Month: uint32(userBaseInfo.Birthday[0]), Day: uint32(userBaseInfo.Birthday[1])},
|
||||
WorldLevel: userBaseInfo.WorldLevel,
|
||||
NameCardId: userBaseInfo.NameCardId,
|
||||
IsShowAvatar: false,
|
||||
FinishAchievementNum: 0,
|
||||
IsFriend: exist,
|
||||
}
|
||||
getPlayerSocialDetailRsp := &proto.GetPlayerSocialDetailRsp{
|
||||
DetailData: socialDetail,
|
||||
}
|
||||
g.SendMsg(cmd.GetPlayerSocialDetailRsp, player.PlayerID, player.ClientSeq, getPlayerSocialDetailRsp)
|
||||
}
|
||||
}
|
||||
|
||||
// 跨服添加好友通知
|
||||
|
||||
func (g *GameManager) ServerAddFriendNotify(addFriendInfo *mq.AddFriendInfo) {
|
||||
switch addFriendInfo.OriginInfo.CmdName {
|
||||
case "AskAddFriendReq":
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(addFriendInfo.TargetUserId)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", addFriendInfo.TargetUserId)
|
||||
return
|
||||
}
|
||||
_, applyExist := targetPlayer.FriendApplyList[addFriendInfo.ApplyPlayerOnlineInfo.UserId]
|
||||
_, friendExist := targetPlayer.FriendList[addFriendInfo.ApplyPlayerOnlineInfo.UserId]
|
||||
if applyExist || friendExist {
|
||||
logger.Error("friend or apply already exist, uid: %v", addFriendInfo.ApplyPlayerOnlineInfo.UserId)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendApplyList[addFriendInfo.ApplyPlayerOnlineInfo.UserId] = true
|
||||
|
||||
// 目标玩家在线则通知
|
||||
askAddFriendNotify := &proto.AskAddFriendNotify{
|
||||
TargetUid: addFriendInfo.ApplyPlayerOnlineInfo.UserId,
|
||||
}
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: addFriendInfo.ApplyPlayerOnlineInfo.UserId,
|
||||
Nickname: addFriendInfo.ApplyPlayerOnlineInfo.Nickname,
|
||||
Level: addFriendInfo.ApplyPlayerOnlineInfo.PlayerLevel,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: addFriendInfo.ApplyPlayerOnlineInfo.HeadImageId},
|
||||
WorldLevel: addFriendInfo.ApplyPlayerOnlineInfo.WorldLevel,
|
||||
Signature: addFriendInfo.ApplyPlayerOnlineInfo.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: 0,
|
||||
NameCardId: addFriendInfo.ApplyPlayerOnlineInfo.NameCardId,
|
||||
Param: 0,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
case "DealAddFriendReq":
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(addFriendInfo.TargetUserId)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", addFriendInfo.TargetUserId)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[addFriendInfo.ApplyPlayerOnlineInfo.UserId] = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +206,10 @@ func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeam
|
||||
empty := new(proto.AbilitySyncStateInfo)
|
||||
for _, worldAvatar := range world.GetWorldAvatarList() {
|
||||
worldPlayer := USER_MANAGER.GetOnlineUser(worldAvatar.uid)
|
||||
if worldPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", worldAvatar.uid)
|
||||
continue
|
||||
}
|
||||
worldPlayerScene := world.GetSceneById(worldPlayer.SceneId)
|
||||
worldPlayerAvatar := worldPlayer.AvatarMap[worldAvatar.avatarId]
|
||||
equipIdList := make([]uint32, 0)
|
||||
|
||||
@@ -112,7 +112,7 @@ type World struct {
|
||||
chatMsgList []*proto.ChatInfo // 世界聊天消息列表
|
||||
aoiManager *aoi.AoiManager // 当前世界地图的aoi管理器
|
||||
playerFirstEnterMap map[uint32]int64 // 玩家第一次进入世界的时间 key:uid value:进入时间
|
||||
waitEnterPlayerMap map[uint32]int64 // 等待进入世界的列表 key:uid value:开始时间
|
||||
waitEnterPlayerMap map[uint32]int64 // 进入世界的玩家等待列表 key:uid value:开始时间
|
||||
multiplayerTeam *MultiplayerTeam
|
||||
peerList []*model.Player // 玩家编号列表
|
||||
}
|
||||
@@ -701,7 +701,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
|
||||
if avatarId == s.world.GetPlayerActiveAvatarId(player) {
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
}
|
||||
GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.FightRoutineAddEntity,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -751,7 +751,7 @@ func (s *Scene) CreateEntityMonster(pos *model.Vector, level uint8, fightProp ma
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.FightRoutineAddEntity,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -901,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))
|
||||
delete(s.entityMap, entityId)
|
||||
GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.FightRoutineDelEntity,
|
||||
FightMsg: &mq.FightMsg{
|
||||
|
||||
@@ -60,7 +60,6 @@ type LogInfo struct {
|
||||
FuncName string
|
||||
Line int
|
||||
GoroutineId string
|
||||
Stack string
|
||||
}
|
||||
|
||||
func InitLogger(appName string) {
|
||||
@@ -81,32 +80,29 @@ func (l *Logger) doLog() {
|
||||
logInfo := <-l.LogInfoChan
|
||||
timeNow := time.Now()
|
||||
timeNowStr := timeNow.Format("2006-01-02 15:04:05.000")
|
||||
logHeader := CYAN + "[" + timeNowStr + "]" + RESET + " "
|
||||
logStr := CYAN + "[" + timeNowStr + "]" + RESET + " "
|
||||
if logInfo.Level == DEBUG {
|
||||
logHeader += BLUE + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
|
||||
logStr += BLUE + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
||||
} else if logInfo.Level == INFO {
|
||||
logHeader += GREEN + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
|
||||
logStr += GREEN + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
||||
} else if logInfo.Level == WARN {
|
||||
logHeader += YELLOW + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
|
||||
logStr += YELLOW + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
||||
} else if logInfo.Level == ERROR {
|
||||
logHeader += RED + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
|
||||
logStr += RED + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
||||
}
|
||||
if logInfo.Level == ERROR {
|
||||
logStr += " " + RED + fmt.Sprintf(logInfo.Msg, logInfo.Param...) + RESET + " "
|
||||
} else {
|
||||
logStr += " " + fmt.Sprintf(logInfo.Msg, logInfo.Param...) + " "
|
||||
}
|
||||
if l.Track {
|
||||
logHeader += MAGENTA + "[" +
|
||||
logStr += MAGENTA + "[" +
|
||||
logInfo.FileName + ":" + strconv.Itoa(logInfo.Line) + " " +
|
||||
logInfo.FuncName + "()" + " " +
|
||||
"goroutine:" + logInfo.GoroutineId +
|
||||
"]" + RESET + " "
|
||||
}
|
||||
logStr := logHeader
|
||||
if logInfo.Level == ERROR {
|
||||
logStr += RED + fmt.Sprintf(logInfo.Msg, logInfo.Param...) + RESET + "\n"
|
||||
} else {
|
||||
logStr += fmt.Sprintf(logInfo.Msg, logInfo.Param...) + "\n"
|
||||
}
|
||||
if logInfo.Stack != "" {
|
||||
logStr += logInfo.Stack
|
||||
"]" + RESET
|
||||
}
|
||||
logStr += "\n"
|
||||
if l.Mode == CONSOLE {
|
||||
log.Print(logStr)
|
||||
} else if l.Mode == FILE {
|
||||
@@ -222,22 +218,6 @@ func Error(msg string, param ...any) {
|
||||
LOG.LogInfoChan <- logInfo
|
||||
}
|
||||
|
||||
func ErrorStack(msg string, param ...any) {
|
||||
if LOG.Level > ERROR {
|
||||
return
|
||||
}
|
||||
logInfo := new(LogInfo)
|
||||
logInfo.Level = ERROR
|
||||
logInfo.Msg = msg
|
||||
logInfo.Param = param
|
||||
if LOG.Track {
|
||||
logInfo.FileName, logInfo.Line, logInfo.FuncName = LOG.getLineFunc()
|
||||
logInfo.GoroutineId = LOG.getGoroutineId()
|
||||
logInfo.Stack = Stack()
|
||||
}
|
||||
LOG.LogInfoChan <- logInfo
|
||||
}
|
||||
|
||||
func (l *Logger) getLevelInt(level string) (ret int) {
|
||||
switch level {
|
||||
case "DEBUG":
|
||||
|
||||
Reference in New Issue
Block a user