锦标赛优化
This commit is contained in:
parent
00809c8484
commit
5da2f68a0c
@ -1,9 +1,11 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
champshipCfg "server/conf/champship"
|
champshipCfg "server/conf/champship"
|
||||||
randnameCfg "server/conf/randname"
|
randnameCfg "server/conf/randname"
|
||||||
|
"server/db"
|
||||||
"server/game/mod/msg"
|
"server/game/mod/msg"
|
||||||
GoUtil "server/game_util"
|
GoUtil "server/game_util"
|
||||||
proto "server/msg"
|
proto "server/msg"
|
||||||
@ -116,37 +118,72 @@ func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) {
|
|||||||
log.Debug("ChampshipMgr ZeroUpdate")
|
log.Debug("ChampshipMgr ZeroUpdate")
|
||||||
data := c.getData()
|
data := c.getData()
|
||||||
data.mu.Lock()
|
data.mu.Lock()
|
||||||
defer data.mu.Unlock()
|
|
||||||
data.ZeroTime = GoUtil.ZeroTimestamp()
|
data.ZeroTime = GoUtil.ZeroTimestamp()
|
||||||
data.PreRank = data.Rank
|
// 深拷贝 map,避免多个协程持有同一个 map 引用导致并发读写
|
||||||
data.PreRobot = data.Robot
|
oldRank := make(map[int][]*ChampshipRank, len(data.Rank))
|
||||||
data.PreGroupInfo = data.GroupInfo
|
for k, v := range data.Rank {
|
||||||
|
oldRank[k] = v
|
||||||
|
}
|
||||||
|
oldRobot := make(map[int]*ChampshipRobot, len(data.Robot))
|
||||||
|
for k, v := range data.Robot {
|
||||||
|
oldRobot[k] = v
|
||||||
|
}
|
||||||
|
oldGroupInfo := make(map[int]int, len(data.GroupInfo))
|
||||||
|
for k, v := range data.GroupInfo {
|
||||||
|
oldGroupInfo[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
data.PreRank = oldRank
|
||||||
|
data.PreRobot = oldRobot
|
||||||
|
data.PreGroupInfo = oldGroupInfo
|
||||||
data.AutoId = 0
|
data.AutoId = 0
|
||||||
data.RobotId = 1
|
data.RobotId = 1
|
||||||
data.Robot = make(map[int]*ChampshipRobot, 0)
|
data.Robot = make(map[int]*ChampshipRobot, 0)
|
||||||
data.Rank = make(map[int][]*ChampshipRank, 0)
|
data.Rank = make(map[int][]*ChampshipRank, 0)
|
||||||
data.GroupInfo = make(map[int]int, 0)
|
data.GroupInfo = make(map[int]int, 0)
|
||||||
c.update = true
|
c.update = true
|
||||||
|
// 0点更新排行榜缓存
|
||||||
|
for k := range data.PreGroupInfo {
|
||||||
|
c.SetRankCache(k)
|
||||||
|
}
|
||||||
|
data.mu.Unlock()
|
||||||
|
|
||||||
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
|
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
|
||||||
c.ZeroUpdate()
|
c.ZeroUpdate()
|
||||||
})
|
})
|
||||||
c.NotifyPlayer()
|
|
||||||
c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() {
|
c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() {
|
||||||
c.NotifyAll()
|
c.NotifyAll()
|
||||||
})
|
})
|
||||||
|
// 在锁外通知玩家,避免在持有锁时调用外部函数
|
||||||
|
go c.NotifyPlayer()
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChampshipMgr) NotifyPlayer() {
|
func (c *ChampshipMgr) NotifyPlayer() {
|
||||||
List := c.getData().PreRank
|
data := c.getData()
|
||||||
for _, v := range List {
|
data.mu.RLock()
|
||||||
for i := 0; i < 3; i++ {
|
// 深拷贝需要通知的数据,避免在锁外访问 map
|
||||||
|
notifyList := make([]struct {
|
||||||
|
Uid int
|
||||||
|
Rank int
|
||||||
|
}, 0)
|
||||||
|
for _, v := range data.PreRank {
|
||||||
|
for i := 0; i < 3 && i < len(v); i++ {
|
||||||
if v[i].Type == RANK_PLAYER_ROBOT {
|
if v[i].Type == RANK_PLAYER_ROBOT {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
NotifyChampshipResult(v[i].Uid, i+1)
|
notifyList = append(notifyList, struct {
|
||||||
|
Uid int
|
||||||
|
Rank int
|
||||||
|
}{Uid: v[i].Uid, Rank: i + 1})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data.mu.RUnlock()
|
||||||
|
|
||||||
|
// 在锁外通知,避免持锁时间过长
|
||||||
|
for _, item := range notifyList {
|
||||||
|
NotifyChampshipResult(item.Uid, item.Rank)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChampshipMgr) ai() (interface{}, error) {
|
func (c *ChampshipMgr) ai() (interface{}, error) {
|
||||||
@ -154,6 +191,7 @@ func (c *ChampshipMgr) ai() (interface{}, error) {
|
|||||||
ChampshipData.mu.Lock()
|
ChampshipData.mu.Lock()
|
||||||
defer ChampshipData.mu.Unlock()
|
defer ChampshipData.mu.Unlock()
|
||||||
Now := GoUtil.Now()
|
Now := GoUtil.Now()
|
||||||
|
uids := make(map[int]struct{})
|
||||||
for k, v := range ChampshipData.Rank {
|
for k, v := range ChampshipData.Rank {
|
||||||
Notify := make(map[int]int)
|
Notify := make(map[int]int)
|
||||||
for e, r := range v {
|
for e, r := range v {
|
||||||
@ -190,18 +228,26 @@ func (c *ChampshipMgr) ai() (interface{}, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if Notify[r.Uid] != e {
|
if Notify[r.Uid] != e {
|
||||||
NotifyPlayer(r.Uid, &msg.Msg{
|
c.SetRankCache(r.Uid)
|
||||||
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
|
uids[r.Uid] = struct{}{}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChampshipData.Rank[k] = v
|
ChampshipData.Rank[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在锁外通知玩家,避免在持锁时启动 goroutine 访问可能被并发修改的数据
|
||||||
|
for uid := range uids {
|
||||||
|
go NotifyPlayer(uid, &msg.Msg{
|
||||||
|
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() {
|
c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() {
|
||||||
c.ai()
|
c.ai()
|
||||||
})
|
})
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChampshipMgr) GetPreRankMsg(Uid int) *proto.ResChampshipPreRank {
|
func (c *ChampshipMgr) GetPreRankMsg(Uid int) *proto.ResChampshipPreRank {
|
||||||
ChampshipData := c.getData()
|
ChampshipData := c.getData()
|
||||||
ChampshipData.mu.RLock()
|
ChampshipData.mu.RLock()
|
||||||
@ -403,12 +449,20 @@ func (c *ChampshipMgr) group() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range ChampshipData.Pool { // 分组完成通知
|
// 收集需要通知的玩家
|
||||||
NotifyPlayer(k, &msg.Msg{
|
notifyList := make([]int, 0, len(ChampshipData.Pool))
|
||||||
|
for k := range ChampshipData.Pool {
|
||||||
|
c.SetRankCache(k) // SetRankCache 使用 unsafe 方法,在持有锁时是安全的
|
||||||
|
notifyList = append(notifyList, k)
|
||||||
|
}
|
||||||
|
c.getData().Pool = make(map[int]*GroupInfo) // 清空未分配池
|
||||||
|
|
||||||
|
// 在锁外通知玩家,避免在持有锁时调用外部函数
|
||||||
|
for _, uid := range notifyList {
|
||||||
|
go NotifyPlayer(uid, &msg.Msg{
|
||||||
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
|
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
c.getData().Pool = make(map[int]*GroupInfo) // 清空未分配池
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,11 +481,19 @@ func (c *ChampshipMgr) getGroupId(Uid int) int {
|
|||||||
|
|
||||||
// 进去榜单
|
// 进去榜单
|
||||||
func (c *ChampshipMgr) inRank(m *msg.Msg) (interface{}, error) {
|
func (c *ChampshipMgr) inRank(m *msg.Msg) (interface{}, error) {
|
||||||
|
data := m.Extra.(CRank)
|
||||||
|
// 在加锁前获取 GroupId,避免在持有写锁时调用会获取读锁的 getGroupId 导致死锁
|
||||||
|
GroupId := c.getGroupId(data.Uid)
|
||||||
|
|
||||||
ChampshipData := c.getData()
|
ChampshipData := c.getData()
|
||||||
ChampshipData.mu.Lock()
|
ChampshipData.mu.Lock()
|
||||||
defer ChampshipData.mu.Unlock()
|
defer ChampshipData.mu.Unlock()
|
||||||
data := m.Extra.(CRank)
|
|
||||||
GroupId := c.getGroupId(data.Uid)
|
// 再次检查 GroupId,因为可能在等待锁期间被其他协程修改
|
||||||
|
if currentGroupId, ok := ChampshipData.GroupInfo[data.Uid]; ok {
|
||||||
|
GroupId = currentGroupId
|
||||||
|
}
|
||||||
|
|
||||||
if GroupId == 0 {
|
if GroupId == 0 {
|
||||||
ChampshipData.Pool[data.Uid] = &GroupInfo{
|
ChampshipData.Pool[data.Uid] = &GroupInfo{
|
||||||
Uid: data.Uid,
|
Uid: data.Uid,
|
||||||
@ -475,15 +537,23 @@ func (c *ChampshipMgr) inRank(m *msg.Msg) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
// 收集需要通知的玩家
|
||||||
|
notifyList := make([]int, 0)
|
||||||
for k, v := range RankList {
|
for k, v := range RankList {
|
||||||
if Notify[v.Uid] != k {
|
if Notify[v.Uid] != k {
|
||||||
NotifyPlayer(v.Uid, &msg.Msg{
|
c.SetRankCache(v.Uid)
|
||||||
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
|
notifyList = append(notifyList, v.Uid)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChampshipData.Rank[GroupId] = RankList
|
ChampshipData.Rank[GroupId] = RankList
|
||||||
|
|
||||||
|
// 在锁外通知玩家
|
||||||
|
for _, uid := range notifyList {
|
||||||
|
go NotifyPlayer(uid, &msg.Msg{
|
||||||
|
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
|
||||||
|
})
|
||||||
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,7 +577,44 @@ func (c *ChampshipMgr) getMyRank(Uid int) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ChampshipMgr) unsafe_getMyRank(Uid int) int {
|
||||||
|
ChampshipData := c.getData()
|
||||||
|
GroupId := ChampshipData.GroupInfo[Uid]
|
||||||
|
if GroupId == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
RankList, ok := ChampshipData.Rank[GroupId]
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for k, v := range RankList {
|
||||||
|
if v.Uid == Uid {
|
||||||
|
return k + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ChampshipMgr) getLastMyRank(Uid int) int {
|
func (c *ChampshipMgr) getLastMyRank(Uid int) int {
|
||||||
|
ChampshipData := c.getData()
|
||||||
|
ChampshipData.mu.RLock()
|
||||||
|
defer ChampshipData.mu.RUnlock()
|
||||||
|
GroupId := ChampshipData.PreGroupInfo[Uid]
|
||||||
|
if GroupId == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
RankList, ok := ChampshipData.PreRank[GroupId]
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for k, v := range RankList {
|
||||||
|
if v.Uid == Uid {
|
||||||
|
return k + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func (c *ChampshipMgr) unsafe_getLastMyRank(Uid int) int {
|
||||||
ChampshipData := c.getData()
|
ChampshipData := c.getData()
|
||||||
GroupId := ChampshipData.PreGroupInfo[Uid]
|
GroupId := ChampshipData.PreGroupInfo[Uid]
|
||||||
if GroupId == 0 {
|
if GroupId == 0 {
|
||||||
@ -736,3 +843,23 @@ func CreateRobot(M float64, GroupId int) *ChampshipRobot {
|
|||||||
PerScore: PerScore,
|
PerScore: PerScore,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ChampshipMgr) SetRankCache(Uid int) {
|
||||||
|
PreRank := c.unsafe_getLastMyRank(Uid)
|
||||||
|
Rank := c.unsafe_getMyRank(Uid)
|
||||||
|
PreGroupId := c.getData().PreGroupInfo[Uid]
|
||||||
|
GroupId := c.getData().GroupInfo[Uid]
|
||||||
|
key := fmt.Sprintf("champship_rank_cache_%d", Uid)
|
||||||
|
db.RedisSetKey(key, fmt.Sprintf("%d_%d_%d_%d", PreRank, Rank, PreGroupId, GroupId), 86400*2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRankCache(Uid int) (int, int, int, int) {
|
||||||
|
key := fmt.Sprintf("champship_rank_cache_%d", Uid)
|
||||||
|
data, err := db.RedisGetKey(key)
|
||||||
|
if err != nil || data == "" {
|
||||||
|
return 0, 0, 0, 0
|
||||||
|
}
|
||||||
|
var PreRank, Rank, PreGroupId, GroupId int
|
||||||
|
fmt.Sscanf(data, "%d_%d_%d_%d", &PreRank, &Rank, &PreGroupId, &GroupId)
|
||||||
|
return PreRank, Rank, PreGroupId, GroupId
|
||||||
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import (
|
|||||||
playroomCfg "server/conf/playroom"
|
playroomCfg "server/conf/playroom"
|
||||||
"server/game/mod/item"
|
"server/game/mod/item"
|
||||||
limitedTimeEvent "server/game/mod/limited_time_event"
|
limitedTimeEvent "server/game/mod/limited_time_event"
|
||||||
"server/game/mod/msg"
|
|
||||||
GoUtil "server/game_util"
|
GoUtil "server/game_util"
|
||||||
proto "server/msg"
|
proto "server/msg"
|
||||||
)
|
)
|
||||||
@ -295,22 +294,14 @@ func (p *Player) ChargeBackData() {
|
|||||||
|
|
||||||
func (p *Player) BackChampship() {
|
func (p *Player) BackChampship() {
|
||||||
ChampshipMod := p.PlayMod.getChampshipMod()
|
ChampshipMod := p.PlayMod.getChampshipMod()
|
||||||
MyRank, MyPreRank := p.GetChampshipRank()
|
rank, preRank := p.GetChampshipRank()
|
||||||
p.PushClientRes(ChampshipMod.BackData(MyRank, MyPreRank))
|
p.PushClientRes(ChampshipMod.BackData(preRank, rank))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取冠军赛排名 redis缓存
|
||||||
func (p *Player) GetChampshipRank() (int, int) {
|
func (p *Player) GetChampshipRank() (int, int) {
|
||||||
MyRank := 0
|
preRank, rank, _, _ := GetRankCache(int(p.M_DwUin))
|
||||||
MyPreRank := 0
|
return rank, preRank
|
||||||
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]
|
|
||||||
}
|
|
||||||
return MyRank, MyPreRank
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回好友信息
|
// 返回好友信息
|
||||||
|
|||||||
@ -95,3 +95,14 @@ func DiffMap(a, b map[int]int) map[int]int {
|
|||||||
}
|
}
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMapIntValueByKey(m interface{}, key string) int {
|
||||||
|
mi, ok := m.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if v, ok := mi[key]; ok {
|
||||||
|
return Int(v)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user