diff --git a/src/server/cluster/cluster_func.go b/src/server/cluster/cluster_func.go index 2571144d..5108b1eb 100644 --- a/src/server/cluster/cluster_func.go +++ b/src/server/cluster/cluster_func.go @@ -27,14 +27,14 @@ func HandShake(a *Agent) { log.Debug("HandShake GobMarshal err %v", err) return } - // log.Debug("握手 server id :%d", conf.Server.ServerID) + log.Debug("握手 server id :%d", conf.Server.ServerID) a.WriteMsg(data) } // 握手回调 func HandShakeRecv(a *Agent, m *msg.Msg) error { ServerId := m.From - // log.Debug("收到握手回复 ServerId %v", ServerId) + log.Debug("收到握手回复 ServerId %v", ServerId) a.ServerId = ServerId serverAgent.Store(ServerId, a) @@ -48,19 +48,14 @@ func HandShakeRecv(a *Agent, m *msg.Msg) error { RemoteAddr: m.Extra.(string), }, }) + } else { + syncMsg := &msg.Msg{ + Type: msg.CLUSTER_FRIEND_SYNC, + To: ServerId, + HandleType: msg.HANDLE_MOD_CLUSTER_SYNC, + } + sendGameMsg(syncMsg) } - syncMsg := &msg.Msg{ - Type: msg.CLUSTER_FRIEND_SYNC, - To: ServerId, - } - sendGameMsg(syncMsg) - // fmt.Print("现有区服连接:") - // serverAgent.Range(func(key, value interface{}) bool { - // fmt.Print(key) - // fmt.Print(",") - // return true - // }) - // fmt.Println() return nil } @@ -102,7 +97,7 @@ func connectRemote(RemoteAddr string, ConnType int, ConnLabel string) error { client.NewAgent = newAgent client.ConnType = ConnType client.ConnLabel = ConnLabel - client.ConnectInterval = time.Duration(time.Minute * 5) + client.ConnectInterval = time.Duration(time.Minute * 1) if ConnType == ClusterCenterId { // 中心服断开重连 client.AutoReconnect = true } @@ -113,6 +108,9 @@ func connectRemote(RemoteAddr string, ConnType int, ConnLabel string) error { } func SendServerMsg(m *msg.Msg, serverId int) error { + if m.UniKey == "" { + m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m)) + } if v, ok := serverAgent.Load(serverId); ok { data, err := GoUtil.GobMarshal(m) if err != nil { @@ -126,32 +124,32 @@ func SendServerMsg(m *msg.Msg, serverId int) error { } func CallServerMsg(m *msg.Msg, serverId int) (*msg.Msg, error) { - m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m)) - + if m.UniKey == "" { + m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m)) + } + v, ok := serverAgent.Load(serverId) + // 之后再发送消息 + if !ok { + return nil, fmt.Errorf("server %d not online", serverId) + } // 先注册回调通道,避免发送出去后对方快速返回导致丢失 newChan := make(chan *msg.Msg, 1) registerChanel(m.UniKey, newChan) defer unregisterChanel(m.UniKey) - - // 之后再发送消息 - if v, ok := serverAgent.Load(serverId); ok { - data, err := GoUtil.GobMarshal(m) - if err != nil { - log.Debug("CallServerMsg GobMarshal err %v", err) - return nil, err - } - v.(network.Agent).WriteMsg(data) - } else { - return nil, fmt.Errorf("server %d not online", serverId) + data, err := GoUtil.GobMarshal(m) + if err != nil { + log.Debug("CallServerMsg GobMarshal err %v", err) + return nil, err } - + v.(network.Agent).WriteMsg(data) // 等待返回(直接接收一次) - timeout := time.After(15 * time.Second) + timeout := time.After(5 * time.Second) select { case backm := <-newChan: if backm == nil { return nil, fmt.Errorf("server %d not response", serverId) } + log.Debug("CallServerMsg reply %v", backm) return backm, nil case <-timeout: return nil, fmt.Errorf("timeout waiting for server %d response", serverId) @@ -172,13 +170,7 @@ func SendMsgAll(m *msg.Msg) { func processMsg(a *Agent, m *msg.Msg) error { var err error - // 先处理同步回调 - if m.UniKey != "" { - if chanel, ok := CallbackChan[m.UniKey]; ok { - chanel <- m - return nil - } - } + if fun, ok := FuncMap[m.Type]; ok { err = fun(a, m) } else { diff --git a/src/server/db/Mysql.go b/src/server/db/Mysql.go index 9cb4b880..ea38de75 100644 --- a/src/server/db/Mysql.go +++ b/src/server/db/Mysql.go @@ -16,13 +16,6 @@ import ( "github.com/jmoiron/sqlx" ) -type user struct { - Id int `db:"user_id"` - Sex int `db:"sex"` - UserName string `db:"username"` - Email string `db:"email"` -} - var SqlDb *sqlx.DB var sqlDbMu sync.Mutex @@ -271,6 +264,22 @@ func GetPlayerBaseInfoFromDbByName(name string) *ResPlayerBaseInfo { return &res } +func GetPlayerBan(name string) int64 { + sqlStr := "SELECT ban FROM t_player_baseinfo WHERE user_name = ?" + var ban int64 + if err := SqlDb.Get(&ban, sqlStr, name); err != nil { + log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "PlayerBaseInfo", sqlStr, err) + return 0 + } + return ban +} + +func UpdatePlayerBan(uid int64, ban int64) error { + sqlStr := "UPDATE t_player_baseinfo SET ban = ? WHERE dwUin = ?" + _, err := SqlDb.Exec(sqlStr, ban, uid) + return err +} + func UpdatePlayerBaseInfoName(oldName, newName string) error { sqlStr := "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?" _, err := SqlDb.Exec(sqlStr, newName, oldName) diff --git a/src/server/db/Redis.go b/src/server/db/Redis.go index f8f59896..bc5ab33d 100644 --- a/src/server/db/Redis.go +++ b/src/server/db/Redis.go @@ -164,6 +164,17 @@ func RedisGetKey(key string) (string, error) { return val, nil } +func RedisGetKeyBytes(key string) ([]byte, error) { + if RdbRead == nil { + return nil, nil + } + val, err := RdbRead.Get(ctx, key).Bytes() + if err != nil { + return nil, err + } + return val, nil +} + func RedisDelKey(key string) { if RdbWrite == nil { log.Debug("redis write client is nil") diff --git a/src/server/db/SqlStruct.go b/src/server/db/SqlStruct.go index ecfe8238..4191e033 100644 --- a/src/server/db/SqlStruct.go +++ b/src/server/db/SqlStruct.go @@ -37,7 +37,7 @@ type ResPlayerBaseInfo struct { Guild int32 `db:"guild"` PackUnlockCount int32 `db:"pack_unlock_count"` LastPlayTime int32 `db:"last_play_time"` - EnergyBuyCount int32 `db:"EnergyBuyCount"` + Ban int64 `db:"ban"` UserName string `db:"user_name"` NickName string `db:"nick_name"` LoginTime int32 `db:"login_time"` diff --git a/src/server/game/GameLogic.go b/src/server/game/GameLogic.go index a46b8b02..426a7c9d 100644 --- a/src/server/game/GameLogic.go +++ b/src/server/game/GameLogic.go @@ -83,8 +83,8 @@ type GameLogic struct { MailMgr *MailMgr // 邮件管理器 ChampshipMgr *ChampshipMgr // 锦标赛管理器 VarMgr *VarMgr // 变量管理器 - BanMgr *BanMgr // 封号管理器 StartTime int64 // 服务器启动时间 + MessageMgr *MessageMgr // 消息管理器 } type ServerInfo struct { @@ -192,7 +192,6 @@ func (ad *GameLogic) NewAccountInsertDataToDB() bool { playerInfo.MusicCode = 1 playerInfo.Guild = 1 playerInfo.PackUnlockCount = 5 - playerInfo.EnergyBuyCount = 0 playerInfo.UserName = ad.Db_AccountInfo.UserName playerInfo.LoginTime = (int32)(time.Now().Unix()) playerInfo.LogoutTime = 0 @@ -271,68 +270,6 @@ func (ad *GameLogic) CreateFriendMgr() { ad.FriendMgr.Init() } -func (ad *GameLogic) FriendMgrSend(m *MsgMod.Msg) { - ad.FriendMgr.Send(m) -} - -func (ad *GameLogic) SetUserData(Uid int, Op int, Data interface{}) { - ad.FriendMgr.Send(&MsgMod.Msg{ - From: Uid, - To: Uid, - Type: MsgMod.HANDLE_TYPE_VAR_USER_SET, - SendT: GoUtil.Now(), - Extra: VarOpration{Type: Op, Data: Data}, - }) -} - -func (ad *GameLogic) SetDataSync(Uid int, Op int, Data interface{}) error { - _, err := ad.VarMgr.Call(&MsgMod.Msg{ - From: Uid, - To: Uid, - Type: MsgMod.HANDLE_TYPE_VAR_EXPIRE_SET, - SendT: GoUtil.Now(), - Extra: VarOpration{Type: Op, Data: Data}, - }) - return err -} - -func (ad *GameLogic) SetCatnipPartner(Uid int, GameId int, PartnerUid int, EndT int64) error { - _, err := ad.VarMgr.Call(&MsgMod.Msg{ - From: Uid, - To: Uid, - Type: MsgMod.HANDLE_TYPE_SET_CATNIP_PARTNER, - SendT: GoUtil.Now(), - End: EndT, - Extra: map[string]interface{}{ - "uid": Uid, - "game_id": GameId, - "partner_uid": PartnerUid, - }, - }) - return err -} - -func (ad *GameLogic) GetUserData(Uid int) *VarUserData { - result, err := ad.FriendMgr.Call(&MsgMod.Msg{ - From: Uid, - To: Uid, - Type: MsgMod.HANDLE_TYPE_VAR_USER_GET, - SendT: GoUtil.Now(), - }) - if err != nil { - return &VarUserData{} - } - return result.(*VarUserData) -} - -func (ad *GameLogic) FriendMgrCall(m *MsgMod.Msg) interface{} { - result, err := ad.FriendMgr.Call(m) - if err != nil { - return nil - } - return result -} - // 排行榜管理器 func (ad *GameLogic) CreateRankMgr() { ad.RankMgr = &RankMgr{ @@ -361,6 +298,13 @@ func (ad *GameLogic) CreateMailMgr() { ad.MailMgr.Init() } +func (ad *GameLogic) CreateMessageMgr() { + ad.MessageMgr = &MessageMgr{ + ServerMod: new(ServerMod), + } + ad.MessageMgr.MessageMgrInit() +} + func (ad *GameLogic) MailMgrSend(m *MsgMod.Msg) { ad.MailMgr.Send(m) } @@ -413,26 +357,6 @@ func (ad *GameLogic) VarMgrCall(m *MsgMod.Msg) interface{} { return result } -// 封号管理器 -func (ad *GameLogic) CreateBanMgr() { - ad.BanMgr = &BanMgr{ - ServerMod: new(ServerMod), - } - ad.BanMgr.Init() -} - -func (ad *GameLogic) BanMgrSend(m *MsgMod.Msg) { - ad.BanMgr.Send(m) -} - -func (ad *GameLogic) BanMgrCall(m *MsgMod.Msg) interface{} { - result, err := ad.BanMgr.Call(m) - if err != nil { - return nil - } - return result -} - func (ad *GameLogic) GetSimplePlayerByUid(Id int) *PlayerSimpleData { if Id == 0 { return nil @@ -546,13 +470,15 @@ func G_getGameLogic() *GameLogic { G_GameLogicPtr.InitActivity() // 初始化活动 G_GameLogicPtr.GetVersion() // 获取版本号 G_GameLogicPtr.CreateLogManager() //加载日志管理器 - G_GameLogicPtr.CreateFriendMgr() //创建好友管理器 - G_GameLogicPtr.CreateRankMgr() //创建排行榜管理器 - G_GameLogicPtr.CreateMailMgr() //创建邮件管理器 - G_GameLogicPtr.CreateChampshipMgr() // 创建竞标赛管理器 - G_GameLogicPtr.CreateVarMgr() // 创建变量管理器 - G_GameLogicPtr.CreateBanMgr() // 创建封号管理器 - ClusterMgrInit() //初始化集群 + if conf.Server.ServerType == "center" { + G_GameLogicPtr.CreateFriendMgr() //创建好友管理器 + G_GameLogicPtr.CreateChampshipMgr() // 创建竞标赛管理器 + G_GameLogicPtr.CreateVarMgr() // 创建变量管理器 + } + G_GameLogicPtr.CreateRankMgr() //创建排行榜管理器 + G_GameLogicPtr.CreateMailMgr() //创建邮件管理器 + G_GameLogicPtr.CreateMessageMgr() // 创建消息管理器 + ClusterMgrInit() //初始化集群 G_GameLogicPtr.StartTime = time.Now().Unix() // G_GameLogicPtr.CreateHttpManager() } @@ -656,7 +582,6 @@ func (ad *GameLogic) ReplaceExistPlayerAndAgent(a gate.Agent, player *Player) er if ok { Timer.Stop() } - player.SyncFriendMsg() log.Debug("player %d 重连", player.M_DwUin) return nil } @@ -728,15 +653,14 @@ func (ad *GameLogic) RegisterNetWorkFunc() { RegisterMsgProcessFunc("ReqId2Verify", ReqId2Verify) // 身份证验证 // 玩家 RegisterMsgProcessFunc("ReqUserInfo", ReqUserInfo) - RegisterMsgProcessFunc("ReqSetName", ReqSetName) // 设置名字 - RegisterMsgProcessFunc("ReqLang", ReqLang) // 设置语言 - RegisterMsgProcessFunc("ReqSetPetName", ReqSetPetName) // 设置宠物名字 - RegisterMsgProcessFunc("ReqSetFacebookUrl", ReqSetFacebookUrl) // 设置facebook地址 - RegisterMsgProcessFunc("ReqPlayerBaseInfo", ReqPlayerBaseInfofunction) // 请求玩家基本信息 - RegisterMsgProcessFunc("UpdateBaseItemInfo", UpdateBaseItemInfofunction) // 保存引导 - RegisterMsgProcessFunc("ReqKv", ReqKv) // 保存客户端数据 - RegisterMsgProcessFunc("ReqGetEnergyByAD", ReqGetEnergyByAD) // 看广告获取能量 - RegisterMsgProcessFunc("ReqBuyEnergy", ReqBuyEnergy) // 购买能量 + RegisterMsgProcessFunc("ReqSetName", ReqSetName) // 设置名字 + RegisterMsgProcessFunc("ReqLang", ReqLang) // 设置语言 + RegisterMsgProcessFunc("ReqSetPetName", ReqSetPetName) // 设置宠物名字 + RegisterMsgProcessFunc("ReqSetFacebookUrl", ReqSetFacebookUrl) // 设置facebook地址 + RegisterMsgProcessFunc("ReqPlayerBaseInfo", ReqPlayerBaseInfofunction) // 请求玩家基本信息 + RegisterMsgProcessFunc("ReqKv", ReqKv) // 保存客户端数据 + RegisterMsgProcessFunc("ReqGetEnergyByAD", ReqGetEnergyByAD) // 看广告获取能量 + RegisterMsgProcessFunc("ReqBuyEnergy", ReqBuyEnergy) // 购买能量 // #region 棋盘 RegisterMsgProcessFunc("ReqPlayerChessData", ReqPlayerChessDataFunc) RegisterMsgProcessFunc("UpdatePlayerChessData", UpdatePlayerChessDataFunc) // 更新棋盘数据 @@ -989,11 +913,9 @@ func (ad *GameLogic) GetStartTime() int64 { } func NotifyPlayer(Uid int, m *MsgMod.Msg) { - p := G_GameLogicPtr.GetPlayer(int64(Uid)) - if p == nil || p.stop { - return - } - p.Send(m) + m.To = Uid + m.HandleType = MsgMod.HANDLE_MOD_PLAYER_MSG + CenterPlayerMsgHandler(m) } func Destroy() { @@ -1009,7 +931,6 @@ func Destroy() { G_GameLogicPtr.ChampshipMgr.SaveData() G_GameLogicPtr.MailMgr.SaveData() G_GameLogicPtr.VarMgr.SaveData() - G_GameLogicPtr.BanMgr.SaveData() G_GameLogicPtr.MLogManager.Close() } log.Debug("服务器下线完成") diff --git a/src/server/game/activity_func.go b/src/server/game/activity_func.go index a840a5cc..78937420 100644 --- a/src/server/game/activity_func.go +++ b/src/server/game/activity_func.go @@ -1,7 +1,6 @@ package game import ( - "fmt" activityCfg "server/conf/activity" catnipCfg "server/conf/catnip" guesscolorCfg "server/conf/guess_color" @@ -360,34 +359,33 @@ func (p *Player) CatnipBackData() { } tmpData := make(map[int]*msg.CatnipInvite) InviteList := make([]*msg.CatnipInvite, 0) - for Uid, Info := range CatnipMod.InviteList { - tmpData[Uid] = &msg.CatnipInvite{ - Uid: int64(Uid), - Time: Info.Time, + for uid, info := range CatnipMod.InviteList { + tmpData[uid] = &msg.CatnipInvite{ + Uid: int64(uid), + Time: info.Time, Type: 1, } } - for Uid, Info := range CatnipMod.BeInvitedList { - tmpData[Uid] = &msg.CatnipInvite{ - Uid: int64(Uid), - Time: Info.Time, + for uid, info := range CatnipMod.BeInvitedList { + tmpData[uid] = &msg.CatnipInvite{ + Uid: int64(uid), + Time: info.Time, Type: 2, } } - for Uid := range FriendMod.NewFriendList { - key := fmt.Sprintf("catnip_partner_%d", Uid) - Var := G_GameLogicPtr.VarMgr.GetExpireVar(key) - if len(GoUtil.IntSlice(Var.D)) >= 4 { - tmpData[Uid] = &msg.CatnipInvite{ - Uid: int64(Uid), + for uid := range FriendMod.NewFriendList { + partnerList := p.GetCatnipPartner(uid) + if len(GoUtil.IntSlice(partnerList)) >= 4 { + tmpData[uid] = &msg.CatnipInvite{ + Uid: int64(uid), Type: 3, } continue } - if _, ok := tmpData[Uid]; !ok { - tmpData[Uid] = &msg.CatnipInvite{ - Uid: int64(Uid), + if _, ok := tmpData[uid]; !ok { + tmpData[uid] = &msg.CatnipInvite{ + Uid: int64(uid), Type: 0, } } @@ -417,14 +415,3 @@ func (p *Player) CatnipBackData() { } p.PushClientRes(res) } - -// 设置猫草大作战游戏锁 -func (p *Player) SetCatnipGameLock(Uid int, GameId int) error { - ActivityInfo := p.GetActivityInfoById(activity.ACT_TYPE_CATNIP) - return G_GameLogicPtr.SetDataSync(int(p.M_DwUin), VAR_OP_CATNIP_LOCK, CatnipLock{ - Uid: int(p.M_DwUin), - Partner: Uid, - GameId: GameId, - End: int(ActivityInfo.EndT), // 锁 - }) -} diff --git a/src/server/game/admin.go b/src/server/game/admin.go index 45361af8..657fd57f 100644 --- a/src/server/game/admin.go +++ b/src/server/game/admin.go @@ -100,7 +100,7 @@ func VerifyUser(accountInfo *db.Db_Account, detail *msg.ReqLogin) (ResLogin *msg return } - if G_GameLogicPtr.BanMgr.IsBanned(playerbaseinfo.DwUin) { + if playerbaseinfo.Ban > GoUtil.Now() || playerbaseinfo.Ban == -1 { ResLogin = &msg.ResLogin{ ResultCode: MergeConst.Protocol_Error_Account_Ban, DwUin: 0, @@ -176,7 +176,7 @@ func AdminPlayerInfo(args []interface{}) error { res["Cumulative"] = player.PlayMod.getBaseMod().Cumulative res["RegisterTime"] = player.GetPlayerBaseMod().GetRegisterTime() res["TodayCumulative"] = player.PlayMod.getBaseMod().TodayCumulative - res["Ban"] = G_GameLogicPtr.BanMgr.GetBanInfo(player.M_DwUin).EndTime + res["Ban"] = db.GetPlayerBan(player.PlayMod.getBaseMod().Account) if online { res["Cumulative"] = int64(player.PlayMod.getBaseMod().Cumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime) res["TodayCumulative"] = int64(player.PlayMod.getBaseMod().TodayCumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime) @@ -283,7 +283,7 @@ func ReqAdminBan(args []interface{}) error { res := make(map[string]interface{}) res["Code"] = 0 res["Msg"] = "ok" - G_GameLogicPtr.BanMgr.BanUser(req.Uid, int64(req.Time), req.Reason) + db.UpdatePlayerBan(req.Uid, int64(req.Time)) AdminPlayerBack(a, res) return nil } diff --git a/src/server/game/ban_mgr.go b/src/server/game/ban_mgr.go deleted file mode 100644 index 0bc22fb0..00000000 --- a/src/server/game/ban_mgr.go +++ /dev/null @@ -1,69 +0,0 @@ -package game - -import ( - "encoding/gob" - GoUtil "server/game_util" -) - -type BanMgr struct { - *ServerMod -} - -type BanData struct { - NewBanList map[int64]*BanInfo // 新增的封禁列表 -} - -type BanInfo struct { - UserId int64 // 玩家ID - EndTime int64 // 封禁结束时间,0表示永久封禁 - Reason string // 封禁原因 -} - -func (f *BanMgr) Init() { - gob.Register(&BanData{}) - f.key = BAN_MGR_KEY - f.data = &BanData{ - NewBanList: make(map[int64]*BanInfo), - } - // 注册处理函数 - f.init() - if f.data.(*BanData).NewBanList == nil { - f.data.(*BanData).NewBanList = make(map[int64]*BanInfo) - } -} - -func (f *BanMgr) IsBanned(userId int64) bool { - if f.data.(*BanData).NewBanList == nil { - return false - } - Info, banned := f.data.(*BanData).NewBanList[userId] - if !banned { - return false - } - return Info.EndTime > GoUtil.Now() || Info.EndTime == -1 // 如果EndTime为0,表示永久封禁 -} - -func (f *BanMgr) GetBanInfo(userId int64) *BanInfo { - if f.data.(*BanData).NewBanList == nil { - return &BanInfo{} - } - Info, banned := f.data.(*BanData).NewBanList[userId] - if !banned { - return &BanInfo{} - } - return Info -} - -func (f *BanMgr) BanUser(userId int64, endTime int64, reason string) { - f.data.(*BanData).NewBanList[userId] = &BanInfo{ - UserId: userId, - EndTime: endTime, - Reason: reason, - } - f.SaveData() -} - -func (f *BanMgr) UnbanUser(userId int64) { - delete(f.data.(*BanData).NewBanList, userId) - f.SaveData() -} diff --git a/src/server/game/champship_mgr.go b/src/server/game/champship_mgr.go index 2eec44f1..d54fbed9 100644 --- a/src/server/game/champship_mgr.go +++ b/src/server/game/champship_mgr.go @@ -81,67 +81,53 @@ func (c *ChampshipMgr) Init() { } // 注册处理函数 c.init() - c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_GROUP, c.group) - c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_INRANK, c.inRank) - c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_AI, c.ai) - c.RegisterHandler(msg.SERVER_ZERO_UPDATE, c.ZeroUpdate) - c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY2, c.NotifyAll) - Now := GoUtil.Now() ZeroTime := GoUtil.ZeroTimestamp() if c.getData().ZeroTime != ZeroTime { - c.ZeroUpdate(&msg.Msg{}) + c.ZeroUpdate() } Remain := Now - ZeroTime Remain1 := 1800 - Remain%1800 c.mDispatr.AfterFunc(time.Duration(Remain1)*time.Second, func() { // 30分钟后重新分组 - c.Send(&msg.Msg{ - Type: msg.HANDLE_TYPE_CHAMPSHIP_GROUP, - }) + c.group() }) c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() { - c.Send(&msg.Msg{ - Type: msg.HANDLE_TYPE_CHAMPSHIP_AI, - }) + c.ai() }) c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() { - c.Send(&msg.Msg{ - Type: msg.SERVER_ZERO_UPDATE, - }) + c.ZeroUpdate() }) } -func (c *ChampshipMgr) NotifyAll(m *msg.Msg) (interface{}, error) { - G_GameLogicPtr.NotifyAll(&msg.Msg{ - Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY, +func (c *ChampshipMgr) NotifyAll() (interface{}, error) { + NotifyAllPlayerMsg(&msg.Msg{ + Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY, + HandleType: msg.HANDLE_MOD_PLAYER_MSG, }) return nil, nil } -func (c *ChampshipMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) { +func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) { log.Debug("ChampshipMgr ZeroUpdate") c.getData().ZeroTime = GoUtil.ZeroTimestamp() c.getData().PreRank = c.getData().Rank c.getData().PreRobot = c.getData().Robot c.getData().PreGroupInfo = c.getData().GroupInfo - + c.getData().AutoId = 0 + c.getData().RobotId = 1 c.getData().Robot = make(map[int]*ChampshipRobot, 0) c.getData().Rank = make(map[int][]*ChampshipRank, 0) c.getData().GroupInfo = make(map[int]int, 0) c.update = true c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() { - c.Send(&msg.Msg{ - Type: msg.SERVER_ZERO_UPDATE, - }) + c.ZeroUpdate() }) c.NotifyPlayer() c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() { - c.Send(&msg.Msg{ - Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY2, - }) + c.NotifyAll() }) return nil, nil } @@ -158,7 +144,7 @@ func (c *ChampshipMgr) NotifyPlayer() { } } -func (c *ChampshipMgr) ai(m *msg.Msg) (interface{}, error) { +func (c *ChampshipMgr) ai() (interface{}, error) { ChampshipData := c.getData() Now := GoUtil.Now() for k, v := range ChampshipData.Rank { @@ -205,9 +191,7 @@ func (c *ChampshipMgr) ai(m *msg.Msg) (interface{}, error) { ChampshipData.Rank[k] = v } c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() { - c.Send(&msg.Msg{ - Type: msg.HANDLE_TYPE_CHAMPSHIP_AI, - }) + c.ai() }) return nil, nil } @@ -265,6 +249,8 @@ func (c *ChampshipMgr) GetPreRankMsg(Uid int) *proto.ResChampshipPreRank { RankList: RL, } } + +// TODO 待优化 func (c *ChampshipMgr) GetRankMsg(Uid int) *proto.ResChampshipRank { ChampshipData := c.getData() GroupId := ChampshipData.GroupInfo[Uid] @@ -320,11 +306,9 @@ func (c *ChampshipMgr) GetRankMsg(Uid int) *proto.ResChampshipRank { } // 分组 -func (c *ChampshipMgr) group(m *msg.Msg) (interface{}, error) { +func (c *ChampshipMgr) group() (interface{}, error) { c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() { // 30分钟后重新分组 - c.Send(&msg.Msg{ - Type: msg.HANDLE_TYPE_CHAMPSHIP_GROUP, - }) + c.group() }) Now := GoUtil.Now() Zero := GoUtil.ZeroTimestamp() diff --git a/src/server/game/charge_func.go b/src/server/game/charge_func.go index 836a3214..f4d3c568 100644 --- a/src/server/game/charge_func.go +++ b/src/server/game/charge_func.go @@ -35,7 +35,7 @@ func (p *Player) Charge(ChargeId int) { } func (p *Player) SendCharge(d *ChargeExtra) { - G_GameLogicPtr.FriendMgrSend(&MsgMod.Msg{ + FriendMgrSend(&MsgMod.Msg{ From: int(p.M_DwUin), Type: MsgMod.HANDLE_TYPE_SEND_CHARGE, To: int(d.Uid), diff --git a/src/server/game/cluster_mgr.go b/src/server/game/cluster_mgr.go index 98374e2f..d3272ac6 100644 --- a/src/server/game/cluster_mgr.go +++ b/src/server/game/cluster_mgr.go @@ -11,20 +11,12 @@ func ClusterMgrInit() { go func() { for { m := <-mergeCluster.MsgChan - clusterHandlerProcess(m) + MessageHandle(m) } }() } -func clusterHandlerProcess(m *msg.Msg) { - if fun, ok := clusterHandler[m.Type]; ok { - fun(m) - } else { - FriendMgrSend(m) - } -} - func RegisterClusterHandler(t int, fun func(*msg.Msg) error) { clusterHandler[t] = fun } diff --git a/src/server/game/friend_mgr.go b/src/server/game/friend_mgr.go index 79ea8061..912a1992 100644 --- a/src/server/game/friend_mgr.go +++ b/src/server/game/friend_mgr.go @@ -3,7 +3,6 @@ package game import ( "encoding/gob" "fmt" - "server/MergeConst" mergeCluster "server/cluster" "server/conf" "server/game/mod/card" @@ -45,7 +44,6 @@ func (f *FriendMgr) Init() { f.RegisterHandler(msg.HANDLE_TYPE_APPLY, f.sendToPlayer) f.RegisterHandler(msg.HADNLE_TYPE_AGREE, f.sendToPlayer) f.RegisterHandler(msg.HANDLE_TYPE_DEL, f.sendToPlayer) - f.RegisterHandler(msg.HANDLE_TYPE_SYNC, f.sync) f.RegisterHandler(msg.HANDLE_TYPE_REFUSE, f.sendToPlayer) f.RegisterHandler(msg.HANDLE_TYPE_INVITE_ADD_FRIEND, f.sendToPlayer) f.RegisterHandler(msg.HANDLE_TYPE_INVITE_FRIEND, f.sendToPlayer) @@ -87,11 +85,6 @@ func (f *FriendMgr) Init() { f.RegisterHandler(msg.HANDLE_TYPE_PLAYROOM_KISS, f.sendToPlayerOnline) f.RegisterHandler(msg.HANDLE_TYPE_PLAYROOM_GAME, f.sendToPlayer) - f.RegisterHandler(msg.HANDLE_TYPE_VAR_USER_GET, f.GetVarUserData) - f.RegisterHandler(msg.HANDLE_TYPE_VAR_USER_SET, f.SetVarUserData) - - f.RegisterHandler(msg.HANDLE_TYPE_VAR_EXPIRE_SET, f.SetExpireVarData) - f.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_LOGIN, f.SendMsgToCenter) f.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_INRANK, f.SendMsgToCenter) } @@ -138,71 +131,6 @@ func (f *FriendMgr) sendToPlayerOnline(m *msg.Msg) (interface{}, error) { return nil, nil } -// 同步信息 -func (f *FriendMgr) sync(m *msg.Msg) (interface{}, error) { - data := f.getData().List[m.From] - return data, nil -} - -func (f *FriendMgr) GetVarUserData(m *msg.Msg) (interface{}, error) { - Key := GoUtil.GetUserKey(int64(m.To)) - data := G_GameLogicPtr.VarMgr.GetUserVar(Key) - if data == nil { - data = &VarUserData{ - Upvote: 0, - } - } - return data, nil -} - -func (f *FriendMgr) SetVarUserData(m *msg.Msg) (interface{}, error) { - VarOp := m.Extra.(VarOpration) - Key := GoUtil.GetUserKey(int64(m.To)) - data := G_GameLogicPtr.VarMgr.GetUserVar(Key) - switch VarOp.Type { - case VAR_OP_UPVOTE: - data.Upvote++ - case VAR_OP_CHIP: - data.Chip += VarOp.Data.(int) - case VAR_OP_CHIP_SET: - data.Chip = VarOp.Data.(int) - case VAR_OP_KISS: - data.Kiss = VarOp.Data.(int) - } - return &VarOpration{ - Data: data, - Code: MergeConst.SUCCESS, - }, nil -} - -func (f *FriendMgr) SetExpireVarData(m *msg.Msg) (interface{}, error) { - VarOp := m.Extra.(VarOpration) - switch VarOp.Type { - case VAR_OP_CATNIP_LOCK: - data := VarOp.Data.(CatnipLock) - MyKey := GoUtil.GetCatnipLockKey(data.Uid, data.GameId) - OtherKey := GoUtil.GetCatnipLockKey(data.Partner, data.GameId) - ExpireData := G_GameLogicPtr.VarMgr.GetExpireVar(OtherKey) - if _, ok := ExpireData.D.(*CatnipLock); ok { - return nil, fmt.Errorf("catnip lock already exists for %d in game %d", data.Uid, data.GameId) - } - G_GameLogicPtr.VarMgr.SetExpireVar(MyKey, &VarExpireData{ - T: int64(data.End + 24*3600), // 设置过期时间 - D: &data, - }) - G_GameLogicPtr.VarMgr.SetExpireVar(OtherKey, &VarExpireData{ - T: int64(data.End + 24*3600), // 设置过期时间 - D: &CatnipLock{ - Uid: data.Partner, - Partner: data.Uid, - GameId: data.GameId, - End: data.End, - }, - }) - } - return nil, nil -} - // 发送消息给玩家 func sendToPlayer(m *msg.Msg) error { p := G_GameLogicPtr.GetPlayer(int64(m.To)) @@ -222,24 +150,6 @@ func sendToPlayerOnline(m *msg.Msg) error { return nil } -func FriendMgrSend(m1 *msg.Msg) error { - if m1.SendT == 0 { - m1.SendT = GoUtil.Now() - } - m := m1.Clone() - ToServer := GoUtil.GetServerIdByUid(m.To) - if ToServer != conf.Server.ServerID { - err := mergeCluster.SendServerMsg(m, ToServer) - if err != nil { // 区服不在线 - G_GameLogicPtr.FriendMgrSend(m) - return err - } - return nil - } - G_GameLogicPtr.FriendMgrSend(m) - return nil -} - // 集群好友消息同步 func ClusterFriendSync(m *msg.Msg) error { if v, ok := G_GameLogicPtr.FriendMgr.getData().ClusterMsg[m.To]; ok { @@ -264,24 +174,3 @@ func (f *FriendMgr) SendMsgToCenter(m *msg.Msg) (interface{}, error) { func (f *FriendMgr) CallMsgToCenter(m *msg.Msg) (interface{}, error) { return mergeCluster.CallServerMsg(m, conf.Server.CenterNode) } - -func FriendMgrCall(m *msg.Msg) interface{} { - ToServer := GoUtil.GetServerIdByUid(m.To) - if ToServer != conf.Server.ServerID { - r, err := mergeCluster.CallServerMsg(m, ToServer) - if err != nil { // 区服不在线 - log.Debug("FriendMgrCall err %v", err) - return nil - } - return r - } - return G_GameLogicPtr.FriendMgrCall(m.Clone()) -} - -func SendMsgToCenter(m *msg.Msg) error { - return mergeCluster.SendServerMsg(m, conf.Server.CenterNode) -} - -func CallMsgToCenter(m *msg.Msg) (interface{}, error) { - return mergeCluster.CallServerMsg(m, conf.Server.CenterNode) -} diff --git a/src/server/game/game_type.go b/src/server/game/game_type.go index 47e1f73a..df0a844c 100644 --- a/src/server/game/game_type.go +++ b/src/server/game/game_type.go @@ -2,9 +2,13 @@ package game import ( "encoding/gob" + "server/game/mod/card" "server/game/mod/friend" + "server/game/mod/item" limitedTimeEvent "server/game/mod/limited_time_event" "server/game/mod/msg" + proto "server/msg" + "sync" ) type PlayerSimpleData struct { @@ -49,11 +53,21 @@ type VarUserData struct { Upvote int Chip int Kiss int + mu sync.Mutex } type VarExpireData struct { - D interface{} - T int64 + D interface{} + T int64 // 过期时间戳 + U int64 // 最后更新时间 + mu sync.Mutex +} + +type CatnipPartner struct { + Uid int + Partner int + GameId int + EndTime int64 } const ( @@ -108,8 +122,13 @@ func init() { gob.Register(&VarUserData{}) gob.Register(&ActivityInfo{}) gob.Register(&ChargeExtra{}) - gob.Register(&GameResult{}) gob.Register(CatnipMsg{}) gob.Register(&CatnipLock{}) gob.Register(CRank{}) + gob.Register(&proto.ResChampshipRank{}) + gob.Register(&proto.ResChampshipPreRank{}) + gob.Register(card.CardInfo{}) + gob.Register(item.Item{}) + gob.Register([]*item.Item{}) // 注册 []*item.Item 类型 + gob.Register(friend.ReplyInfo{}) } diff --git a/src/server/game/gm_handler.go b/src/server/game/gm_handler.go index 74d8c921..e57ed313 100644 --- a/src/server/game/gm_handler.go +++ b/src/server/game/gm_handler.go @@ -46,7 +46,7 @@ func ReqGmCommand_(player *Player, Command string) error { // log.Error("ReqGmCommand panic: %v", err) // } // }() - if conf.Server.GameName != "pet_home" && conf.Server.GameName != "merge_pet_sdk" && conf.Server.GameName != "Merge_Pet_Local" { + if conf.Server.GameName != "pet_home" && conf.Server.GameName != "merge_pet_sdk" && conf.Server.GameName != "Merge_Pet_Local" && conf.Server.GameName != "pet_home_local" { return fmt.Errorf("Player %d ReqGmCommand not support in game %s, command %s", player.M_DwUin, conf.Server.GameName, Command) } player.TeLog("gm", map[string]interface{}{ @@ -393,13 +393,8 @@ func ReqGmCommand_(player *Player, Command string) error { } player.PushClientRes(CardMod.NotifyCard()) case "resetRankUser": - O := G_GameLogicPtr.RankMgr.getAllRank(RANK_TYPE_USER) - for _, v := range O { - Uid := strconv.Itoa(v.Uid) - TimeSort := fmt.Sprintf("0.%d", RANK_TIME_SORT-GoUtil.Now()) - TimeSortF, _ := strconv.ParseFloat(TimeSort, 64) - db.RedisZAdd(RANK_USER, Uid, v.Score+TimeSortF) - } + db.RedisDelKey(RANK_USER) + db.RedisDelKey(fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode)) case "addFriendStar": FriendTreasureMod := player.PlayMod.getFriendTreasureMod() FriendTreasureMod.AddStar(200) @@ -513,6 +508,7 @@ func ReqGmCommand_(player *Player, Command string) error { BaseMod.Uid = player.M_DwUin BaseMod.NickName = player.PlayMod.getBaseMod().NickName BaseMod.LoginTime = GoUtil.Now() + BaseMod.AddCode = fmt.Sprintf("MMM-%s-%s", "156", GoUtil.UniqueStringFromInt(int(BaseMod.Uid))) // deep copy p1.PlayMod.mod_list to avoid sharing internal pointers var modCopy PlayerModList var buf bytes.Buffer diff --git a/src/server/game/message_handler.go b/src/server/game/message_handler.go index 13254d2b..18fc979d 100644 --- a/src/server/game/message_handler.go +++ b/src/server/game/message_handler.go @@ -509,38 +509,6 @@ func (p *Player) handle(m *msg.Msg) error { return nil } -// 同步好友请求 -func (p *Player) SyncFriendMsg() { - MsgList := G_GameLogicPtr.FriendMgrCall(&msg.Msg{Type: msg.HANDLE_TYPE_SYNC, From: int(p.M_DwUin)}) - FriendMod := p.PlayMod.getFriendMod() - MsgId := FriendMod.GetSyncId() - if MsgList == nil { - return - } - ml := MsgList.([]*msg.Msg) - if len(ml) == 0 { - return - } - sort.Slice(ml, func(i, j int) bool { - return ml[i].Id < ml[j].Id - }) - maxId := int64(0) - for _, v := range ml { - maxId = max(maxId, v.Id) - if v.H == 1 { - continue - } - if v.Id > 0 && v.Id <= MsgId { - continue - } - log.Debug("uid : %d, handle friend msg : %v", p.M_DwUin, v) - p.handle(v) - v.H = 1 - } - FriendMod.SetSyncId(maxId) - p.PlayMod.save() -} - func SyncMailMsg(p *Player) { ServerMailList := G_GameLogicPtr.MailMgr.Sync(int(p.M_DwUin), p.GetPlayerBaseMod().GetRegisterTime()) MailMod := p.PlayMod.getMailMod() @@ -736,7 +704,7 @@ func NotifyChampshipResult(Uid, Rank int) { SendT: GoUtil.Now(), Extra: []int{Rank, GoUtil.GetServerOpenDay()}, } - FriendMgrSend(Msg) + CenterPlayerMsgHandler(Msg) } } @@ -1302,3 +1270,18 @@ func (player *Player) IsWeeklyDiscount() bool { LimitEventMod := player.PlayMod.getLimitedTimeEventMod() return ChargeMod.IsWeeklyDiscountDay() || LimitEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_CAT_DAY_SALE) } + +func (p *Player) SetCatnipPartner(GameId, Partner int, EndTime int64) error { + _, err := SendMsgToCenterSync(&msg.Msg{ + From: int(p.M_DwUin), + To: int(p.M_DwUin), + Type: msg.HANDLE_MOD_CATNIP_PARTNER, + Extra: CatnipPartner{ + GameId: GameId, + Partner: Partner, + EndTime: EndTime, + Uid: int(p.M_DwUin), + }, + }) + return err +} diff --git a/src/server/game/message_mgr.go b/src/server/game/message_mgr.go index 5f7dc0a9..f2da29e9 100644 --- a/src/server/game/message_mgr.go +++ b/src/server/game/message_mgr.go @@ -1,26 +1,315 @@ package game import ( + "context" + "encoding/gob" "fmt" + "runtime/debug" mergeCluster "server/cluster" + "server/conf" "server/game/mod/msg" GoUtil "server/game_util" "server/pkg/github.com/name5566/leaf/log" + "sync" + "time" ) +// 中间件函数类型 +type MessageMiddleware func(MessageHandlerFunc) MessageHandlerFunc + type MessageMgr struct { *ServerMod + middlewares []MessageMiddleware + workerPool *WorkerPool + handler map[int]MessageHandlerFunc } type MessageData struct { - MessageList map[int64][]*msg.Msg + MessageList map[int64]*MessageList + PlayerList map[int64]int + mu sync.Mutex +} + +type MessageList struct { + Messages []*msg.Msg + mu sync.Mutex +} + +// Worker Pool 结构 +type WorkerPool struct { + workers int + taskQueue chan *MessageTask + wg sync.WaitGroup + ctx context.Context + cancel context.CancelFunc + maxQueue int +} + +// 消息任务 +type MessageTask struct { + Msg *msg.Msg + Handler MessageHandlerFunc + Result chan *TaskResult +} + +// 任务结果 +type TaskResult struct { + Data interface{} + Error error } func (m *MessageMgr) MessageMgrInit() { m.key = MESSAGE_MGR_KEY - m.data = &MessageData{} + m.data = &MessageData{ + MessageList: make(map[int64]*MessageList), + PlayerList: make(map[int64]int), + } + gob.Register(msg.VarData{}) + gob.Register(GameResult{}) // 注册处理函数 m.init() + m.handler = make(map[int]MessageHandlerFunc) + m.middlewares = []MessageMiddleware{} + // 初始化 Worker Pool (10个worker, 1000个队列大小) + m.workerPool = NewWorkerPool(10, 1000) + // 注册默认中间件 + m.Use(RecoveryMiddleware()) + m.Use(LoggingMiddleware()) + m.Use(TimeoutMiddleware(5 * time.Second)) + m.NodeRegister() + m.CenterRegister() +} + +// 注册处理器 +func (s *MessageMgr) RegisterHandler(HandlerType int, fun MessageHandlerFunc) { + s.handler[HandlerType] = fun +} + +func (m *MessageMgr) NodeRegister() { + if conf.Server.ServerType == "node" { + m.RegisterHandler(msg.HANDLE_MOD_PLAYER_MSG, MessageHandlerFunc(PlayerMsgHandler)) + m.RegisterHandler(msg.HANDLE_MOD_REPLY_PLAYER_MSG, MessageHandlerFunc(PlayerReplyMsgHandler)) + m.RegisterHandler(msg.HANDLE_MOD_CLUSTER_SYNC, MessageHandlerFunc(ClusterSyncHandler)) + } +} + +func (m *MessageMgr) CenterRegister() { + if conf.Server.ServerType == "center" { + m.RegisterHandler(msg.HANDLE_MOD_PLAYER_LOGIN, MessageHandlerFunc(PlayerLoginHandler)) + m.RegisterHandler(msg.HANDLE_MDO_PLAYER_LOGOUT, MessageHandlerFunc(PlayerLogoutHandler)) + m.RegisterHandler(msg.HANDLE_MOD_PLAYER_MSG, MessageHandlerFunc(CenterPlayerMsgHandler)) + m.RegisterHandler(msg.HANDLE_MOD_COMSUME_MSG, MessageHandlerFunc(ComsumerMsgHandler)) + m.RegisterHandler(msg.HANDLE_MOD_VAR_SET, MessageHandlerFunc(SetVarDataHandler)) + m.RegisterHandler(msg.HANDLE_MOD_VAR_GET, MessageHandlerFunc(GetVarDataHandler)) + m.RegisterHandler(msg.HANDLE_MOD_USER_VAR_SET, MessageHandlerFunc(SetUserVarDataHandler)) + m.RegisterHandler(msg.HANDLE_MOD_USER_VAR_GET, MessageHandlerFunc(GetUserVarDataHandler)) + m.RegisterHandler(msg.HANDLE_MOD_CATNIP_PARTNER, MessageHandlerFunc(CatnipPartnerHandler)) + m.RegisterHandler(msg.HANDLE_MDO_CHAMPSHIP_INRANK, MessageHandlerFunc(ChampshipInRankHandler)) + m.RegisterHandler(msg.HANDLE_MOD_CHAMPSHIP_RANK_INFO, MessageHandlerFunc(ChampshipRankInfoHandler)) + m.RegisterHandler(msg.HANDLE_MOD_CHAMPSHIP_RANK_LIST, MessageHandlerFunc(ChampshipRankListHandler)) + m.RegisterHandler(msg.HANDLE_MOD_CHAMPSHIP_PRE_RANK, MessageHandlerFunc(ChampshipRankPreHandler)) + } +} + +func getMessageData() *MessageData { + return G_GameLogicPtr.MessageMgr.data.(*MessageData) +} + +// ----------------------------------- 处理函数实现 --------------------------- +func ChampshipRankPreHandler(data *msg.Msg) (interface{}, error) { + PlayerId := data.From + PreRankMsg := G_GameLogicPtr.ChampshipMgr.GetPreRankMsg(PlayerId) + ReplyPlayerMsgASync(data, PreRankMsg) + return nil, nil +} + +func ChampshipRankListHandler(data *msg.Msg) (interface{}, error) { + PlayerId := data.From + RankMsg := G_GameLogicPtr.ChampshipMgr.GetRankMsg(PlayerId) + ReplyPlayerMsgASync(data, RankMsg) + return nil, nil +} + +func ChampshipRankInfoHandler(data *msg.Msg) (interface{}, error) { + PlayerId := data.From + MyRank := G_GameLogicPtr.ChampshipMgr.getMyRank(PlayerId) + MyPreRank := G_GameLogicPtr.ChampshipMgr.getLastMyRank(PlayerId) + ReplyPlayerMsgASync(data, []int{MyRank, MyPreRank}) + return nil, nil +} + +func NotifyAllPlayerMsg(m *msg.Msg) { + messageMgrData := getMessageData() + for PlayerId, node := range messageMgrData.PlayerList { + m.To = int(PlayerId) + go SendMsgToNodeAsync(m, node) + } +} + +func ChampshipInRankHandler(data *msg.Msg) (interface{}, error) { + G_GameLogicPtr.ChampshipMgr.inRank(data) + return nil, nil +} + +func CatnipPartnerHandler(data *msg.Msg) (interface{}, error) { + m, ok := data.Extra.(*CatnipPartner) + if !ok { + return nil, fmt.Errorf("invalid catnip partner data") + } + return G_GameLogicPtr.VarMgr.HandleCatnipPartner(m.Uid, m.Partner, m.GameId, m.EndTime) +} + +func ReplyPlayerMsgASync(m *msg.Msg, reply interface{}) (interface{}, error) { + clone := m.Reply(reply) + messageMgrData := getMessageData() + if node, ok := messageMgrData.PlayerList[int64(m.From)]; ok { + go SendMsgToNodeAsync(clone, node) + } + return nil, nil +} + +// 节点连接时,同步消息 +func ClusterSyncHandler(data *msg.Msg) (interface{}, error) { + // 遍历所有玩家,发送登录消息 + G_GameLogicPtr.M_Players.Range(func(k, v interface{}) bool { + SendMsgToCenterAsync(&msg.Msg{ + From: int(v.(*Player).M_DwUin), + HandleType: msg.HANDLE_MOD_PLAYER_LOGIN, + Extra: conf.Server.ServerID, + }) + return true + }) + // 发送暂存区消息 + messageMgrData := getMessageData() + messageMgrData.mu.Lock() + defer messageMgrData.mu.Unlock() + TempMessageList := messageMgrData.MessageList + messageMgrData.MessageList = make(map[int64]*MessageList) + for PlayerId, Message := range TempMessageList { + for _, msgItem := range Message.Messages { + go SendMsgToNodeAsync(msgItem, messageMgrData.PlayerList[PlayerId]) + } + } + return nil, nil +} + +func PlayerLoginHandler(data *msg.Msg) (interface{}, error) { + // 关闭 Worker Pool + messageMgrData := getMessageData() + messageMgrData.mu.Lock() + defer messageMgrData.mu.Unlock() + messageMgrData.PlayerList[int64(data.From)] = data.Extra.(int) + if _, ok := messageMgrData.MessageList[int64(data.From)]; !ok { + messageMgrData.MessageList[int64(data.From)] = &MessageList{ + Messages: []*msg.Msg{}, + } + } + log.Debug("[Middleware] Player login success player id: %v, node: %v", data.From, data.Extra.(int)) + node := data.Extra.(int) + messageMgrData.PlayerList[int64(data.From)] = node + + // 发送离线消息 + messages := messageMgrData.MessageList[int64(data.From)] + messages.mu.Lock() + defer messages.mu.Unlock() + for _, message := range messages.Messages { + go sendMessageAsync(message, node) + } + return nil, nil +} + +func PlayerLogoutHandler(data *msg.Msg) (interface{}, error) { + messageMgrData := getMessageData() + messageMgrData.mu.Lock() + defer messageMgrData.mu.Unlock() + delete(messageMgrData.PlayerList, int64(data.From)) + log.Debug("[Middleware] Player logout success player id: %v", data.From) + return nil, nil +} + +func ComsumerMsgHandler(data *msg.Msg) (interface{}, error) { + messageMgrData := getMessageData() + Message, ok := messageMgrData.MessageList[int64(data.To)] + if !ok { + return nil, nil + } + Message.mu.Lock() + defer Message.mu.Unlock() + for i, msgItem := range Message.Messages { + if msgItem.UniKey == data.UniKey { + // 删除消息 + Message.Messages = append(Message.Messages[:i], Message.Messages[i+1:]...) + log.Debug("[Middleware] Comsume message success type: %d, player id: %v", msgItem.Type, msgItem.From) + break + } + } + return nil, nil +} + +func CenterPlayerMsgHandler(data *msg.Msg) (interface{}, error) { + PlayerId := int64(data.To) + messageMgrData := getMessageData() + // 遍历消息列表,发送消息给在线玩家 + messages, ok := messageMgrData.MessageList[int64(PlayerId)] + if !ok { + messageMgrData.mu.Lock() + messages = &MessageList{ + Messages: []*msg.Msg{}, + } + messageMgrData.MessageList[int64(PlayerId)] = messages + messageMgrData.mu.Unlock() + } + messages.mu.Lock() + defer messages.mu.Unlock() + messages.Messages = append(messages.Messages, data) + if node, ok := messageMgrData.PlayerList[int64(PlayerId)]; ok { + for _, message := range messages.Messages { + go SendMsgToNodeAsync(message, node) + } + } + return nil, nil +} + +func PlayerMsgHandler(data *msg.Msg) (interface{}, error) { + p := G_GameLogicPtr.GetPlayer(int64(data.To)) + // 不在线 不处理 + if p == nil || p.stop { + return nil, nil + } + p.lock.Lock() + defer p.lock.Unlock() + p.Send(data.Clone()) + // 处理完后发送消费消息 + if data.HandleType == msg.HANDLE_MOD_PLAYER_MSG { + data.HandleType = msg.HANDLE_MOD_COMSUME_MSG + go SendMsgToCenterAsync(data) + } + return nil, nil +} + +func PlayerReplyMsgHandler(data *msg.Msg) (interface{}, error) { + // 先处理同步回调 + if data.UniKey != "" { + if chanel, ok := mergeCluster.CallbackChan[data.UniKey]; ok { + log.Debug("reply message ") + chanel <- data + } + } + return nil, nil +} + +// 添加中间件 +func (m *MessageMgr) Use(middleware MessageMiddleware) { + m.middlewares = append(m.middlewares, middleware) +} + +// 应用所有中间件到处理函数 +func (m *MessageMgr) applyMiddlewares(handler MessageHandlerFunc) MessageHandlerFunc { + // 从后往前应用中间件 + for i := len(m.middlewares) - 1; i >= 0; i-- { + handler = m.middlewares[i](handler) + } + return handler } type MessageHandlerFunc func(message *msg.Msg) (interface{}, error) @@ -31,21 +320,311 @@ func (m *MessageMgr) RegisterMessageHandler(hType int, handler MessageHandlerFun func (m *MessageMgr) Handle(msg *msg.Msg) (interface{}, error) { if fun, ok := m.handler[msg.Type]; ok { - return fun.(MessageHandlerFunc)(msg) + return fun(msg) } log.Error("server mod key:%s handle not exist handle type:%d", m.key, msg.Type) return nil, fmt.Errorf("server mod handler err") } -func SendMessage(m1 *msg.Msg) error { - if m1.SendT == 0 { - m1.SendT = GoUtil.Now() +// 异步处理消息 (多线程版本) +func (m *MessageMgr) MessageHandleAsync(message *msg.Msg) error { + if fun, ok := m.handler[message.HandleType]; ok { + // 应用中间件 + handlerWithMiddleware := m.applyMiddlewares(fun) + + // 创建任务 + task := &MessageTask{ + Msg: message, + Handler: handlerWithMiddleware, + Result: make(chan *TaskResult, 1), + } + + // 提交到 Worker Pool + if err := m.workerPool.Submit(task); err != nil { + log.Error("Failed to submit message task: %v", err) + return err + } + + // 可以选择等待结果或直接返回 + go func() { + result := <-task.Result + if result.Error != nil { + log.Error("Message handle error: %v", result.Error) + } + }() + + return nil } - m := m1.Clone() - err := mergeCluster.SendServerMsg(m, 1) - if err != nil { // 区服不在线 - G_GameLogicPtr.FriendMgrSend(m) + log.Error("server mod key:%s handle not exist handle type:%d", m.key, message.Type) + return fmt.Errorf("server mod handler err") +} + +// 兼容旧版本的函数 +func MessageHandle(m *msg.Msg) error { + log.Debug("RecvMessage m %v", m) + // 这里可以调用 MessageMgr 的处理方法 + G_GameLogicPtr.MessageMgr.MessageHandleAsync(m) + return nil +} + +// ==================== Worker Pool 实现 ==================== + +// 创建 Worker Pool +func NewWorkerPool(workers, maxQueue int) *WorkerPool { + ctx, cancel := context.WithCancel(context.Background()) + pool := &WorkerPool{ + workers: workers, + taskQueue: make(chan *MessageTask, maxQueue), + ctx: ctx, + cancel: cancel, + maxQueue: maxQueue, + } + pool.start() + return pool +} + +// 启动 Worker Pool +func (p *WorkerPool) start() { + for i := 0; i < p.workers; i++ { + p.wg.Add(1) + go p.worker(i) + } +} + +// Worker 工作函数 +func (p *WorkerPool) worker(id int) { + defer p.wg.Done() + log.Debug("Worker %d started", id) + + for { + select { + case <-p.ctx.Done(): + log.Debug("Worker %d stopped", id) + return + case task, ok := <-p.taskQueue: + if !ok { + log.Debug("Worker %d: task queue closed", id) + return + } + // 执行任务 + result, err := task.Handler(task.Msg) + // 发送结果 + task.Result <- &TaskResult{ + Data: result, + Error: err, + } + close(task.Result) + } + } +} + +// 提交任务 +func (p *WorkerPool) Submit(task *MessageTask) error { + select { + case <-p.ctx.Done(): + return fmt.Errorf("worker pool is closed") + case p.taskQueue <- task: + return nil + default: + return fmt.Errorf("task queue is full") + } +} + +// 关闭 Worker Pool +func (p *WorkerPool) Shutdown() { + log.Debug("Shutting down worker pool...") + p.cancel() + close(p.taskQueue) + p.wg.Wait() + log.Debug("Worker pool shut down complete") +} + +// ==================== 中间件实现 ==================== + +// 日志中间件 +func LoggingMiddleware() MessageMiddleware { + return func(next MessageHandlerFunc) MessageHandlerFunc { + return func(message *msg.Msg) (interface{}, error) { + start := time.Now() + log.Debug("[Middleware] Processing message type: %d, time: %v", message.Type, start) + + result, err := next(message) + + duration := time.Since(start) + if err != nil { + log.Error("[Middleware] Message type: %d failed, duration: %v, error: %v", message.Type, duration, err) + } else { + log.Debug("[Middleware] Message type: %d success, duration: %v", message.Type, duration) + } + + return result, err + } + } +} + +// 恢复 Panic 中间件 +func RecoveryMiddleware() MessageMiddleware { + return func(next MessageHandlerFunc) MessageHandlerFunc { + return func(message *msg.Msg) (result interface{}, err error) { + defer func() { + if r := recover(); r != nil { + log.Error("[Middleware] Panic recovered: %v\nStack: %s", r, debug.Stack()) + err = fmt.Errorf("panic recovered: %v", r) + } + }() + return next(message) + } + } +} + +// 超时中间件 +func TimeoutMiddleware(timeout time.Duration) MessageMiddleware { + return func(next MessageHandlerFunc) MessageHandlerFunc { + return func(message *msg.Msg) (interface{}, error) { + resultChan := make(chan *TaskResult, 1) + + go func() { + result, err := next(message) + resultChan <- &TaskResult{Data: result, Error: err} + }() + + select { + case result := <-resultChan: + return result.Data, result.Error + case <-time.After(timeout): + log.Error("[Middleware] Message type: %d timeout after %v", message.Type, timeout) + return nil, fmt.Errorf("message handler timeout") + } + } + } +} + +// 重试中间件 +func RetryMiddleware(maxRetries int) MessageMiddleware { + return func(next MessageHandlerFunc) MessageHandlerFunc { + return func(message *msg.Msg) (interface{}, error) { + var result interface{} + var err error + + for i := 0; i <= maxRetries; i++ { + result, err = next(message) + if err == nil { + return result, nil + } + + if i < maxRetries { + log.Debug("[Middleware] Retry %d/%d for message type: %d, error: %v", i+1, maxRetries, message.Type, err) + time.Sleep(time.Millisecond * 100 * time.Duration(i+1)) + } + } + + return result, fmt.Errorf("failed after %d retries: %w", maxRetries, err) + } + } +} + +// 验证中间件 +func ValidationMiddleware() MessageMiddleware { + return func(next MessageHandlerFunc) MessageHandlerFunc { + return func(message *msg.Msg) (interface{}, error) { + // 添加消息验证逻辑 + if message == nil { + return nil, fmt.Errorf("message is nil") + } + if message.Type <= 0 { + return nil, fmt.Errorf("invalid message type: %d", message.Type) + } + + return next(message) + } + } +} + +// ----------------------------------- 发送消息相关函数 --------------------------- +func SendMsgToCenterAsync(m *msg.Msg) { + go sendMessageAsync(m, conf.Server.CenterNode) +} + +func SendMsgToCenterSync(m *msg.Msg) (*msg.Msg, error) { + return sendMessageSync(m, conf.Server.CenterNode) +} + +func SendMsgToNodeAsync(m *msg.Msg, node int) { + go sendMessageAsync(m, node) +} + +func SendMsgToNodeSync(m *msg.Msg, node int) (*msg.Msg, error) { + return sendMessageSync(m, node) +} + +func SendPlayerMsgAsync(m *msg.Msg) error { + if m.SendT == 0 { + m.SendT = GoUtil.Now() + } + clone := m.Clone() + clone.HandleType = msg.HANDLE_MOD_PLAYER_MSG + SendMsgToCenterAsync(clone) + return nil +} + +func SendPlayerMsgSync(m *msg.Msg) (interface{}, error) { + clone := m.Clone() + clone.HandleType = msg.HANDLE_MOD_PLAYER_MSG + return SendMsgToCenterSync(clone) +} + +func FriendMgrSend(m1 *msg.Msg) error { + SendPlayerMsgAsync(m1) + return nil +} + +// 异步发送消息到指定节点 节点不在线则保存消息 +func sendMessageAsync(m *msg.Msg, node int) error { + err := mergeCluster.SendServerMsg(m, node) + if err != nil { + saveMessage(m) return err } return nil } + +// 同步消息到指定节点 节点不在线则保存消息 +func sendMessageSync(m *msg.Msg, node int) (*msg.Msg, error) { + msg, err := mergeCluster.CallServerMsg(m, node) + if err != nil && conf.Server.ServerType == "center" { + saveMessage(m) + return nil, err + } + return msg, nil +} + +// 保存消息到本地 +func saveMessage(m *msg.Msg) error { + data := getMessageData() + data.mu.Lock() + defer data.mu.Unlock() + if _, ok := data.MessageList[int64(m.To)]; !ok { + data.MessageList[int64(m.To)] = &MessageList{ + Messages: []*msg.Msg{}, + } + } + data.MessageList[int64(m.To)].mu.Lock() + defer data.MessageList[int64(m.To)].mu.Unlock() + data.MessageList[int64(m.To)].Messages = append(data.MessageList[int64(m.To)].Messages, m) + return nil +} + +func GetUserData(PlayerId int64, Key string) (*msg.Msg, error) { + return SendMsgToCenterSync(&msg.Msg{ + From: int(PlayerId), + HandleType: msg.HANDLE_MOD_USER_VAR_GET, + Extra: msg.VarData{Key: Key}, + }) +} + +// func GetServerData(Key string) (*msg.Msg, error) { +// return SendMsgToCenterSync(&msg.Msg{ +// HandleType: msg.HANDLE_MOD_VAR_GET, +// Extra: msg.VarData{Key: Key}, +// }) +// } diff --git a/src/server/game/mod/friend/Friend.go b/src/server/game/mod/friend/Friend.go index fe69b2a6..2bb2c8f5 100644 --- a/src/server/game/mod/friend/Friend.go +++ b/src/server/game/mod/friend/Friend.go @@ -219,6 +219,11 @@ func (f *FriendMod) SetNpc(id int) error { if !friendCfg.IsNpcFriend(id) { return fmt.Errorf("not npc friend") } + for _, v := range f.Npc { + if v == id { + return fmt.Errorf("npc already exist") + } + } f.Npc = append(f.Npc, id) return nil } diff --git a/src/server/game/mod/msg/Msg.go b/src/server/game/mod/msg/Msg.go index c8592553..02c7077b 100644 --- a/src/server/game/mod/msg/Msg.go +++ b/src/server/game/mod/msg/Msg.go @@ -16,9 +16,40 @@ type Msg struct { HandleType int //处理类型 } +type VarData struct { + Key string + Value interface{} + SetType int // 操作类型 0 设置 1 增加 2 减少 3 覆盖 +} + +const ( + VAR_OP_ADD = 1 + VAR_OP_SUB = 2 + VAR_OP_SET = 3 +) + var MSG_ZERO_UPDATE = &Msg{Type: SERVER_ZERO_UPDATE} var MSG_NOON_UPDATE = &Msg{Type: SERVER_NOON_UPDATE} +const ( + HANDLE_MOD_PLAYER_MSG = 20001 // 玩家消息 + HANDLE_MOD_CLUSTER_MSG = 20002 // 集群消息 + HANDLE_MOD_PLAYER_LOGIN = 20003 // 玩家登录消息 + HANDLE_MOD_COMSUME_MSG = 20004 // 消费消息 + HANDLE_MOD_CLUSTER_SYNC = 20005 // 集群同步消息 + HANDLE_MDO_PLAYER_LOGOUT = 20006 // 玩家登出消息 + HANDLE_MOD_VAR_GET = 20007 // 获取变量 + HANDLE_MOD_VAR_SET = 20008 // 设置变量 + HANDLE_MOD_CATNIP_PARTNER = 20009 // 猫薄荷伙伴 + HANDLE_MOD_USER_VAR_GET = 20010 // 获取玩家变量 + HANDLE_MOD_USER_VAR_SET = 20011 // 设置玩家变量 + HANDLE_MOD_REPLY_PLAYER_MSG = 20012 // 回复玩家消息 + HANDLE_MDO_CHAMPSHIP_INRANK = 20013 // 锦标赛入榜 + HANDLE_MOD_CHAMPSHIP_RANK_INFO = 20014 // 锦标赛排名信息 + HANDLE_MOD_CHAMPSHIP_RANK_LIST = 20015 // 锦标赛排行榜 + HANDLE_MOD_CHAMPSHIP_PRE_RANK = 20016 // 锦标赛上期排名 +) + const ( //好友操作 HANDLE_TYPE_APPLY = iota //申请好友 @@ -114,6 +145,8 @@ const ( HANDLE_TYPE_SET_CATNIP_PARTNER // 设置猫薄荷伙伴 HANDLE_TYPE_CATNIP_SEND_EMOJI // 发送猫薄荷表情 HANDLE_TYPE_CHAMPSHIP_MY_RANK // 锦标赛我的排名 + + HANDLE_TYPE_LOGIN // 玩家登录处理 ) const ( @@ -141,6 +174,21 @@ func (m *Msg) Clone() *Msg { } } +func (m *Msg) Reply(data interface{}) *Msg { + return &Msg{ + Type: m.Type, + To: m.From, + Item: m.Item, + SendT: m.SendT, + End: m.End, + Extra: data, + Id: m.Id, + H: m.H, + UniKey: m.UniKey, + HandleType: HANDLE_MOD_REPLY_PLAYER_MSG, + } +} + func Handle(fun func(Msg) error, m Msg) error { return fun(m) } diff --git a/src/server/game/player_back.go b/src/server/game/player_back.go index 839b5b31..6cf5c34b 100644 --- a/src/server/game/player_back.go +++ b/src/server/game/player_back.go @@ -5,6 +5,7 @@ import ( playroomCfg "server/conf/playroom" "server/game/mod/item" limitedTimeEvent "server/game/mod/limited_time_event" + "server/game/mod/msg" GoUtil "server/game_util" proto "server/msg" ) @@ -113,7 +114,6 @@ func (p *Player) PlayroomBackData() { ItemId: int32(k), }) } - data := G_GameLogicPtr.GetUserData(int(p.M_DwUin)) r.Dress = Dress r.DressSet = GoUtil.MapIntToInt32(PlayroomMod.GetDressSet()) @@ -156,7 +156,7 @@ func (p *Player) PlayroomBackData() { r.Unlock = PlayroomMod.GetUnlockIds() r.DailyTaskReward = GoUtil.IntToInt32(PlayroomMod.DailyTaskReward) r.DailyTask = PlayroomMod.BackDataTask() - r.Kiss = int32(data.Kiss) + r.Kiss = int32(p.GetPlayroomKiss()) r.Revenge = PlayroomMod.RevengeUid r.InteractNum = int32(PlayroomMod.InteractNum) r.AdItem = AdWatch @@ -195,18 +195,16 @@ func (p *Player) PlayroomVisit(Uid int) { r.Upvote = GoUtil.InArray(Uid, PlayroomMod.UpvoteList) r.Items = Items r.Status = int32(PlayroomMod.GameStatus) - data := G_GameLogicPtr.GetUserData(Uid) - r.UpvoteCount = int32(data.Upvote) - r.Chip = int32(data.Chip) - r.Kiss = int32(data.Kiss) + r.UpvoteCount = int32(p.GetPlayroomUpvote()) + r.Chip = int32(p.GetPlayroomChip()) + r.Kiss = int32(p.GetPlayroomKiss()) r.DressSet = GoUtil.MapIntToInt32(PlayerData.DressSet) p.PushClientRes(r) } func (p *Player) NotifyPlayroomKiss() { - data := G_GameLogicPtr.GetUserData(int(p.M_DwUin)) m := &proto.NotifyPlayroomKiss{ - Kiss: int32(data.Kiss), + Kiss: int32(p.GetPlayroomKiss()), } p.PushClientRes(m) } @@ -297,8 +295,16 @@ func (p *Player) ChargeBackData() { func (p *Player) BackChampship() { ChampshipMod := p.PlayMod.getChampshipMod() - MyRank := G_GameLogicPtr.ChampshipMgr.getMyRank(int(p.M_DwUin)) - MyPreRank := G_GameLogicPtr.ChampshipMgr.getLastMyRank(int(p.M_DwUin)) + MyRank := 0 + MyPreRank := 0 + res, _ := SendMsgToCenterSync(&msg.Msg{ + From: int(p.M_DwUin), + HandleType: msg.HANDLE_MOD_CHAMPSHIP_RANK_INFO, + }) + if res != nil { + MyRank = res.Extra.([]int)[0] + MyPreRank = res.Extra.([]int)[1] + } p.PushClientRes(ChampshipMod.BackData(MyRank, MyPreRank)) } diff --git a/src/server/game/player_base_mod.go b/src/server/game/player_base_mod.go index bc236c2a..ce9ed427 100644 --- a/src/server/game/player_base_mod.go +++ b/src/server/game/player_base_mod.go @@ -43,7 +43,7 @@ func (p *PlayerBaseData) BackUp() msg.ResPlayerBaseInfo { Guild: p.Data.Guild, PackUnlockCount: p.Data.PackUnlockCount, LastPlayTime: p.Data.LastPlayTime, - EnergyBuyCount: p.Data.EnergyBuyCount, + Ban: p.Data.Ban, LoginTime: p.Data.LoginTime, UserName: p.Data.UserName, LogoutTime: p.Data.LogoutTime, @@ -70,7 +70,7 @@ func (p *PlayerBaseData) Recover(old *PlayerBaseData) *PlayerBaseData { Guild: p.Data.Guild, PackUnlockCount: p.Data.PackUnlockCount, LastPlayTime: p.Data.LastPlayTime, - EnergyBuyCount: p.Data.EnergyBuyCount, + Ban: p.Data.Ban, LoginTime: p.Data.LoginTime, UserName: p.Data.UserName, LogoutTime: p.Data.LogoutTime, @@ -104,7 +104,7 @@ func (p *PlayerBaseData) LoadDataFromDB(UserName interface{}) bool { p.Data.Guild = sqlStruck.Guild p.Data.PackUnlockCount = sqlStruck.PackUnlockCount p.Data.LastPlayTime = sqlStruck.LastPlayTime - p.Data.EnergyBuyCount = sqlStruck.EnergyBuyCount + p.Data.Ban = sqlStruck.Ban p.Data.UserName = sqlStruck.UserName p.Data.LogoutTime = sqlStruck.LogoutTime p.Data.Todayolinetime = sqlStruck.Todayolinetime @@ -132,7 +132,7 @@ func (p *PlayerBaseData) SaveDataFromDB(Key interface{}) bool { sqlStruck.Guild = p.Data.Guild sqlStruck.PackUnlockCount = p.Data.PackUnlockCount sqlStruck.LastPlayTime = p.Data.LastPlayTime - sqlStruck.EnergyBuyCount = p.Data.EnergyBuyCount + sqlStruck.Ban = int64(p.Data.Ban) sqlStruck.LoginTime = int32(BaseMod.LoginTime) sqlStruck.UserName = p.Data.UserName sqlStruck.LogoutTime = int32(BaseMod.LogoutTime) @@ -163,22 +163,6 @@ func (p *PlayerBaseData) GetMaxEnergy() int { } // 更新游戏道具 -func (p *PlayerBaseData) UpdateBaseItemInfo(update *msg.UpdateBaseItemInfo) { - for k, v := range update.MUpdateItem { - switch k { - case 4: - p.Data.EnergyBuyCount = v - case 8: - p.Data.Guild = v - case 9: - p.Data.PackUnlockCount = v - case 10: - p.Data.EmitOrderCnt = v - case 11: - p.Data.LastPlayTime = v - } - } -} func (p *PlayerBaseData) ReqRemoveAd(player *Player, buf []byte) { req := &msg.ReqRemoveAd{} @@ -654,7 +638,7 @@ func (p *PlayerBaseData) GetDataByUid(Uid interface{}) bool { p.Data.Guild = sqlStruck.Guild p.Data.PackUnlockCount = sqlStruck.PackUnlockCount p.Data.LastPlayTime = sqlStruck.LastPlayTime - p.Data.EnergyBuyCount = sqlStruck.EnergyBuyCount + p.Data.Ban = sqlStruck.Ban p.Data.LoginTime = sqlStruck.LoginTime p.Data.UserName = sqlStruck.UserName p.Data.LogoutTime = sqlStruck.LogoutTime diff --git a/src/server/game/player_data.go b/src/server/game/player_data.go index aa6b369b..28cc71c8 100644 --- a/src/server/game/player_data.go +++ b/src/server/game/player_data.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "math" + "server/conf" activityCfg "server/conf/activity" cardCfg "server/conf/card" chargeCfg "server/conf/charge" @@ -101,12 +102,13 @@ func (p *Player) CallEvent(Duration time.Duration, F func(), Label string) { } // 异步请求 -func (p *Player) Send(m *MsgMod.Msg) { +func (p *Player) Send(m *MsgMod.Msg) error { if m == nil { - return + return nil } p.wg.Add(1) p.msgChan <- m + return nil } func (p *Player) Call(m MsgMod.Msg) { @@ -252,7 +254,6 @@ func (p *Player) InitPlayer(UserName string) error { p.NoonUpdate(nil) p.Login() p.OrderShip() - p.SyncFriendMsg() p.UpdateUserInfo() // fix bug ChargeMod := p.PlayMod.getChargeMod() @@ -451,11 +452,16 @@ func (p *Player) ClearData() { log.Debug("ClearData BeginTx failed:", err) return } + Uid := int(p.M_DwUin) p.PlayerBaseMod.ClearData() p.PlayMod.ClearData(p) tx.Commit() p.Stop() G_GameLogicPtr.DelPlayer(p) + SendMsgToCenterAsync(&MsgMod.Msg{ + From: Uid, + HandleType: MsgMod.HANDLE_MDO_PLAYER_LOGOUT, + }) } func (p *Player) AutoSaveData() { @@ -863,6 +869,11 @@ func (p *Player) HandleItem(itemList []*item.Item, Label string) error { // 登录返回数据 func (p *Player) LoginBackData() { + SendMsgToCenterAsync(&MsgMod.Msg{ + From: int(p.M_DwUin), + HandleType: MsgMod.HANDLE_MOD_PLAYER_LOGIN, + Extra: conf.Server.ServerID, + }) p.PushClientRes(p.PlayMod.mod_list.Base.BackData()) p.PushClientRes(p.PlayMod.mod_list.Handbook.BackData()) p.PushClientRes(p.PlayMod.mod_list.Base.BackData()) @@ -975,7 +986,7 @@ func (p *Player) UpdateUserInfo() { //TODO 存储到redis 在新版本中将优化成gob进行压缩 value, _ := json.Marshal(simple) - IdStr := strconv.Itoa(int(p.M_DwUin)) + IdStr := GoUtil.String(p.M_DwUin) go db.RedisSetKeyBytes(IdStr, value, 0) } @@ -1013,8 +1024,9 @@ func (p *Player) HandleInChampshipRank() { H: ChampshipMod.GetH(), N: ChampshipMod.GetN(), }, + HandleType: MsgMod.HANDLE_MDO_CHAMPSHIP_INRANK, } - G_GameLogicPtr.ChampshipMgrSend(m) + SendMsgToCenterAsync(m) } func (p *Player) AddLog(Uid int, Type int, Param string, Time int64) { diff --git a/src/server/game/register_network_func.go b/src/server/game/register_network_func.go index 30b48549..4f1c0e49 100644 --- a/src/server/game/register_network_func.go +++ b/src/server/game/register_network_func.go @@ -119,17 +119,6 @@ func ReqRemoveAdFunc(player *Player, buf []byte) error { return nil } -// 更新玩家物品 -func UpdateBaseItemInfofunction(player *Player, buf []byte) error { - detail := &msg.UpdateBaseItemInfo{} - err := proto.Unmarshal(buf, detail) - if err != nil { - return err - } - player.PlayerBaseMod.UpdateBaseItemInfo(detail) - return nil -} - // 请求玩家棋盘信息 func ReqPlayerChessDataFunc(player *Player, buf []byte) error { detail := &msg.ReqPlayerChessData{} @@ -1785,15 +1774,14 @@ func ReqLimitSenceReward(player *Player, buf []byte) error { } func ReqGetGoldCard(player *Player, buf []byte) error { - data := G_GameLogicPtr.VarMgr.GetVar(VAR_GOLD_CARD) - if data == nil { + gold := player.GetGoldCard() + if gold == nil { player.SendErrClienRes(&msg.ResGetGoldCard{ Four: 0, Five: 0, }) return fmt.Errorf("not exist") } - gold := data.(*VarGoldCard) player.PushClientRes(&msg.ResGetGoldCard{ Four: int32(gold.Four), Five: int32(gold.Five), @@ -1870,13 +1858,13 @@ func ReqApplyFriend(player *Player, buf []byte) error { }) return fmt.Errorf("already friend") } - if FriendMod.AddSendApply(Uid) { - player.SendErrClienRes(&msg.ResApplyFriend{ - Code: msg.RES_CODE_FAIL, - Msg: "already apply", - }) - return fmt.Errorf("already apply") - } + // if FriendMod.AddSendApply(Uid) { + // player.SendErrClienRes(&msg.ResApplyFriend{ + // Code: msg.RES_CODE_FAIL, + // Msg: "already apply", + // }) + // return fmt.Errorf("already apply") + // } if req.Type == 1 { Items, err := FriendMod.GetSponsorReward() if err != nil { @@ -2576,7 +2564,18 @@ func ReqChampshipRank(player *Player, buf []byte) error { if err != nil { return err } - m := G_GameLogicPtr.ChampshipMgr.GetRankMsg(int(player.M_DwUin)) + res, err := SendMsgToCenterSync(&MsqMod.Msg{ + From: int(player.M_DwUin), + HandleType: MsqMod.HANDLE_MOD_CHAMPSHIP_RANK_LIST, + }) + if err != nil { + return err + } + if res == nil { + player.PushClientRes(&msg.ResChampshipRank{}) + return nil + } + m := res.Extra.(*msg.ResChampshipRank) player.PushClientRes(m) return nil } @@ -2587,7 +2586,18 @@ func ReqChampshipPreRank(player *Player, buf []byte) error { if err != nil { return err } - m := G_GameLogicPtr.ChampshipMgr.GetPreRankMsg(int(player.M_DwUin)) + res, err := SendMsgToCenterSync(&MsqMod.Msg{ + From: int(player.M_DwUin), + HandleType: MsqMod.HANDLE_MOD_CHAMPSHIP_PRE_RANK, + }) + if err != nil { + return err + } + if res == nil { + player.PushClientRes(&msg.ResChampshipPreRank{}) + return nil + } + m := res.Extra.(*msg.ResChampshipPreRank) player.PushClientRes(m) return nil } @@ -3279,7 +3289,7 @@ func ReqSelfInvited(player *Player, buf []byte) error { if err != nil { return err } - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ Type: MsqMod.HANDLE_TYPE_INVITE_FRIEND, From: int(player.M_DwUin), To: int(req.InviterId), @@ -3346,7 +3356,7 @@ func ReqAutoAddInviteFriend(player *Player, buf []byte) error { player.PushClientRes(&msg.ResAutoAddInviteFriend{ ResultCode: 1, }) - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ From: int(player.M_DwUin), To: Uid, Type: MsqMod.HANDLE_TYPE_INVITE_ADD_FRIEND, @@ -3390,7 +3400,7 @@ func ReqAutoAddInviteFriend2(player *Player, buf []byte) error { player.PushClientRes(&msg.ResAutoAddInviteFriend2{ ResultCode: 1, }) - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ From: int(player.M_DwUin), To: Uid, Type: MsqMod.HANDLE_TYPE_INVITE_ADD_FRIEND, @@ -3790,7 +3800,7 @@ func ReqPlayroomInteract(player *Player, buf []byte) error { return err } if GoUtil.InArray(int(req.Id), playroomCfg.GetInteractIdBath()) { - G_GameLogicPtr.SetUserData(int(req.Id), VAR_OP_KISS, 0) + player.SetPlayroomKiss(0) } PExp := playroomCfg.GetInteractPExp(int(req.Id)) _, err = player.GetPlayerBaseMod().AddExp(player, 0, PExp) @@ -3804,7 +3814,6 @@ func ReqPlayroomInteract(player *Player, buf []byte) error { PlayroomMod.AddInteractNum(BaseMod.GetLevel()) player.QuestTrigger(&quest.Trigger{Label: quest.TRIGGER_LABEL_INTERACT, A: []interface{}{int(req.Id)}}) player.PlayMod.save() - G_GameLogicPtr.SetUserData(int(player.M_DwUin), VAR_OP_KISS, 0) player.LimitedTimePlayroomTrigger_(PType) player.NotifyPlayroomKiss() player.TeLog("playroom_interact", map[string]interface{}{ @@ -3868,7 +3877,7 @@ func ReqPlayroomGame(player *Player, buf []byte) error { }) return err } - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ From: int(player.M_DwUin), To: Target, Type: MsqMod.HANDLE_TYPE_PLAYROOM_GAME, @@ -3928,7 +3937,7 @@ func ReqPlayroomSelectReward(player *Player, buf []byte) error { }) return fmt.Errorf("no game or target") } - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ From: int(player.M_DwUin), To: Target, Type: MsqMod.HANDLE_TYPE_PLAYROOM_LOSE, @@ -3943,7 +3952,7 @@ func ReqPlayroomSelectReward(player *Player, buf []byte) error { if LimitedTimeEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_PET_THIEF) { player.GetPetThiefReward(Target) } - G_GameLogicPtr.SetUserData(Target, VAR_OP_CHIP, 1) + player.AddPlayroomChip(int(req.Id)) player.TeLog("finish_mini_game", map[string]interface{}{ "mini_game_type": PlayroomMod.GetGameId(), "is_chip": true, @@ -4083,8 +4092,9 @@ func ReqPlayroomChip(player *Player, buf []byte) error { player.TeLog("remove_chip", map[string]interface{}{ "remove_chip_number": ChipNum, }) - - G_GameLogicPtr.SetUserData(int(player.M_DwUin), VAR_OP_CHIP_SET, len(PlayroomMod.ChipList)) + for range ChipNum { + player.SubPlayroomChip(int(player.M_DwUin)) + } player.PlayMod.save() player.PlayroomBackData() player.PushClientRes(&msg.ResPlayroomChip{ @@ -4156,7 +4166,7 @@ func ReqPlayroomFlipReward(player *Player, buf []byte) error { }) return err } - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ From: int(player.M_DwUin), To: Target, Type: MsqMod.HANDLE_TYPE_PLAYROOM_LOSE, @@ -4258,8 +4268,8 @@ func ReqPlayroomUpvote(player *Player, buf []byte) error { Type: MsqMod.HANDLE_TYPE_PLAYROOM_KISS, SendT: GoUtil.Now(), }) - G_GameLogicPtr.SetUserData(int(req.Id), VAR_OP_UPVOTE, 1) - G_GameLogicPtr.SetUserData(int(req.Id), VAR_OP_KISS, 1) + player.AddPlayroomUpvote(int(req.Id)) + player.SetPlayroomKiss(1) player.TeLog("visit_like", map[string]interface{}{ "user_id": req.Id, }) @@ -4621,7 +4631,7 @@ func ReqFriendTreasureEnd(player *Player, buf []byte) error { if v.Status == 1 { ItemNum = FriendItemNum } - G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{ + FriendMgrSend(&MsqMod.Msg{ From: int(player.M_DwUin), To: int(v.Uid), Type: MsqMod.FRIEND_TREASURE_HANDLE, @@ -5449,7 +5459,7 @@ func ReqCatnipAgree(player *Player, buf []byte) error { }) return err } - err = G_GameLogicPtr.SetCatnipPartner(int(player.M_DwUin), int(req.Id), int(req.Uid), ActivityInfo.EndT) + err = player.SetCatnipPartner(int(req.Id), int(req.Uid), ActivityInfo.EndT) if err != nil { player.SendErrClienRes(&msg.ResCatnipAgree{ Code: msg.RES_CODE_FAIL, @@ -5769,7 +5779,7 @@ func ReqFriendReplyHandle(player *Player, buf []byte) error { case friend.REPLY_TYPE_CATNIP: // 猫草大作战同意邀请 GameId := GoUtil.Int(ReplyInfo.Param) activityInfo := player.GetActivityInfo(player.GetActivityId(activity.ACT_TYPE_CATNIP)) - err := G_GameLogicPtr.SetCatnipPartner(int(player.M_DwUin), GameId, ReplyInfo.Uid, activityInfo.EndT) + err := player.SetCatnipPartner(GameId, ReplyInfo.Uid, activityInfo.EndT) if err == nil { CatnipMod := player.PlayMod.getCatnipMod() ActivityId := player.GetActivityId(activity.ACT_TYPE_MINING) diff --git a/src/server/game/var.go b/src/server/game/var.go new file mode 100644 index 00000000..72b51563 --- /dev/null +++ b/src/server/game/var.go @@ -0,0 +1,182 @@ +package game + +import ( + "fmt" + "server/db" + "server/game/mod/msg" + GoUtil "server/game_util" + "server/pkg/github.com/name5566/leaf/log" +) + +const ( + VAR_KEY_FRIEND_MSG = "friend_msg" // 好友消息 + VAR_GOLD_CARD = "gold_card" + VAR_PLAYROOM_UPVOTE = "playroom_upvote" + VAR_PLAYROOM_CHIP = "playroom_chip" + VAR_PLAYROOM_KISS = "playroom_kiss" + VAR_USER_DATA = "user_data" + VAR_CATNIP_PARTNER = "catnip_partner" +) + +func (p *Player) GetVarData(key string) interface{} { + cache := &VarExpireData{} + err := LoadCacheVarData(key, cache) + if err != nil { + log.Error("GetVarData err : %s, key: %s", err, key) + return nil + } + return cache.D +} + +func (p *Player) GetUserVarData(key string) interface{} { + cache := map[string]*VarExpireData{} + err := LoadCacheVarData(GoUtil.GetVarKey(int(p.M_DwUin)), &cache) + if err != nil { + log.Error("GetUserVarData err : %s, key: %s", err, key) + return nil + } + data, ok := cache[key] + if !ok { + return nil + } + return data.D +} + +// func GetServerVarData(key string) interface{} { +// data, err := GetServerData(key) +// if err != nil { +// log.Error("GetServerVarData err : %s", err) +// return nil +// } +// return data.Extra +// } + +func (p *Player) OpVarDataAsync(key string, value interface{}, opType int) { + SendMsgToCenterAsync(&msg.Msg{ + From: int(p.M_DwUin), + HandleType: msg.HANDLE_MOD_USER_VAR_SET, + Extra: msg.VarData{ + Key: key, + Value: value, + SetType: opType, + }, + }) +} + +func (p *Player) OpVarDataSync(key string, value interface{}, opType int) (*msg.Msg, error) { + return SendMsgToCenterSync(&msg.Msg{ + From: int(p.M_DwUin), + HandleType: msg.HANDLE_MOD_USER_VAR_SET, + Extra: msg.VarData{ + Key: key, + Value: value, + SetType: opType, + }, + }) +} + +func (p *Player) OpServerVarDataAsync(key string, Value interface{}, opType int) { + SendMsgToCenterSync(&msg.Msg{ + HandleType: msg.HANDLE_MOD_VAR_SET, + Extra: msg.VarData{Key: key, Value: Value, SetType: opType}, + }) +} + +func (p *Player) OpServerVarDataSync(key string, Value interface{}, opType int) (*msg.Msg, error) { + return SendMsgToCenterSync(&msg.Msg{ + HandleType: msg.HANDLE_MOD_VAR_SET, + Extra: msg.VarData{Key: key, Value: Value, SetType: opType}, + }) +} + +func (p *Player) SetVarDataAsync(key string, value interface{}) { + p.OpVarDataAsync(key, value, msg.VAR_OP_SET) +} + +func (p *Player) AddVarDataAsync(key string) { + p.OpVarDataAsync(key, nil, msg.VAR_OP_ADD) +} + +func (p *Player) SubVarDataAsync(key string) { + p.OpVarDataAsync(key, nil, msg.VAR_OP_SUB) +} + +func (p *Player) AddPlayroomUpvote(PlayerId int) { + p.AddVarDataAsync(VAR_PLAYROOM_UPVOTE) +} + +func (p *Player) AddPlayroomChip(PlayerId int) { + p.AddVarDataAsync(VAR_PLAYROOM_CHIP) +} + +func (p *Player) SubPlayroomChip(PlayerId int) { + p.SubVarDataAsync(VAR_PLAYROOM_CHIP) +} + +func (p *Player) GetPlayroomUpvote() int { + data := p.GetUserVarData(VAR_PLAYROOM_UPVOTE) + if data == nil { + return 0 + } + return data.(int) +} + +func (p *Player) GetPlayroomChip() int { + data := p.GetUserVarData(VAR_PLAYROOM_CHIP) + if data == nil { + return 0 + } + return data.(int) +} + +func (p *Player) SetPlayroomKiss(Kiss int) { + p.SetVarDataAsync(VAR_PLAYROOM_KISS, Kiss) +} + +func (p *Player) GetPlayroomKiss() int { + data := p.GetUserVarData(VAR_PLAYROOM_KISS) + if data == nil { + return 0 + } + return data.(int) +} + +func (p *Player) GetGoldCard() *VarGoldCard { + data := p.GetVarData(VAR_GOLD_CARD) + if data == nil { + return &VarGoldCard{} + } + return data.(*VarGoldCard) +} + +func (p *Player) GetCatnipPartner(Uid int) []int { + data, err := GetUserData(p.M_DwUin, VAR_CATNIP_PARTNER) + if err != nil { + log.Error("GetVarData err : %s", err) + return nil + } + if data == nil { + return nil + } + return GoUtil.IntSlice(data.Extra) +} + +func SaveCacheVarData(key string, value interface{}) { + data, err := GoUtil.GobMarshal(value) + if err != nil { + log.Error("SaveCacheVarData GobMarshal err : %s", err) + return + } + db.RedisSetKeyBytes(key, data, 0) +} + +func LoadCacheVarData(key string, value interface{}) error { + data, err := db.RedisGetKeyBytes(key) + if err != nil { + return err + } + if data == nil { + return fmt.Errorf("no data") + } + return GoUtil.GobUnmarshal(data, value) +} diff --git a/src/server/game/var_mgr.go b/src/server/game/var_mgr.go index a228b5fd..e2d2b309 100644 --- a/src/server/game/var_mgr.go +++ b/src/server/game/var_mgr.go @@ -6,6 +6,8 @@ import ( "server/game/mod/card" "server/game/mod/msg" GoUtil "server/game_util" + "strings" + "sync" "time" ) @@ -17,14 +19,13 @@ type VarData struct { Var map[string]interface{} VarExpire map[string]*VarExpireData UserVar map[string]*VarUserData - ZeroTime int64 -} -const ( - VAR_GOLD_CARD = "gold_card" - VAR_PLAYROOM_UPVOTE = "playroom_upvote" - VAR_USER_DATA = "user_data" -) + NewVar map[string]*VarExpireData + NewUseVar map[int]map[string]*VarExpireData + ZeroTime int64 + Version int64 + mu sync.Mutex +} const ( VAR_OP_UPVOTE = 1 @@ -36,14 +37,18 @@ const ( func (f *VarMgr) Init() { gob.Register(&VarGoldCard{}) + gob.Register(&VarExpireData{}) f.key = VAR_MGR_KEY f.data = &VarData{ - Var: map[string]interface{}{}, + NewVar: map[string]*VarExpireData{}, + NewUseVar: map[int]map[string]*VarExpireData{}, } // 注册处理函数 f.init() - if f.data.(*VarData).Var == nil { - f.data.(*VarData).Var = make(map[string]interface{}) + // 版本更新 重构 + f.version() + if f.data.(*VarData).NewVar == nil { + f.data.(*VarData).NewVar = make(map[string]*VarExpireData) } if f.data.(*VarData).UserVar == nil { f.data.(*VarData).UserVar = make(map[string]*VarUserData) @@ -52,23 +57,37 @@ func (f *VarMgr) Init() { f.data.(*VarData).VarExpire = make(map[string]*VarExpireData) } if f.getData().ZeroTime == GoUtil.ZeroTimestamp() { - f.ZeroUpdate(&msg.Msg{}) + f.ZeroUpdate() } - f.RegisterHandler(msg.SERVER_ZERO_UPDATE, f.ZeroUpdate) - f.RegisterHandler(msg.HANDLE_TYPE_SET_CATNIP_PARTNER, f.SetCatnipPartner) f.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() { - f.Send(&msg.Msg{ - Type: msg.SERVER_ZERO_UPDATE, - }) + f.ZeroUpdate() }) } -func (f *VarMgr) SetGlobalData(m *msg.Msg) (interface{}, error) { - return nil, nil +func (f *VarMgr) version() { + switch v := f.getData().Version; v { + case 0: + // future version update + data := f.getData() + data.mu.Lock() + defer data.mu.Unlock() + // set to next version + for k, v := range data.UserVar { + if v != nil { + uidStr := strings.Split(k, "_")[2] + uid := GoUtil.Int(uidStr) + f.SetUserVar(uid, VAR_PLAYROOM_UPVOTE, v.Upvote) + f.SetUserVar(uid, VAR_PLAYROOM_CHIP, v.Chip) + f.SetUserVar(uid, VAR_PLAYROOM_KISS, v.Kiss) + delete(data.UserVar, k) + } + } + f.getData().Version = 1 + } } -func (f *VarMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) { +func (f *VarMgr) ZeroUpdate() { f.getData().ZeroTime = GoUtil.ZeroTimestamp() // 随机生成两个金卡 Card1, Card2 := card.RankGoldCard() @@ -76,72 +95,82 @@ func (f *VarMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) { Four: Card1, Five: Card2, }) - for k, v := range f.getData().VarExpire { + for k, v := range f.getData().NewVar { if v.T < GoUtil.ZeroTimestamp() { - delete(f.getData().VarExpire, k) + delete(f.getData().Var, k) } } + f.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() { + f.ZeroUpdate() + }) +} + +func (f *VarMgr) HandleCatnipPartner(Uid, Partner, GameId int, EndTime int64) (interface{}, error) { + data := f.getData() + data.mu.Lock() + defer data.mu.Unlock() + + OtherPartnerInfo := f.GetUserVar(Uid, VAR_CATNIP_PARTNER) + MyPartnerInfo := f.GetUserVar(Partner, VAR_CATNIP_PARTNER) + MyOfPartnerList := GoUtil.IntSlice(MyPartnerInfo.D) + OtherOfPartnerList := GoUtil.IntSlice(OtherPartnerInfo.D) + if len(MyOfPartnerList) > 4 || len(OtherOfPartnerList) > 4 { + return nil, fmt.Errorf("catnip partner already full for uid %d in game %d", Partner, GameId) + } + f.SetUserVar(Partner, VAR_CATNIP_PARTNER, &VarExpireData{ + D: append(OtherOfPartnerList, Uid), + T: EndTime, + }) + f.SetUserVar(Uid, VAR_CATNIP_PARTNER, &VarExpireData{ + D: append(MyOfPartnerList, Partner), + T: EndTime, + }) return nil, nil } -func (f *VarMgr) SetCatnipPartner(m *msg.Msg) (interface{}, error) { - if Param, ok := m.Extra.(map[string]interface{}); ok { - MyUid := GoUtil.Int(Param["uid"]) - CatnipGameId := GoUtil.Int(Param["game_id"]) - CatnipPartnerId := GoUtil.Int(Param["partner_uid"]) - myKey := fmt.Sprintf("catnip_partner_%d", MyUid) - key := fmt.Sprintf("catnip_partner_%d", CatnipPartnerId) - OtherPartnerInfo := f.GetExpireVar(key) - MyPartnerInfo := f.GetExpireVar(myKey) - MyOfPartnerList := GoUtil.IntSlice(MyPartnerInfo.D) - OtherOfPartnerList := GoUtil.IntSlice(OtherPartnerInfo.D) - if len(MyOfPartnerList) > 4 || len(OtherOfPartnerList) > 4 { - return nil, fmt.Errorf("catnip partner already full for uid %d in game %d", CatnipPartnerId, CatnipGameId) - } - f.SetExpireVar(key, &VarExpireData{ - D: append(OtherOfPartnerList, MyUid), - T: m.End, - }) - f.SetExpireVar(myKey, &VarExpireData{ - D: append(MyOfPartnerList, CatnipPartnerId), - T: m.End, - }) - return nil, nil +func (f *VarMgr) SetUserVar(uid int, key string, value interface{}) { + varData := f.getData().NewUseVar[uid] + if varData == nil { + varData = make(map[string]*VarExpireData) + f.getData().NewUseVar[uid] = varData } - return nil, fmt.Errorf("invalid parameters for setting catnip partner") + ved, ok := varData[key] + if !ok { + ved = &VarExpireData{} + } + ved.D = value + varData[key] = ved + f.getData().NewUseVar[uid] = varData + SaveCacheVarData(GoUtil.GetVarKey(uid), varData) +} + +func (f *VarMgr) GetUserVar(uid int, key string) *VarExpireData { + varData := f.getData().NewUseVar[uid] + if varData == nil { + varData = make(map[string]*VarExpireData) + f.getData().NewUseVar[uid] = varData + } + ved, ok := varData[key] + if !ok { + ved = &VarExpireData{} + varData[key] = ved + } + return ved } func (f *VarMgr) SetVar(key string, value interface{}) { - f.getData().Var[key] = value + f.getData().NewVar[key] = &VarExpireData{ + D: value, + } + SaveCacheVarData(key, f.getData().NewVar[key]) } -func (f *VarMgr) GetVar(key string) interface{} { - return f.getData().Var[key] -} - -func (f *VarMgr) SetExpireVar(key string, value *VarExpireData) { - f.getData().VarExpire[key] = value -} - -func (f *VarMgr) GetExpireVar(key string) *VarExpireData { - if v, ok := f.getData().VarExpire[key]; ok { +func (f *VarMgr) GetVar(key string) *VarExpireData { + if v, ok := f.getData().NewVar[key]; ok { return v } data := &VarExpireData{} - f.getData().VarExpire[key] = data - return data -} - -func (f *VarMgr) SetUserVar(key string, value *VarUserData) { - f.getData().UserVar[key] = value -} - -func (f *VarMgr) GetUserVar(key string) *VarUserData { - if v, ok := f.getData().UserVar[key]; ok { - return v - } - data := &VarUserData{} - f.getData().UserVar[key] = data + f.getData().NewVar[key] = data return data } @@ -152,3 +181,121 @@ func (f *VarMgr) DelVar(key string) { func (f *VarMgr) getData() *VarData { return f.data.(*VarData) } + +func getVarData() *VarData { + return G_GameLogicPtr.VarMgr.getData() +} + +func SetVarDataHandler(m *msg.Msg) (interface{}, error) { + data := getVarData() + data.mu.Lock() + defer data.mu.Unlock() + if v, ok := m.Extra.(msg.VarData); ok { + ved, ok := data.NewVar[v.Key] + if !ok { + ved = &VarExpireData{} + } + switch v.SetType { + case msg.VAR_OP_SET: + ved.D = v.Value + case msg.VAR_OP_ADD: + if num, ok := ved.D.(int); ok { + ved.D = num + 1 + } else { + ved.D = 1 + } + case msg.VAR_OP_SUB: + if num, ok := ved.D.(int); ok { + if num > 0 { + ved.D = num - 1 + } else { + ved.D = 0 + } + } else { + ved.D = 0 + } + } + ved.U = time.Now().Unix() + if m.End > 0 { + ved.T = m.End + } + data.Var[v.Key] = ved + SaveCacheVarData(v.Key, ved) + } + return nil, nil +} + +func GetUserVarDataHandler(m *msg.Msg) (interface{}, error) { + data := getVarData() + userVar := &VarExpireData{} + if v, ok := m.Extra.(msg.VarData); ok { + if varData, ok := data.NewUseVar[m.From]; ok { + userVar, _ = varData[v.Key] + } + if userVar == nil { + userVar = &VarExpireData{} + } + ReplyPlayerMsgASync(m, userVar.D) + return userVar, nil + } + return nil, fmt.Errorf("invalid parameters for getting var data") +} + +func SetUserVarDataHandler(m *msg.Msg) (interface{}, error) { + data := getVarData() + data.mu.Lock() + defer data.mu.Unlock() + if v, ok := m.Extra.(msg.VarData); ok { + varData := data.NewUseVar[m.From] + if varData == nil { + varData = make(map[string]*VarExpireData) + data.NewUseVar[m.From] = varData + } + ved, ok := varData[v.Key] + if !ok { + ved = &VarExpireData{} + } + switch v.SetType { + case msg.VAR_OP_SET: + ved.D = v.Value + case msg.VAR_OP_ADD: + if num, ok := ved.D.(int); ok { + ved.D = num + 1 + } else { + ved.D = 1 + } + case msg.VAR_OP_SUB: + if num, ok := ved.D.(int); ok { + if num > 0 { + ved.D = num - 1 + } else { + ved.D = 0 + } + } else { + ved.D = 0 + } + } + ved.U = time.Now().Unix() + if m.End > 0 { + ved.T = m.End + } + data.Var[v.Key] = ved + } + // 保存到缓存中 + SaveCacheVarData(GoUtil.GetVarKey(m.From), data.NewUseVar[m.From]) + return nil, nil +} + +func GetVarDataHandler(m *msg.Msg) (interface{}, error) { + data := getVarData() + varData := &VarExpireData{} + if v, ok := m.Extra.(msg.VarData); ok { + varData, _ = data.NewVar[v.Key] + if varData == nil { + varData = &VarExpireData{} + } + ReplyPlayerMsgASync(m, varData.D) + return varData, nil + } + return nil, fmt.Errorf("invalid parameters for getting var data") +} diff --git a/src/server/game_util/GoUtil.go b/src/server/game_util/GoUtil.go index b5ca11dd..fde503f6 100644 --- a/src/server/game_util/GoUtil.go +++ b/src/server/game_util/GoUtil.go @@ -300,10 +300,6 @@ func UniKey(seed string) string { return fmt.Sprintf("%x", hash.Sum(nil)) } -func GetUserKey(Uid int64) string { - return fmt.Sprintf("user_data_%d", Uid) -} - func GetCatnipLockKey(Uid, GameId int) string { return fmt.Sprintf("catnip_lock_%d_%d", Uid, GameId) } @@ -535,3 +531,7 @@ func GetISOCodeByIP(ip string) (string, error) { } return GetISOCodeByCountry(country) } + +func GetVarKey(Uid int) string { + return fmt.Sprintf("var_%d", Uid) +} diff --git a/src/server/msg/Gameapi.pb.go b/src/server/msg/Gameapi.pb.go index 26fa474b..c0f9515b 100644 --- a/src/server/msg/Gameapi.pb.go +++ b/src/server/msg/Gameapi.pb.go @@ -2628,7 +2628,7 @@ type ResPlayerBaseInfo struct { Guild int32 `protobuf:"varint,10,opt,name=guild,proto3" json:"guild,omitempty"` PackUnlockCount int32 `protobuf:"varint,11,opt,name=pack_unlock_count,json=packUnlockCount,proto3" json:"pack_unlock_count,omitempty"` LastPlayTime int32 `protobuf:"varint,12,opt,name=last_play_time,json=lastPlayTime,proto3" json:"last_play_time,omitempty"` - EnergyBuyCount int32 `protobuf:"varint,13,opt,name=EnergyBuyCount,proto3" json:"EnergyBuyCount,omitempty"` + Ban int64 `protobuf:"varint,13,opt,name=ban,proto3" json:"ban,omitempty"` UserName string `protobuf:"bytes,14,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` LoginTime int32 `protobuf:"varint,15,opt,name=login_time,json=loginTime,proto3" json:"login_time,omitempty"` LogoutTime int32 `protobuf:"varint,16,opt,name=logout_time,json=logoutTime,proto3" json:"logout_time,omitempty"` @@ -2758,9 +2758,9 @@ func (x *ResPlayerBaseInfo) GetLastPlayTime() int32 { return 0 } -func (x *ResPlayerBaseInfo) GetEnergyBuyCount() int32 { +func (x *ResPlayerBaseInfo) GetBan() int64 { if x != nil { - return x.EnergyBuyCount + return x.Ban } return 0 } @@ -27717,7 +27717,7 @@ const file_proto_Gameapi_proto_rawDesc = "" + "ResultCode\x18\x01 \x01(\x05R\n" + "ResultCode\")\n" + "\x11ReqPlayerBaseInfo\x12\x14\n" + - "\x05dwUin\x18\x01 \x01(\x03R\x05dwUin\"\x93\x06\n" + + "\x05dwUin\x18\x01 \x01(\x03R\x05dwUin\"\xfd\x05\n" + "\x11ResPlayerBaseInfo\x12\x14\n" + "\x05dwUin\x18\x01 \x01(\x03R\x05dwUin\x12\x16\n" + "\x06energy\x18\x02 \x01(\x05R\x06energy\x12\x12\n" + @@ -27732,8 +27732,8 @@ const file_proto_Gameapi_proto_rawDesc = "" + "\x05guild\x18\n" + " \x01(\x05R\x05guild\x12*\n" + "\x11pack_unlock_count\x18\v \x01(\x05R\x0fpackUnlockCount\x12$\n" + - "\x0elast_play_time\x18\f \x01(\x05R\flastPlayTime\x12&\n" + - "\x0eEnergyBuyCount\x18\r \x01(\x05R\x0eEnergyBuyCount\x12\x1b\n" + + "\x0elast_play_time\x18\f \x01(\x05R\flastPlayTime\x12\x10\n" + + "\x03ban\x18\r \x01(\x03R\x03ban\x12\x1b\n" + "\tuser_name\x18\x0e \x01(\tR\buserName\x12\x1d\n" + "\n" + "login_time\x18\x0f \x01(\x05R\tloginTime\x12\x1f\n" +