diff --git a/common/id.go b/common/id.go new file mode 100644 index 0000000..2673f16 --- /dev/null +++ b/common/id.go @@ -0,0 +1,9 @@ +package common + +import "github.com/bwmarrin/snowflake" + +var IdNode, _ = snowflake.NewNode(int64(GetSelfSrvId())) + +func GetId() int64 { + return IdNode.Generate().Int64() +} diff --git a/dbproxy/main.go b/dbproxy/main.go index 8db7452..4ca7989 100644 --- a/dbproxy/main.go +++ b/dbproxy/main.go @@ -12,7 +12,7 @@ import ( _ "mongo.games.com/game" "mongo.games.com/game/common" - _ "mongo.games.com/game/dbproxy/mq" + dbmq "mongo.games.com/game/dbproxy/mq" "mongo.games.com/game/dbproxy/svc" "mongo.games.com/game/model" "mongo.games.com/game/mq" @@ -20,6 +20,7 @@ import ( ) func main() { + dbmq.Init() // 自定义配置文件 model.InitGameParam() // package模块 diff --git a/dbproxy/mq/c_apilog.go b/dbproxy/mq/c_apilog.go index 95450de..b213a7c 100644 --- a/dbproxy/mq/c_apilog.go +++ b/dbproxy/mq/c_apilog.go @@ -12,7 +12,7 @@ import ( ) func init() { - mq.RegisterSubscriber(model.APILogCollName, func(e broker.Event) (err error) { + mq.RegisterSubscriber(mq.MgrAPILog, func(e broker.Event) (err error) { msg := e.Message() if msg != nil { defer func() { @@ -32,5 +32,5 @@ func init() { return } return nil - }, broker.Queue(model.APILogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue()) + }, broker.Queue(mq.MgrAPILog), broker.DisableAutoAck(), rabbitmq.DurableQueue()) } diff --git a/dbproxy/mq/c_coinlog.go b/dbproxy/mq/c_coinlog.go index 0b77dde..80375d6 100644 --- a/dbproxy/mq/c_coinlog.go +++ b/dbproxy/mq/c_coinlog.go @@ -26,7 +26,7 @@ func init() { } if log.Count == 0 { //玩家冲账探针 - mq.Send(model.TopicProbeCoinLogAck, log) + mq.Send(mq.WorldLogCoinAck, log) } else { c := svc.CoinLogsCollection(log.Platform) if c != nil { diff --git a/dbproxy/mq/c_customlog.go b/dbproxy/mq/c_customlog.go index 60af0ba..897d1d5 100644 --- a/dbproxy/mq/c_customlog.go +++ b/dbproxy/mq/c_customlog.go @@ -1,11 +1,6 @@ package mq import ( - "encoding/json" - - "mongo.games.com/goserver/core/broker" - "mongo.games.com/goserver/core/broker/rabbitmq" - "mongo.games.com/game/dbproxy/svc" "mongo.games.com/game/model" "mongo.games.com/game/mq" @@ -13,48 +8,39 @@ import ( func init() { // 竞技馆对局记录 - mq.RegisterSubscriber(mq.DBCustomLog, func(e broker.Event) (err error) { - msg := e.Message() - if msg != nil { - defer func() { - e.Ack() - }() - - var log model.CustomLog - err = json.Unmarshal(msg.Body, &log) - if err != nil { - return + mq.RegisterHandler(&mq.RegisterHandlerParam{ + Name: mq.DBCustomLog, + Data: model.CustomLog{}, + Handler: func(data interface{}) (err error) { + log, ok := data.(*model.CustomLog) + if !ok { + return nil } - c := svc.DbCustomLogCollection(log.Platform) if c != nil { err = c.Insert(log) } - return - } - return nil - }, broker.Queue(mq.DBCustomLog), broker.DisableAutoAck(), rabbitmq.DurableQueue()) + return nil + }, + }) // 竞技馆奖励记录 - mq.RegisterSubscriber(mq.DBCustomLogAward, func(e broker.Event) (err error) { - msg := e.Message() - if msg != nil { - defer func() { - e.Ack() - }() - - var log model.CustomLogAward - err = json.Unmarshal(msg.Body, &log) - if err != nil { - return + mq.RegisterHandler(&mq.RegisterHandlerParam{ + Name: mq.DBCustomLogAward, + Data: model.CustomLogAward{}, + Handler: func(data interface{}) (err error) { + log, ok := data.(*model.CustomLogAward) + if !ok { + return nil } - c := svc.DbCustomLogAwardCollection(log.Platform) if c != nil { err = c.Insert(log) + if err == nil { + mq.Write(log) // 通知ranksrv广播获奖消息 + } } return - } - return nil - }, broker.Queue(mq.DBCustomLogAward), broker.DisableAutoAck(), rabbitmq.DurableQueue()) + }, + }) } diff --git a/dbproxy/mq/c_invite.go b/dbproxy/mq/c_invite.go index 5f91352..b1ff619 100644 --- a/dbproxy/mq/c_invite.go +++ b/dbproxy/mq/c_invite.go @@ -20,7 +20,7 @@ import ( ) func init() { - mq.RegisterSubscriber(model.EvtInvite, func(e broker.Event) (err error) { + mq.RegisterSubscriber(mq.DBInvite, func(e broker.Event) (err error) { msg := e.Message() if msg != nil { defer func() { @@ -80,7 +80,7 @@ func init() { return err } msg.Score = 0 - mq.Send(model.EvtInviteAck, msg) + mq.Send(mq.WorldInviteAck, msg) } return nil } @@ -301,10 +301,10 @@ func init() { logger.Logger.Errorf("EvtInvite add find error:%v psnid:%v score:%v rate:%v", err, v, log.Score, log.Rate) return err } - mq.Send(model.EvtInviteAck, msg) + mq.Send(mq.WorldInviteAck, msg) } } return nil - }, broker.Queue(model.EvtInvite), broker.DisableAutoAck(), rabbitmq.DurableQueue()) + }, broker.Queue(mq.DBInvite), broker.DisableAutoAck(), rabbitmq.DurableQueue()) } diff --git a/dbproxy/mq/init.go b/dbproxy/mq/init.go new file mode 100644 index 0000000..1e80f01 --- /dev/null +++ b/dbproxy/mq/init.go @@ -0,0 +1,19 @@ +package mq + +import ( + "mongo.games.com/game/model" + "mongo.games.com/game/mq" +) + +func Init() { + InitHandler() + // 竞技馆获奖通知 + mq.RegisterMessage(&mq.RegisterMessageParam{ + Name: mq.RankCustomLogAward, + Data: model.CustomLogAward{}, + }) +} + +func InitHandler() { + +} diff --git a/dbproxy/svc/l_customaward.go b/dbproxy/svc/l_customaward.go index 77c1f2d..4fac893 100644 --- a/dbproxy/svc/l_customaward.go +++ b/dbproxy/svc/l_customaward.go @@ -39,7 +39,7 @@ func (this *DBCustomLogAwardSvc) Find(req *model.CustomLogAwardFindReq, res *mod return ErrCustomLogAwardNotFound } - if err := c.Find(bson.M{"startts": bson.M{"$gte": req.StartTs, "$lte": req.EndTs}}).Sort("startts").All(&res.List); err != nil { + if err := c.Find(bson.M{"startts": bson.M{"$gte": req.StartTs, "$lte": req.EndTs}}).Sort("-endts").Limit(50).All(&res.List); err != nil { return err } return nil diff --git a/dbproxy/svc/l_itemlog.go b/dbproxy/svc/l_itemlog.go index 35f295c..521675a 100644 --- a/dbproxy/svc/l_itemlog.go +++ b/dbproxy/svc/l_itemlog.go @@ -117,6 +117,7 @@ func (svc *ItemLogSvc) UpdateState(req *model.UpdateParam, res *model.UpdateRes) func (svc *ItemLogSvc) GetClawdollItemLog(args *model.ClawdollItemLogReq, ret *model.GetClawdollItemLogRet) (err error) { + limitDataNum := 200 var Logs []model.RetClawdollItemLog for _, typeId := range args.TypeIds { var SubLogs []model.RetClawdollItemLog @@ -137,7 +138,7 @@ func (svc *ItemLogSvc) GetClawdollItemLog(args *model.ClawdollItemLogReq, ret *m return } - err = c.Find(bson.M{"$and": sql}).Select(bson.M{"itemid": 1, "createts": 1, "typeid": 1, "count": 1, "logtype": 1}).All(&SubLogs) + err = c.Find(bson.M{"$and": sql}).Sort("-createts").Limit(limitDataNum).Select(bson.M{"itemid": 1, "createts": 1, "typeid": 1, "count": 1, "logtype": 1}).All(&SubLogs) Logs = append(Logs, SubLogs...) } @@ -155,8 +156,9 @@ func (svc *ItemLogSvc) GetClawdollSuccessItemLog(args *model.ClawdollSuccessItem return } + limitDataNum := 300 var datas []model.ItemLog - err = c.Find(cond).All(&datas) + err = c.Find(cond).Sort("-createts").Limit(limitDataNum).All(&datas) if err != nil { logger.Logger.Error("GetClawdollSuccessItemLog error: ", err) return err diff --git a/dbproxy/svc/l_matchawardlog.go b/dbproxy/svc/l_matchawardlog.go index bbc8dfd..d482031 100644 --- a/dbproxy/svc/l_matchawardlog.go +++ b/dbproxy/svc/l_matchawardlog.go @@ -75,8 +75,9 @@ func (svc *MatchAwardSvc) GetMatchAward(plt string, ret *model.MatchAward) (err err = c.Find(nil).One(ret) if err != nil && err != mgo.ErrNotFound { logger.Logger.Errorf("GetMatchAward err:%v", err) + return err } - return err + return nil } func init() { diff --git a/gamesrv/clawdoll/action_clawdoll.go b/gamesrv/clawdoll/action_clawdoll.go index 75837bb..3da5a08 100644 --- a/gamesrv/clawdoll/action_clawdoll.go +++ b/gamesrv/clawdoll/action_clawdoll.go @@ -109,6 +109,7 @@ func MSDollMachineoCoinResultHandler(session *netlib.Session, packetId int, data case 2: if msg.Result == 1 { // 获得娃娃卡 + playerEx.CatchCardClawdoll() playerEx.IsWin = true logger.Logger.Tracef("下抓成功!!!!!!!!!!!!snid = %v", msg.Snid) @@ -118,8 +119,6 @@ func MSDollMachineoCoinResultHandler(session *netlib.Session, packetId int, data playerEx.IsWin = false } - playerEx.CatchCardClawdoll() - logger.Logger.Tracef("ClawDoll StatePlayGame OnPlayerOp Grab response, SnId= %v", msg.Snid) s.ChangeSceneState(rule.ClawDollSceneStateBilled) diff --git a/mgrsrv/api/logchannel.go b/mgrsrv/api/logchannel.go index a694462..e461788 100644 --- a/mgrsrv/api/logchannel.go +++ b/mgrsrv/api/logchannel.go @@ -53,5 +53,5 @@ func (c *LogChannel) WriteMQData(data *model.RabbitMQData) { } func init() { - LogChannelSington.RegisteLogCName(model.APILogCollName, &model.APILog{}) + LogChannelSington.RegisteLogCName(mq.MgrAPILog, &model.APILog{}) } diff --git a/model/baginfo.go b/model/baginfo.go index 0c80863..a32f549 100644 --- a/model/baginfo.go +++ b/model/baginfo.go @@ -8,6 +8,12 @@ import ( "mongo.games.com/goserver/core/logger" ) +type Item struct { + ItemId int32 // 物品ID + ItemNum int64 // 物品数量 + ObtainTime int64 //获取的时间 +} + type BagInfo struct { BagId bson.ObjectId `bson:"_id"` SnId int32 //玩家账号直接在这里生成 @@ -19,20 +25,11 @@ type BagInfo struct { GainWay int32 `bson:"-"` } -type Item struct { - ItemId int32 // 物品ID - ItemNum int64 // 物品数量 - ObtainTime int64 //获取的时间 -} type GetBagInfoArgs struct { Plt string SnId int32 } -func NewBagInfo(sid int32, plt string) *BagInfo { - return &BagInfo{BagId: bson.NewObjectId(), SnId: sid, Platform: plt, BagItem: make(map[int32]*Item)} -} - func GetBagInfo(sid int32, plt string) (*BagInfo, error) { if rpcCli == nil { return nil, ErrRPClientNoConn @@ -76,18 +73,6 @@ func SaveDBBagItem(args *BagInfo) error { return nil } -func SaveToDelBackupBagItem(args *BagInfo) error { - if rpcCli == nil { - return ErrRPClientNoConn - } - ret := false - err := rpcCli.CallWithTimeout("BagSvc.UpdateBag", args, &ret, time.Second*30) - if err != nil { - return err - } - return nil -} - type AddItemParam struct { Platform string SnId int32 diff --git a/model/coinlog.go b/model/coinlog.go index 84d0be3..fcba59a 100644 --- a/model/coinlog.go +++ b/model/coinlog.go @@ -12,9 +12,8 @@ import ( ) var ( - CoinLogDBName = "log" - CoinLogCollName = "log_coinex" - TopicProbeCoinLogAck = "ack_logcoin" + CoinLogDBName = "log" + CoinLogCollName = "log_coinex" ) var COINEX_GLOBAL_SEQ = int64(0) diff --git a/model/invitecode.go b/model/invitecode.go index 381ba49..b702d88 100644 --- a/model/invitecode.go +++ b/model/invitecode.go @@ -64,7 +64,6 @@ type EvtInviteMsg struct { RechargeScore int64 // 充值成功积分 } -const EvtInviteAck = "evt_invite_ack" // 绑定邀请人 dbproxy -> worldsrv type EvtInviteAckMsg struct { Platform string Snid int32 diff --git a/mq/keyconf.go b/mq/keyconf.go index 23bf85a..536733f 100644 --- a/mq/keyconf.go +++ b/mq/keyconf.go @@ -19,10 +19,30 @@ const ( BackSystemJyb = "back_jyblog" ) +// mgrsrv + +const ( + MgrAPILog = "mgr_apilog" +) + +// worldsrv 消息 + +const ( + WorldLogCoinAck = "world_logcoin_ack" + WorldInviteAck = "world_invite_ack" +) + // dbproxy 消息 const ( - DBVipGiftLog = "db_vipgift" - DBCustomLog = "db_customlog" // 房卡场对局记录 + DBVipGiftLog = "db_vipgift" + DBCustomLog = "db_customlog" // 房卡场对局记录 DBCustomLogAward = "db_customlog_award" // 房卡场对局奖励 + DBInvite = "db_invite" +) + +// ranksrv 消息 + +const ( + RankCustomLogAward = "rank_customlog_award" // 房卡场对局奖励 ) diff --git a/mq/messagemgr.go b/mq/messagemgr.go new file mode 100644 index 0000000..9ca1d55 --- /dev/null +++ b/mq/messagemgr.go @@ -0,0 +1,141 @@ +package mq + +import ( + "encoding/json" + "fmt" + "reflect" + + "mongo.games.com/goserver/core/broker" + "mongo.games.com/goserver/core/broker/rabbitmq" + "mongo.games.com/goserver/core/logger" +) + +type HandlerFunc func(data interface{}) (err error) + +type HandlerData struct { + T reflect.Type + F HandlerFunc +} + +type MessageMgr struct { + name map[reflect.Type]string + handler map[string]HandlerData +} + +type RegisterMessageParam struct { + Name string + Data interface{} +} + +// RegisterMessage 注册消息 +func (c *MessageMgr) RegisterMessage(param *RegisterMessageParam) { + if param == nil { + return + } + t := c.getType(param.Data) + c.name[t] = param.Name +} + +func (c *MessageMgr) getType(data interface{}) reflect.Type { + return reflect.Indirect(reflect.ValueOf(data)).Type() +} + +func (c *MessageMgr) getName(data interface{}) string { + t := c.getType(data) + if name, exist := c.name[t]; exist { + return name + } + return "" +} + +// Write 记录消息,需要提前注册 +func (c *MessageMgr) Write(data interface{}) { + name := c.getName(data) + if name == "" { + name = "_null_" + } + logger.Logger.Tracef("==> RabbitMQ(%v): %#v", name, data) + Send(name, data) +} + +// WriteMQData rabbitMQ消息 +func (c *MessageMgr) WriteMQData(name string, data interface{}) { + logger.Logger.Tracef("==> RabbitMQ(%v): %#v", name, data) + Send(name, data) +} + +type RegisterHandlerParam struct { + Name string + Data interface{} + Handler HandlerFunc +} + +// RegisterHandler 注册消息处理函数 +func (c *MessageMgr) RegisterHandler(param *RegisterHandlerParam) { + if param == nil { + return + } + if _, ok := c.handler[param.Name]; ok { + panic(fmt.Sprintf("RabbitMQ RegisterHandler repeatet name:%v", param.Name)) + return + } + if param.Data == nil { + return + } + if param.Handler == nil { + return + } + c.handler[param.Name] = HandlerData{ + T: c.getType(param.Data), + F: param.Handler, + } + + RegisterSubscriber(param.Name, func(e broker.Event) (err error) { + msg := e.Message() + if msg != nil { + defer func() { + e.Ack() + }() + + log := reflect.New(c.handler[param.Name].T).Interface() + err = json.Unmarshal(msg.Body, log) + if err != nil { + logger.Logger.Errorf("RabbitMQ Unmarshal error: %v", err) + return + } + logger.Logger.Tracef("==> Receive RabbitMQ(%v): %#v", param.Name, log) + + return c.handler[param.Name].F(log) + } + return nil + }, broker.Queue(param.Name), broker.DisableAutoAck(), rabbitmq.DurableQueue()) +} + +// MessageMgrSingle 消息发送器 +var MessageMgrSingle = &MessageMgr{ + name: make(map[reflect.Type]string), + handler: make(map[string]HandlerData), +} + +// RegisterMessage 注册消息 +// name: 消息名称 +// data: 消息结构体指针 +func RegisterMessage(param *RegisterMessageParam) { + MessageMgrSingle.RegisterMessage(param) +} + +// Write 发送消息 +// 默认队列名称规则:队列前缀_消息结构体名称 +func Write(data interface{}) { + MessageMgrSingle.Write(data) +} + +// WriteMQData 发送消息 +func WriteMQData(name string, data interface{}) { + MessageMgrSingle.WriteMQData(name, data) +} + +// RegisterHandler 注册消息处理函数 +func RegisterHandler(param *RegisterHandlerParam) { + MessageMgrSingle.RegisterHandler(param) +} diff --git a/ranksrv/com/listmgr.go b/ranksrv/com/listmgr.go index 14d818e..218cfe3 100644 --- a/ranksrv/com/listmgr.go +++ b/ranksrv/com/listmgr.go @@ -92,6 +92,7 @@ func (r *ListMgr[T]) Take(platform string, index int32, f func([]T, error)) { } // UpdateCache 更新缓存 +// 重新获取数据 func (r *ListMgr[T]) UpdateCache(platform string, index int32) { tp := r.platform[platform] if tp == nil { diff --git a/ranksrv/com/logchannel.go b/ranksrv/com/logchannel.go deleted file mode 100644 index eb7fa5a..0000000 --- a/ranksrv/com/logchannel.go +++ /dev/null @@ -1,53 +0,0 @@ -package com - -import ( - "reflect" - - "mongo.games.com/goserver/core/logger" - - "mongo.games.com/game/model" - "mongo.games.com/game/mq" -) - -// LogChannelSingleton 日志记录器 -var LogChannelSingleton = &LogChannel{ - cName: make(map[reflect.Type]string), -} - -type LogChannel struct { - cName map[reflect.Type]string -} - -func (c *LogChannel) RegisterLogCName(cname string, log interface{}) { - t := c.getLogType(log) - c.cName[t] = cname -} - -func (c *LogChannel) getLogType(log interface{}) reflect.Type { - return reflect.Indirect(reflect.ValueOf(log)).Type() -} - -func (c *LogChannel) getLogCName(log interface{}) string { - t := c.getLogType(log) - if name, exist := c.cName[t]; exist { - return name - } - return "" -} - -func (c *LogChannel) WriteLog(log interface{}) { - cname := c.getLogCName(log) - if cname == "" { - cname = "_null_" - } - logger.Logger.Tracef("LogChannel ==> %#v", log) - mq.Send(cname, log) -} - -func (c *LogChannel) WriteMQData(data *model.RabbitMQData) { - mq.Send(data.MQName, data.Data) -} - -func init() { - LogChannelSingleton.RegisterLogCName(mq.DBCustomLogAward, &model.CustomLogAward{}) -} diff --git a/ranksrv/main.go b/ranksrv/main.go index 97140c0..68264ec 100644 --- a/ranksrv/main.go +++ b/ranksrv/main.go @@ -11,9 +11,11 @@ import ( "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/mq" + rankmq "mongo.games.com/game/ranksrv/mq" ) func main() { + rankmq.Init() // 自定义配置文件 model.InitGameParam() // package模块 diff --git a/ranksrv/mq/init.go b/ranksrv/mq/init.go new file mode 100644 index 0000000..223a7cd --- /dev/null +++ b/ranksrv/mq/init.go @@ -0,0 +1,55 @@ +package mq + +import ( + "mongo.games.com/goserver/core/logger" + "mongo.games.com/goserver/srvlib" + "mongo.games.com/goserver/srvlib/action" + + "mongo.games.com/game/common" + "mongo.games.com/game/model" + "mongo.games.com/game/mq" + rankproto "mongo.games.com/game/protocol/rank" + "mongo.games.com/game/ranksrv/rank" +) + +// Init 初始化 +func Init() { + InitHandler() + // 注册消息 + mq.RegisterMessage(&mq.RegisterMessageParam{ + Name: mq.DBCustomLogAward, + Data: model.CustomLogAward{}, + }) +} + +// InitHandler 注册消息处理方法 +func InitHandler() { + mq.RegisterHandler(&mq.RegisterHandlerParam{ + Name: mq.RankCustomLogAward, + Data: model.CustomLogAward{}, + Handler: func(data interface{}) (err error) { + log, ok := data.(*model.CustomLogAward) + if !ok { + return nil + } + rank.CustomAwardMgrInstance.UpdateCache(log.Platform, 0) + + var awards []*rankproto.Item + for _, v := range log.Awards { + awards = append(awards, &rankproto.Item{ + Id: v.ItemId, + N: v.ItemNum, + }) + } + pack := &rankproto.UserAward{ + Snid: log.SnId, + Name: log.Name, + Awards: awards, + Ts: log.EndTs, + } + action.BroadcastMessage(common.GetSelfAreaId(), srvlib.GateServerType, int(rankproto.Rank_PACKET_SCRoomAwardOne), pack, nil) + logger.Logger.Tracef("SCRoomAwardOne %v", pack) + return + }, + }) +} diff --git a/ranksrv/rank/customaward.go b/ranksrv/rank/customaward.go index fdafc74..94cd619 100644 --- a/ranksrv/rank/customaward.go +++ b/ranksrv/rank/customaward.go @@ -7,11 +7,10 @@ import ( "github.com/jinzhu/now" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/module" - "mongo.games.com/goserver/srvlib" - "mongo.games.com/goserver/srvlib/action" "mongo.games.com/game/common" "mongo.games.com/game/model" + "mongo.games.com/game/mq" "mongo.games.com/game/protocol/rank" "mongo.games.com/game/ranksrv/com" "mongo.games.com/game/srvdata" @@ -75,7 +74,7 @@ func (c *CustomAwardMgr) Update() { name = srvdata.PBDB_NameMgr.Datas.GetArr()[n].Name } id := common.RandInt(20000000, 99999999) - com.LogChannelSingleton.WriteLog(&model.CustomLogAward{ + mq.Write(&model.CustomLogAward{ Platform: k, CycleId: "", SnId: int32(id), @@ -84,15 +83,6 @@ func (c *CustomAwardMgr) Update() { StartTs: nowTime.Add(-time.Minute * 8).Unix(), EndTs: nowTime.Unix(), }) - // 通知获奖 - pack := &rank.UserAward{ - Snid: int32(id), - Name: name, - Awards: items, - Ts: nowTime.Unix(), - } - action.BroadcastMessage(common.GetSelfAreaId(), srvlib.GateServerType, int(rank.Rank_PACKET_SCRoomAwardOne), pack, nil) - logger.Logger.Tracef("BroadcastMessage UserAward: %v", pack) break } } diff --git a/ranksrv/rank/wincoin.go b/ranksrv/rank/wincoin.go index 66d5c6f..e38bc48 100644 --- a/ranksrv/rank/wincoin.go +++ b/ranksrv/rank/wincoin.go @@ -61,6 +61,7 @@ func (w *WinCoinMgr) Update() { } func (w *WinCoinMgr) Shutdown() { + module.UnregisteModule(w) } func init() { diff --git a/worldsrv/action_bag.go b/worldsrv/action_bag.go index 66a00a0..f5d68c7 100644 --- a/worldsrv/action_bag.go +++ b/worldsrv/action_bag.go @@ -626,14 +626,13 @@ func CSDollChange(s *netlib.Session, packetid int, data interface{}, sid int64) }) logger.Logger.Trace("背包内使用兑换娃娃卡 bagInfo = ", bagInfo) pack.RetCode = rest + if isF { + itemId := item.ItemId task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - dollLog := model.NewDbBagChangeDoll(p.Platform, p.SnId, item.ItemId, 1, 0, "", msg.Addr, msg.UserName, msg.UserTel) + dollLog := model.NewDbBagChangeDoll(p.Platform, p.SnId, itemId, 1, 0, "", msg.Addr, msg.UserName, msg.UserTel) return model.InsertDbBagChangeDollLog(dollLog) }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { - if data != nil { - logger.Logger.Errorf("CSDollChange err: %v", data) - } }), "CSDollChange").Start() } diff --git a/worldsrv/action_login.go b/worldsrv/action_login.go index c66ccc9..296cbd6 100644 --- a/worldsrv/action_login.go +++ b/worldsrv/action_login.go @@ -216,7 +216,7 @@ func (this *CSLoginHandler) Process(s *netlib.Session, packetid int, data interf if player != nil { waitMatch, _ = TournamentMgr.IsMatchWaiting(player.Platform, player.SnId) } - if len(lss) > 0 && (player != nil && (player.scene != nil || player.thrscene != 0 || waitMatch || TournamentMgr.IsMatching(player.SnId))) { + if len(lss) > 0 && (player != nil && (player.scene != nil || player.thrscene != 0 || waitMatch || TournamentMgr.IsGaming(player.SnId))) { sendSCLogin(login_proto.OpResultCode_OPRC_LoginOtherPlace) sendSCDisconnect(common.KickReason_Logining) return nil diff --git a/worldsrv/action_tournament.go b/worldsrv/action_tournament.go index 64d889a..eb5286f 100644 --- a/worldsrv/action_tournament.go +++ b/worldsrv/action_tournament.go @@ -82,8 +82,8 @@ func CSSignRace(s *netlib.Session, packetid int, data interface{}, sid int64) er } default: // 取消报名 - if TournamentMgr.IsMatching(p.SnId) { - logger.Logger.Warnf("player(%v) IsMatching.", p.SnId) + if TournamentMgr.IsGaming(p.SnId) { + logger.Logger.Warnf("player(%v) IsGaming.", p.SnId) } else { //取消报名 TournamentMgr.CancelSignUp(platform, tmId, p.SnId) @@ -115,7 +115,7 @@ func CSMatchList(s *netlib.Session, packetId int, data interface{}, sid int64) e // 开始时间排序 sort.Slice(list, func(i, j int) bool { - return list[i].StartTime < list[j].StartTime + return list[i].StartTime.Compare(list[j].StartTime) == -1 }) for _, v := range list { diff --git a/worldsrv/bagmgr.go b/worldsrv/bagmgr.go index 01a13e0..637d0fb 100644 --- a/worldsrv/bagmgr.go +++ b/worldsrv/bagmgr.go @@ -10,7 +10,6 @@ import ( "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/i18n" "mongo.games.com/goserver/core/logger" - "mongo.games.com/goserver/core/module" "mongo.games.com/goserver/core/task" "mongo.games.com/game/common" @@ -24,10 +23,22 @@ import ( "mongo.games.com/game/worldsrv/internal" ) -func init() { - module.RegisteModule(BagMgrSingleton, time.Second, 0) - internal.RegisterPlayerLoad(BagMgrSingleton) +const ( + BagItemMax int32 = 200 +) +// 道具功能 Function +const ( + ItemCanUse = iota //可以使用 + ItemCanGive //可以赠送 + ItemCanSell //可以出售 + ItemCanExchange //可以兑换 + ItemCanFen //可以分解 + ItemMax +) + +func init() { + internal.RegisterPlayerLoad(BagMgrSingleton) BagMgrSingleton.AddOnChangeFuncs(func(param *model.ChangeItemParam) { p := PlayerMgrSington.GetPlayerBySnId(param.SnId) if p == nil { @@ -138,20 +149,6 @@ func init() { }) } -const ( - BagItemMax int32 = 200 -) - -// 道具功能 Function -const ( - ItemCanUse = iota //可以使用 - ItemCanGive //可以赠送 - ItemCanSell //可以出售 - ItemCanExchange //可以兑换 - ItemCanFen //可以分解 - ItemMax -) - type Item struct { ItemId int32 // 物品ID ItemNum int64 // 物品数量 @@ -186,11 +183,7 @@ func NewBagInfo(platform string, snid int32) *BagInfo { } } -// BagMgrSingleton 背包管理器 -var BagMgrSingleton = &BagMgr{ - PlayerBag: make(map[int32]*BagInfo), -} - +// BagMgr 玩家背包 type BagMgr struct { PlayerBag map[int32]*BagInfo // snid:背包 @@ -198,20 +191,241 @@ type BagMgr struct { onChangeFuncs []func(param *model.ChangeItemParam) } -func (this *BagMgr) ModuleName() string { - return "BagMgr" +// BagMgrSingleton 背包管理器 +var BagMgrSingleton = &BagMgr{ + PlayerBag: make(map[int32]*BagInfo), } -func (this *BagMgr) Init() { +// ============================================================================ +// implement IPlayerLoad +//============================================================================= + +type LoadData struct { + BagInfo *model.BagInfo } -func (this *BagMgr) Update() { +func (this *BagMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay { + // 加载道具 + bagInfo, err := model.GetBagInfo(snid, platform) + if err != nil { + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: err, + Data: nil, + } + } + + // 对账时间戳初始化 + if bagInfo.Ts == 0 { + bagInfo.Ts = time.Now().UnixNano() + } + + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: err, + Data: &LoadData{ + BagInfo: bagInfo, + }, + } } -func (this *BagMgr) Shutdown() { - module.UnregisteModule(this) +func (this *BagMgr) Callback(player any, ret *internal.PlayerLoadReplay) { + if ret == nil || ret.Data == nil { + return + } + + data, ok := ret.Data.(*LoadData) + if !ok || data == nil || data.BagInfo == nil { + return + } + + // 背包数据 + newBagInfo := NewBagInfo(ret.Platform, ret.Snid) + newBagInfo.Ts = data.BagInfo.Ts + for k, bi := range data.BagInfo.BagItem { + item := srvdata.GameItemMgr.Get(ret.Platform, bi.ItemId) + if item != nil { + if bi.ItemNum > 0 { + newBagInfo.BagItem[k] = &Item{ + ItemId: bi.ItemId, + ItemNum: bi.ItemNum, + ObtainTime: bi.ObtainTime, + } + } + } else { + logger.Logger.Error("InitBagInfo err: item is nil. ItemId:", bi.ItemId) + } + } + this.PlayerBag[ret.Snid] = newBagInfo } +type LoadAfterData struct { + GameID []int32 + ItemLogs []*model.ItemLog + StarTs, EndTs int64 +} + +func (this *BagMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay { + var err error + // 查询最近游戏 + gameID := model.GetRecentGame(platform, snid) + + // 道具变更记录 + endTs := time.Now().UnixNano() + var itemLogs []*model.ItemLog + itemLogs, err = model.GetItemLog(platform, snid, this.PlayerBag[snid].Ts) + if err != nil { + logger.Logger.Errorf("LoadAfter GetItemLog err: %v", err) + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: err, + Data: nil, + } + } + + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: nil, + Data: &LoadAfterData{ + GameID: gameID, + ItemLogs: itemLogs, + StarTs: this.PlayerBag[snid].Ts, + EndTs: endTs, + }, + } +} + +func (this *BagMgr) CallbackAfter(ret *internal.PlayerLoadReplay) { + if ret == nil { + return + } + if ret.Err != nil { + logger.Logger.Error("BagMgr LoadAfter err:", ret.Err) + return + } + + param, ok := ret.Data.(*LoadAfterData) + if !ok { + logger.Logger.Errorf("BagMgr LoadAfter BUGE 1") + return + } + + p := PlayerMgrSington.GetPlayerBySnId(ret.Snid) + if p == nil { + logger.Logger.Errorf("BagMgr LoadAfter BUGE 2") + return + } + + // 最近游戏 + p.GameID = param.GameID + + // 道具变更记录 + bagInfo := this.PlayerBag[p.SnId] + if bagInfo != nil { + changeItems := make(map[int32]struct{}) + for _, v := range param.ItemLogs { + if v == nil { + continue + } + if v.Ts > param.StarTs && v.Ts <= param.EndTs { + bagInfo.dirty = true + num := v.Count + if v.LogType == 1 { + num = -num + } + if v.Ts > bagInfo.Ts { + bagInfo.Ts = v.Ts + } + if v.Offline == 0 { + // 在线数据恢复 + logger.Logger.Tracef("道具恢复 SnId:%v Item:%+v", p.SnId, *v) + if _, ok := bagInfo.BagItem[v.ItemId]; !ok { + bagInfo.BagItem[v.ItemId] = &Item{ + ItemId: v.ItemId, + ItemNum: 0, + ObtainTime: v.CreateTs, + } + } + bagInfo.BagItem[v.ItemId].ItemNum += num + changeItems[v.ItemId] = struct{}{} + } else { + // 离线时的变更 + logger.Logger.Tracef("处理离线道具变化 SnId:%v Item:%v", p.SnId, *v) + this.OnChangeFuncs(&model.ChangeItemParam{ + SnId: p.SnId, + ItemId: v.ItemId, + ItemNum: num, + GainWay: v.TypeId, + RoomConfigId: v.RoomConfigId, + GameId: v.GameId, + GameFreeId: v.GameFreeId, + Cost: v.Cost, + }) + } + } + } + + this.SyncBagData(p.SnId, maps.Keys(changeItems)...) + } +} + +func (this *BagMgr) Save(platform string, snid int32, isSync, force bool) { + bagInfo := this.GetBagInfo(snid) + if bagInfo == nil { + return + } + if !bagInfo.dirty && !force { + return + } + logger.Logger.Tracef("SaveBagData: %+v", *bagInfo) + + var err error + f := func() { + newBagInfo := &model.BagInfo{ + SnId: bagInfo.SnId, + Platform: bagInfo.Platform, + Ts: bagInfo.Ts, + BagItem: make(map[int32]*model.Item), + } + for _, v := range bagInfo.BagItem { + newBagInfo.BagItem[v.ItemId] = &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum, ObtainTime: v.ObtainTime} + } + err = model.UpBagItem(newBagInfo) + } + + cf := func() { + if err == nil && this.PlayerBag[snid] != nil { + this.PlayerBag[snid].dirty = false + } + } + + if isSync { + f() + cf() + return + } + + task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { + f() + return nil + }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { + cf() + })).StartByExecutor(fmt.Sprintf("Player%v", snid)) +} + +func (this *BagMgr) Release(platform string, snid int32) { + delete(this.PlayerBag, snid) +} + +// =========================================================================== +// other functions +//============================================================================ + +// AddOnChangeFuncs 添加道具变更监听 func (this *BagMgr) AddOnChangeFuncs(f ...func(param *model.ChangeItemParam)) { this.onChangeFuncs = append(this.onChangeFuncs, f...) } @@ -706,7 +920,7 @@ func (this *BagMgr) VerifyUpJybInfo(p *Player, args *model.VerifyUpJybInfoArgs) }), "VerifyUpJybInfo").Start() } -// 兑换话费卡 +// ItemExchangeCard 兑换话费卡 func (this *BagMgr) ItemExchangeCard(p *Player, itemId int32, money, cardType int32, logId string) bool { // 兑换码奖品 var err error @@ -799,226 +1013,3 @@ func (this *BagMgr) ItemExchangeCard(p *Player, itemId int32, money, cardType in }), fmt.Sprintf("ItemExChange%d", p.SnId)).Start() return true } - -// ========================implement IPlayerLoad ============================== - -type LoadData struct { - BagInfo *model.BagInfo -} - -func (this *BagMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay { - // 加载道具 - bagInfo, err := model.GetBagInfo(snid, platform) - if err != nil { - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: nil, - } - } - - // 对账时间戳初始化 - if bagInfo.Ts == 0 { - bagInfo.Ts = time.Now().UnixNano() - } - - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: &LoadData{ - BagInfo: bagInfo, - }, - } -} - -func (this *BagMgr) Callback(player any, ret *internal.PlayerLoadReplay) { - if ret == nil || ret.Data == nil { - return - } - - data, ok := ret.Data.(*LoadData) - if !ok || data == nil || data.BagInfo == nil { - return - } - - // 背包数据 - newBagInfo := NewBagInfo(ret.Platform, ret.Snid) - newBagInfo.Ts = data.BagInfo.Ts - for k, bi := range data.BagInfo.BagItem { - item := srvdata.GameItemMgr.Get(ret.Platform, bi.ItemId) - if item != nil { - if bi.ItemNum > 0 { - newBagInfo.BagItem[k] = &Item{ - ItemId: bi.ItemId, - ItemNum: bi.ItemNum, - ObtainTime: bi.ObtainTime, - } - } - } else { - logger.Logger.Error("InitBagInfo err: item is nil. ItemId:", bi.ItemId) - } - } - this.PlayerBag[ret.Snid] = newBagInfo -} - -type LoadAfterData struct { - GameID []int32 - ItemLogs []*model.ItemLog - StarTs, EndTs int64 -} - -func (this *BagMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay { - var err error - // 查询最近游戏 - gameID := model.GetRecentGame(platform, snid) - - // 道具变更记录 - endTs := time.Now().UnixNano() - var itemLogs []*model.ItemLog - itemLogs, err = model.GetItemLog(platform, snid, this.PlayerBag[snid].Ts) - if err != nil { - logger.Logger.Errorf("LoadAfter GetItemLog err: %v", err) - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: nil, - } - } - - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: nil, - Data: &LoadAfterData{ - GameID: gameID, - ItemLogs: itemLogs, - StarTs: this.PlayerBag[snid].Ts, - EndTs: endTs, - }, - } -} - -func (this *BagMgr) CallbackAfter(ret *internal.PlayerLoadReplay) { - if ret == nil { - return - } - if ret.Err != nil { - logger.Logger.Error("BagMgr LoadAfter err:", ret.Err) - return - } - - param, ok := ret.Data.(*LoadAfterData) - if !ok { - logger.Logger.Errorf("BagMgr LoadAfter BUGE 1") - return - } - - p := PlayerMgrSington.GetPlayerBySnId(ret.Snid) - if p == nil { - logger.Logger.Errorf("BagMgr LoadAfter BUGE 2") - return - } - - // 最近游戏 - p.GameID = param.GameID - - // 道具变更记录 - bagInfo := this.PlayerBag[p.SnId] - if bagInfo != nil { - changeItems := make(map[int32]struct{}) - for _, v := range param.ItemLogs { - if v == nil { - continue - } - if v.Ts > param.StarTs && v.Ts <= param.EndTs { - bagInfo.dirty = true - num := v.Count - if v.LogType == 1 { - num = -num - } - if v.Ts > bagInfo.Ts { - bagInfo.Ts = v.Ts - } - if v.Offline == 0 { - // 在线数据恢复 - logger.Logger.Tracef("道具恢复 SnId:%v Item:%+v", p.SnId, *v) - if _, ok := bagInfo.BagItem[v.ItemId]; !ok { - bagInfo.BagItem[v.ItemId] = &Item{ - ItemId: v.ItemId, - ItemNum: 0, - ObtainTime: v.CreateTs, - } - } - bagInfo.BagItem[v.ItemId].ItemNum += num - changeItems[v.ItemId] = struct{}{} - } else { - // 离线时的变更 - logger.Logger.Tracef("处理离线道具变化 SnId:%v Item:%v", p.SnId, *v) - this.OnChangeFuncs(&model.ChangeItemParam{ - SnId: p.SnId, - ItemId: v.ItemId, - ItemNum: num, - GainWay: v.TypeId, - RoomConfigId: v.RoomConfigId, - GameId: v.GameId, - GameFreeId: v.GameFreeId, - Cost: v.Cost, - }) - } - } - } - - this.SyncBagData(p.SnId, maps.Keys(changeItems)...) - } -} - -func (this *BagMgr) Save(platform string, snid int32, isSync, force bool) { - bagInfo := this.GetBagInfo(snid) - if bagInfo == nil { - return - } - if !bagInfo.dirty && !force { - return - } - logger.Logger.Tracef("SaveBagData: %+v", *bagInfo) - - var err error - f := func() { - newBagInfo := &model.BagInfo{ - SnId: bagInfo.SnId, - Platform: bagInfo.Platform, - Ts: bagInfo.Ts, - BagItem: make(map[int32]*model.Item), - } - for _, v := range bagInfo.BagItem { - newBagInfo.BagItem[v.ItemId] = &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum, ObtainTime: v.ObtainTime} - } - err = model.UpBagItem(newBagInfo) - } - - cf := func() { - if err == nil && this.PlayerBag[snid] != nil { - this.PlayerBag[snid].dirty = false - } - } - - if isSync { - f() - cf() - return - } - - task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - f() - return nil - }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { - cf() - })).StartByExecutor(fmt.Sprintf("Player%v", snid)) -} - -func (this *BagMgr) Release(platform string, snid int32) { - delete(this.PlayerBag, snid) -} diff --git a/worldsrv/logchannel.go b/worldsrv/logchannel.go index 44b69ce..cc44a15 100644 --- a/worldsrv/logchannel.go +++ b/worldsrv/logchannel.go @@ -61,7 +61,7 @@ func init() { LogChannelSingleton.RegisterLogCName(model.MQRankPlayerCoin, &model.RankPlayerCoin{}) LogChannelSingleton.RegisterLogCName(mq.BackBankrupt, &model.BankruptLog{}) LogChannelSingleton.RegisterLogCName(mq.BackReliefund, &model.ReliefFundLog{}) - LogChannelSingleton.RegisterLogCName(model.EvtInvite, &model.EvtInviteMsg{}) + LogChannelSingleton.RegisterLogCName(mq.DBInvite, &model.EvtInviteMsg{}) LogChannelSingleton.RegisterLogCName(model.MQRankPlayerLevel, &model.PlayerLevelInfo{}) LogChannelSingleton.RegisterLogCName(model.MQRankPlayerPermit, &model.PermitScore{}) LogChannelSingleton.RegisterLogCName(mq.BackSystemPermitCycle, &model.BackendPermitCycle{}) diff --git a/worldsrv/matchscenemgr.go b/worldsrv/matchscenemgr.go index 83aacdc..29bb005 100644 --- a/worldsrv/matchscenemgr.go +++ b/worldsrv/matchscenemgr.go @@ -1,12 +1,14 @@ package main import ( - "mongo.games.com/game/srvdata" + "time" + "mongo.games.com/goserver/core/logger" "mongo.games.com/game/common" "mongo.games.com/game/proto" "mongo.games.com/game/protocol/server" + "mongo.games.com/game/srvdata" ) var MatchSceneMgrSingleton = &MatchSceneMgr{} @@ -119,6 +121,7 @@ func (ms *MatchSceneMgr) MatchStart(tm *TmMatch) { // NewRoundStart 开始非首轮比赛 func (ms *MatchSceneMgr) NewRoundStart(tm *TmMatch, mct []*PlayerMatchContext, finals bool, round int32) { + tm.RoundTime = time.Now() var scene *Scene csp := CoinSceneMgrSingleton.GetCoinScenePool(tm.Platform, tm.dbGameFree.GetId()) if csp == nil { diff --git a/worldsrv/mq_coinlog.go b/worldsrv/mq_coinlog.go index 01b9ec0..d5528d2 100644 --- a/worldsrv/mq_coinlog.go +++ b/worldsrv/mq_coinlog.go @@ -15,7 +15,7 @@ import ( ) func init() { - mq.RegisterSubscriber(model.TopicProbeCoinLogAck, func(e broker.Event) (err error) { + mq.RegisterSubscriber(mq.WorldLogCoinAck, func(e broker.Event) (err error) { msg := e.Message() if msg != nil { defer func() { @@ -40,10 +40,10 @@ func init() { return } return nil - }, broker.Queue(model.TopicProbeCoinLogAck), rabbitmq.DurableQueue()) + }, broker.Queue(mq.WorldLogCoinAck), rabbitmq.DurableQueue()) // 邀请数据同步 - mq.RegisterSubscriber(model.EvtInviteAck, func(e broker.Event) error { + mq.RegisterSubscriber(mq.WorldInviteAck, func(e broker.Event) error { msg := e.Message() if msg != nil { defer func() { @@ -86,5 +86,5 @@ func init() { }), true) } return nil - }, broker.Queue(model.EvtInviteAck), rabbitmq.DurableQueue()) + }, broker.Queue(mq.WorldInviteAck), rabbitmq.DurableQueue()) } diff --git a/worldsrv/scene.go b/worldsrv/scene.go index 06327ea..0907ad8 100644 --- a/worldsrv/scene.go +++ b/worldsrv/scene.go @@ -899,7 +899,7 @@ func (this *Scene) TryForceDeleteMatchInfo() { if players, exist := TournamentMgr.players[this.MatchSortId]; exist { for _, player := range this.players { if player != nil && !player.IsRob { - if TournamentMgr.IsMatching(player.SnId) { + if TournamentMgr.IsGaming(player.SnId) { delete(players, player.SnId) } } diff --git a/worldsrv/tmmatch.go b/worldsrv/tmmatch.go index ec50184..3cfae1e 100644 --- a/worldsrv/tmmatch.go +++ b/worldsrv/tmmatch.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "math" "math/rand" "sort" @@ -21,7 +22,7 @@ import ( ) func getSortId() int64 { - return time.Now().UnixMilli() + return common.GetId() } type TmPlayer struct { @@ -49,10 +50,17 @@ type TmMatch struct { robotGrades map[int][]*TmGradeInfo // 第几轮:玩家积分 copyRobotGrades []*TmGradeInfo // 最近一轮的机器人积分备份 useRobot int32 // 是否使用机器人 - StartTime int64 // 本场比赛开始时间 + StartTime time.Time // 本场比赛开始时间 + RoundTime time.Time // 本轮开始时间 +} + +func (tm *TmMatch) String() string { + return fmt.Sprintf("比赛配置id: %v 比赛id:%v 开启机器人:%v 比赛开始时间: %v 本轮开始时间:%v 比赛玩家: %v", + tm.TMId, tm.SortId, tm.useRobot, tm.StartTime, tm.RoundTime, tm.TmPlayer) } func NewTmMatch(platform string, match *webapi_proto.GameMatchDate, players map[int32]*TmPlayer) *TmMatch { + now := time.Now() ret := &TmMatch{ SortId: getSortId(), TMId: match.Id, @@ -63,7 +71,8 @@ func NewTmMatch(platform string, match *webapi_proto.GameMatchDate, players map[ dbGameFree: srvdata.PBDB_GameFreeMgr.GetData(match.GameFreeId), robotGrades: make(map[int][]*TmGradeInfo), useRobot: match.UseRobot, - StartTime: time.Now().Unix(), + StartTime: now, + RoundTime: now, } ret.copyPlayers(players) diff --git a/worldsrv/tournament.go b/worldsrv/tournament.go index 4fd672f..a51bf06 100644 --- a/worldsrv/tournament.go +++ b/worldsrv/tournament.go @@ -84,16 +84,18 @@ type PlayerRoundInfo struct { type Tournament struct { common.BaseClockSinker - TypeList map[string]*webapiproto.GameMatchType // 比赛类型列表 平台id:比赛类型列表 - GameMatchDateList map[string]map[int32]*webapiproto.GameMatchDate // 比赛配置,platform:比赛场配置id:比赛配置 - singleSignupPlayers map[int32]*SignupInfo // 开启机器人时,报名的玩家,玩家Id:报名信息 - signupPlayers map[string]map[int32]*SignInfo // 报名的玩家 platform:比赛配置id:报名人 - playerWaitStart map[int32]int64 // 等待时间 玩家Id:等待时长秒 - matches map[int32]map[int64]*TmMatch // 开始比赛的数据,比赛配置Id:比赛顺序序号:一场开始的比赛数据 - players map[int64]map[int32]*PlayerMatchContext // 比赛中玩家 比赛顺序序号:玩家id:玩家信息 - roundPlayers map[int64]map[int32]*PlayerRoundInfo // 每轮比赛数据备份 比赛顺序序号:第几轮 - finalPerRank map[int64][]*PerRankInfo // 本场比赛排名,每淘汰一位记录一位,最后记录决赛玩家 比赛顺序序号 - MatchAwardNum map[string]map[int32]int32 // 比赛配置Id:比赛奖励次數 + TypeList map[string]*webapiproto.GameMatchType // 平台id:比赛类型列表 + GameMatchDateList map[string]map[int32]*webapiproto.GameMatchDate // 平台id:比赛场配置id:比赛配置 + + singleSignupPlayers map[int32]*SignupInfo // 玩家Id:报名信息; 使用机器人时的报名信息 + signupPlayers map[string]map[int32]*SignInfo // 平台id:比赛配置id:报名信息; 不使用机器人时的报名信息 + MatchAwardNum map[string]map[int32]int32 // 平台id:比赛配置Id:发第一名奖励次数 + + playerWaitStart map[int32]int64 // 玩家Id:等待时长秒; 玩家报名后等待比赛开始 + matches map[int32]map[int64]*TmMatch // 比赛配置Id:比赛顺序序号:开始的比赛数据 + players map[int64]map[int32]*PlayerMatchContext // 比赛顺序序号:玩家id:玩家信息 + roundPlayers map[int64]map[int32]*PlayerRoundInfo // 比赛顺序序号:第几轮:结算记录 + finalPerRank map[int64][]*PerRankInfo // 比赛顺序序号:本场比赛排名,每淘汰一位记录一位,最后记录决赛玩家 } func NewTournament() *Tournament { @@ -111,6 +113,61 @@ func NewTournament() *Tournament { return ret } +func (this *Tournament) ModuleName() string { + return "Tournament" +} + +func (this *Tournament) Init() { + logger.Logger.Trace("Tournament Init") + for _, v := range PlatformMgrSingleton.GetPlatforms() { + if v == nil || v.IdStr == "0" { + continue + } + ret, err := model.GetMatchAward(v.IdStr) + if err != nil { + logger.Logger.Warnf("GetMatchAward error %v", err) + continue + } + if this.MatchAwardNum == nil { + this.MatchAwardNum = make(map[string]map[int32]int32) + } + this.MatchAwardNum[v.IdStr] = ret.Award + } +} + +func (this *Tournament) Update() { + // 使用机器人的情况 + for snId, info := range this.singleSignupPlayers { + if info == nil || info.Ts <= 0 { + continue + } + matchInfo := this.GetMatchInfo(info.Platform, info.TmId, 0) + if this.IsMatchOn(matchInfo) && !this.IsOutTime(matchInfo) && this.IsRobotOn(matchInfo) { + needTime := this.playerWaitStart[snId] + if time.Now().Unix()-info.Ts > needTime { + signInfo := &SignInfo{ + signup: make(map[int32]*TmPlayer), + Platform: info.Platform, + MaxCnt: int(matchInfo.MatchNumebr), + } + seq := rand.Intn(int(matchInfo.MatchNumebr)) + 1 + signInfo.signup[snId] = &TmPlayer{SnId: snId, seq: seq} + this.signupPlayers[info.Platform][info.TmId] = signInfo + + //倒计时结束 开始比赛 + this.Start(info.Platform, info.TmId) + } + } else { + this.CancelSignUpAll(info.Platform, info.TmId) + } + } +} + +func (this *Tournament) Shutdown() { + this.SaveMatchAward() + module.UnregisteModule(this) +} + // 检查下数据是否合法(主要检查报名人数和晋级方式) n n|...|4|1 func (this *Tournament) checkData(cfg *webapiproto.GameMatchDate) bool { if cfg == nil { @@ -486,8 +543,8 @@ func (this *Tournament) GetAllMatchInfo(platform string) map[int32]*webapiproto. return nil } -// IsMatching 判断是否在比赛中 -func (this *Tournament) IsMatching(snId int32) bool { +// IsGaming 判断是否在比赛中 +func (this *Tournament) IsGaming(snId int32) bool { if this.players != nil { for _, v := range this.players { if v != nil { @@ -503,6 +560,7 @@ func (this *Tournament) IsMatching(snId int32) bool { } // IsMatchWaiting 判断是否在匹配中,已报名 +// 返回 是否匹配中,比赛配置id func (this *Tournament) IsMatchWaiting(platform string, snId int32) (bool, int32) { // 未使用机器人 for k, v := range this.signupPlayers[platform] { @@ -666,7 +724,7 @@ func (this *Tournament) SignUp(tmId int32, p *Player) (bool, int32) { } // 已报名 isWaiting, _ := this.IsMatchWaiting(p.Platform, p.SnId) - if this.IsMatching(p.SnId) || isWaiting { + if this.IsGaming(p.SnId) || isWaiting { return false, int32(tournament.SignRaceCode_OPRC_Repeat) } if this.GetMatchAwardNum(p.Platform, tmId) <= 0 { @@ -783,27 +841,41 @@ func (this *Tournament) CancelSignUpAll(platform string, tmId int32) { func (this *Tournament) Quit(platform string, snid int32) { logger.Logger.Tracef("TournamentMgr.Quit: snId:%d", snid) isWaiting, tmid := this.IsMatchWaiting(platform, snid) - if isWaiting && !this.IsMatching(snid) { + if isWaiting && !this.IsGaming(snid) { this.CancelSignUp(platform, tmid, snid) } } -// ForceQuit 强制退赛 +// ForceQuit 强制退赛,异常时才使用 func (this *Tournament) ForceQuit(platform string, snId int32) { logger.Logger.Tracef("TournamentMgr.ForceQuit: snId:%d", snId) + if snId <= 0 { + return + } this.Quit(platform, snId) - var info *PlayerMatchContext - var ok bool - for _, v := range this.players { - info, ok = v[snId] - if ok { - break + p := PlayerMgrSington.GetPlayerBySnId(snId) + if p != nil { + if p.matchCtx != nil && p.matchCtx.tm != nil { + this.StopMatch(p.matchCtx.tm.TMId, p.matchCtx.tm.SortId) + return } } - if info != nil && info.tm != nil { - this.StopMatch(info.tm.TMId, info.tm.SortId) - MatchSceneMgrSingleton.MatchStop(info.tm) + + for _, v := range this.matches { + for _, vv := range v { + if vv != nil && vv.TmPlayer[snId] != nil { + this.StopMatch(vv.TMId, vv.SortId) + return + } + } + } + + for _, v := range this.players { + if info, ok := v[snId]; ok && info != nil && info.tm != nil { + this.StopMatch(info.tm.TMId, info.tm.SortId) + return + } } } @@ -861,6 +933,7 @@ func (this *Tournament) Start(platform string, tmId int32) { // 开始比赛,清除报名数据 for _, v := range signInfo.signup { delete(this.singleSignupPlayers, v.SnId) + delete(this.playerWaitStart, v.SnId) TaskSubjectSingleton.Touch(common.TaskTypeJoinMatch, &TaskData{ SnId: v.SnId, GameID: int(tm.dbGameFree.GetGameId()), @@ -880,9 +953,10 @@ func (this *Tournament) Start(platform string, tmId int32) { // StopMatch 比赛结束 func (this *Tournament) StopMatch(tmId int32, sortId int64) { logger.Logger.Tracef("StopMatch:%v, %v", tmId, sortId) + var tm *TmMatch //房间清理 if this.matches[tmId] != nil && this.matches[tmId][sortId] != nil { - tm := this.matches[tmId][sortId] + tm = this.matches[tmId][sortId] matchLog := this.MakeMatchLog(tm.Platform, tmId, sortId) this.saveMatchLog(matchLog) tm.Stop() @@ -1030,6 +1104,25 @@ func (this *Tournament) GetRank(sortId int64, snid int32) int32 { } } +func (this *Tournament) CanStopMatch(matchId int32, sortId int64) (isOver bool) { + if this.players[sortId] != nil { + hasReal := false + for snId, context := range this.players[sortId] { + if !context.p.IsRob && !this.isOut(sortId, snId) { // 有真人没有淘汰 + hasReal = true + break + } + } + //没有真人比赛解散 + if !hasReal { + isOver = true + logger.Logger.Tracef("没有真人比赛解散 matchId:%v sortId:%v", matchId, sortId) + this.StopMatch(matchId, sortId) + } + } + return +} + // UpdateMatchInfo 玩家比赛结束 更新积分 func (this *Tournament) UpdateMatchInfo(p *Player, sortId int64, grade, isWin int32, matchRobotGrades map[int32]int32) { logger.Logger.Tracef("UpdateMatchInfo: sortId:%v, grade:%v, isWin: %v, matchRobotGrades:%v", sortId, grade, isWin, matchRobotGrades) @@ -1083,25 +1176,6 @@ func (this *Tournament) UpdateMatchInfo(p *Player, sortId int64, grade, isWin in } } -func (this *Tournament) stopMatch(matchId int32, sortId int64) (isOver bool) { - if this.players[sortId] != nil { - hasReal := false - for snId, context := range this.players[sortId] { - if !context.p.IsRob && !this.isOut(sortId, snId) { // 有真人没有淘汰 - hasReal = true - break - } - } - //没有真人比赛解散 - if !hasReal { - isOver = true - logger.Logger.Trace("没有真人比赛解散") - this.StopMatch(matchId, sortId) - } - } - return -} - // NextRoundStartSingle 下一轮是否开始 // 开启机器人时使用 func (this *Tournament) NextRoundStartSingle(sortId int64, playerCtx *PlayerMatchContext, matchRobotGrades map[int32]int32) { @@ -1283,6 +1357,7 @@ func (this *Tournament) NextRoundStart(sortId int64, playerCtx *PlayerMatchConte willOut = true } else { if !meIn { //自己暂时没晋级 + logger.Logger.Tracef("待定 %+v", info.players) this.sendPromotionInfo(playerCtx, sortId, DaiDing, false, false) //待定 } } @@ -1292,10 +1367,9 @@ func (this *Tournament) NextRoundStart(sortId int64, playerCtx *PlayerMatchConte for _, v := range info.players { logger.Logger.Tracef("淘汰 %+v", *v) this.sendPromotionInfo(v, sortId, TaoTai, true, false) //淘汰 - //真人被淘汰,如果剩下的都是机器人,比赛解散 if !v.p.IsRob { - isOver = this.stopMatch(playerCtx.tm.TMId, sortId) + isOver = this.CanStopMatch(playerCtx.tm.TMId, sortId) } } } @@ -1307,23 +1381,23 @@ func (this *Tournament) NextRoundStart(sortId int64, playerCtx *PlayerMatchConte }), nil, time.Second*7, 1) } } else { - this.sendPromotionInfo(playerCtx, sortId, DaiDing, false, false) //待定 + // 待定 + logger.Logger.Tracef("待定 %+v", info.players) + this.sendPromotionInfo(playerCtx, sortId, DaiDing, false, false) } } else { - if len(info.players) == 4 { - MatchContextSlice(info.players).Sort(true) - for _, mc := range info.players { - outCode := TaoTai - if mc.rank == 1 { - outCode = JinJi - } - this.sendPromotionInfo(mc, sortId, outCode, true, true) //晋级 + MatchContextSlice(info.players).Sort(true) + for _, mc := range info.players { + outCode := TaoTai + if mc.rank == 1 { + outCode = JinJi } - logger.Logger.Trace("比赛结束!!! ") - - // 比赛结束 - this.StopMatch(playerCtx.tm.TMId, sortId) + this.sendPromotionInfo(mc, sortId, outCode, true, true) //晋级 } + logger.Logger.Trace("比赛结束!!! ") + + // 比赛结束 + this.StopMatch(playerCtx.tm.TMId, sortId) } } @@ -1442,7 +1516,7 @@ func (this *Tournament) sendPromotionInfo(mc *PlayerMatchContext, sortId int64, delete(this.players[sortId], mc.p.SnId) //真人被淘汰,如果剩下的都是机器人,比赛解散 if !mc.p.IsRob { - this.stopMatch(mc.tm.TMId, sortId) + this.CanStopMatch(mc.tm.TMId, sortId) } } } @@ -1877,7 +1951,7 @@ func (this *Tournament) MakeMatchLog(platform string, tmId int32, sortId int64) matchLog.MatchName = gameMatchDate.MatchName matchLog.Platform = platform matchLog.GameFreeId = gameMatchDate.GameFreeId - matchLog.StartTime = time.Unix(this.matches[tmId][sortId].StartTime, 0) + matchLog.StartTime = this.matches[tmId][sortId].StartTime matchLog.EndTime = time.Now() matchLog.SortId = sortId return matchLog @@ -1898,84 +1972,6 @@ func (this *Tournament) saveMatchLog(matchLog *model.MatchLog) { })).StartByFixExecutor("saveMatchLogTask") } -func (this *Tournament) ModuleName() string { - return "Tournament" -} - -func (this *Tournament) Init() { - logger.Logger.Trace("Tournament Init") - for _, v := range PlatformMgrSingleton.GetPlatforms() { - if v == nil || v.IdStr == "0" { - continue - } - ret, err := model.GetMatchAward(v.IdStr) - if err != nil { - logger.Logger.Warnf("GetMatchAward error %v", err) - continue - } - if this.MatchAwardNum == nil { - this.MatchAwardNum = make(map[string]map[int32]int32) - } - this.MatchAwardNum[v.IdStr] = ret.Award - } -} - -func (this *Tournament) Update() { - // 使用机器人的情况 - for snId, info := range this.singleSignupPlayers { - if info == nil || info.Ts <= 0 { - continue - } - matchInfo := this.GetMatchInfo(info.Platform, info.TmId, 0) - if this.IsMatchOn(matchInfo) && !this.IsOutTime(matchInfo) && this.IsRobotOn(matchInfo) { - needTime := this.playerWaitStart[snId] - if time.Now().Unix()-info.Ts > needTime { - signInfo := &SignInfo{ - signup: make(map[int32]*TmPlayer), - Platform: info.Platform, - MaxCnt: int(matchInfo.MatchNumebr), - } - seq := rand.Intn(int(matchInfo.MatchNumebr)) + 1 - signInfo.signup[snId] = &TmPlayer{SnId: snId, seq: seq} - this.signupPlayers[info.Platform][info.TmId] = signInfo - - //倒计时结束 开始比赛 - this.Start(info.Platform, info.TmId) - } - } else { - this.CancelSignUpAll(info.Platform, info.TmId) - } - } - - // 防止内存泄露 - now := time.Now().Unix() - for _, v := range this.matches { - for _, vv := range v { - if vv != nil && now-vv.StartTime > int64(time.Hour.Seconds()*5) { - for _, p := range vv.TmPlayer { - this.ForceQuit(vv.Platform, p.SnId) - break - } - } - } - } -} - -func (this *Tournament) OnDayTimer() { - for k := range this.MatchAwardNum { - this.MatchAwardNum[k] = make(map[int32]int32) - } - task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - this.SaveMatchAward() - return nil - }), nil, "save_match_award_times").Start() -} - -func (this *Tournament) Shutdown() { - this.SaveMatchAward() - module.UnregisteModule(this) -} - func (this *Tournament) SaveMatchAward() { if this.MatchAwardNum == nil { return @@ -2047,11 +2043,44 @@ func (this *Tournament) FixMatchTimeStamp(d *webapiproto.GameMatchDate) { } func (this *Tournament) OnHourTimer() { + now := time.Now() for _, v := range this.GameMatchDateList { for _, vv := range v { this.FixMatchTimeStamp(vv) } } + // 防止异常情况卡房间 + for _, v := range this.matches { + for _, vv := range v { + if vv != nil && (now.Sub(vv.RoundTime).Hours() >= 1 || now.Sub(vv.StartTime).Hours() > 5) { + logger.Logger.Errorf("比赛异常,长时间未结束 %v", vv) + this.StopMatch(vv.TMId, vv.SortId) + } + } + } + for sortId := range this.players { + for _, tm := range this.matches { + if _, ok := tm[sortId]; !ok { + for _, v := range this.players[sortId] { + if v != nil { + logger.Logger.Errorf("比赛异常,比赛已经不存在了 %v", v.tm) + } + break + } + this.StopMatch(0, sortId) + } + } + } +} + +func (this *Tournament) OnDayTimer() { + for k := range this.MatchAwardNum { + this.MatchAwardNum[k] = make(map[int32]int32) + } + task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { + this.SaveMatchAward() + return nil + }), nil, "save_match_award_times").Start() } // GetMatchAwardNum 剩余奖励数量 @@ -2080,6 +2109,7 @@ func (this *Tournament) GetMatchAwardNum(platform string, id int32) int32 { return num } +// GetRound 获取当前轮次 func (this *Tournament) GetRound(sortId int64) int32 { d, ok := this.roundPlayers[sortId] if !ok || d == nil {