pet_home_server/src/server/game/RankMgr.go
2025-11-25 11:09:58 +08:00

245 lines
5.5 KiB
Go

package game
import (
"fmt"
"server/GoUtil"
"server/conf"
"server/db"
"server/game/mod/msg"
"sort"
"strconv"
)
const (
RANK_TIME_SORT = 3000000000
)
type RankMgr struct {
*ServerMod
}
type RankData struct {
List map[int][]*Rank // 玩家排行榜
Champship map[int][]*Rank // 锦标赛排行榜
BackData map[int][]*Rank // 玩家排行榜 备份
}
type RankInfo struct {
List []*Rank
MyRank int
MyScore float64
}
const (
RANK_TYPE_USER = 1 // 玩家排行榜
RANK_TYPE_GLOBAL = 2 // 全球排行榜
RANK_USER = "rank_user" // redis玩家排行榜
RANK_COUNTRY_USER = "rank_country_user" // redis国家排行榜
)
type Rank struct {
Uid int
Score float64
Time int64
}
type RankMsg struct {
Uid int
Score float64
RankType int
}
func (r *RankMgr) Init() {
r.key = RANK_MGR_KEY
r.data = &RankData{
List: make(map[int][]*Rank, 0),
}
// 注册处理函数
r.init()
r.RegisterHandler(msg.HANDLE_TYPE_RANK, r.inRank)
r.RegisterHandler(msg.HANDLE_TYPE_RANK_INFO, r.getRankInfo)
r.RegisterHandler(msg.SERVER_ZERO_UPDATE, r.ZeroUpdate)
r.version()
}
func (r *RankMgr) version() error {
RedisKey := fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode)
RedisList, _ := db.RedisZRevRangeWithScores(RedisKey, 0, 100)
if len(RedisList) > 0 {
return nil
}
rankList := r.getRank(RANK_TYPE_USER)
if len(rankList) == 0 {
return nil
}
for _, v := range rankList {
Uid := strconv.Itoa(v.Uid)
db.RedisZAdd(RedisKey, Uid, v.Score)
}
return nil
}
func (r *RankMgr) getData() *RankData {
return r.data.(*RankData)
}
// 零点更新 重置榜单
func (r *RankMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) {
return nil, nil
}
// 获取榜单数据
func (r *RankMgr) getRank(RankType int) []*Rank {
if v, ok := r.getData().List[RankType]; ok {
len := min(100, len(v))
return v[:len]
}
return []*Rank{}
}
func (r *RankMgr) getAllRank(RankType int) []*Rank {
if v, ok := r.getData().List[RankType]; ok {
return v
}
return []*Rank{}
}
func (r *RankMgr) getMyRank(Uid, RankType int) (int, float64) {
if d, ok := r.getData().List[RankType]; ok {
for k, v := range d {
if v.Uid == Uid {
return k + 1, v.Score
}
}
}
return 0, 0.0
}
// 设置榜单数据
func (r *RankMgr) setRank(RankType int, data []*Rank) {
r.getData().List[RankType] = data
}
// 获取排行榜信息
func (r *RankMgr) getRankInfo(m *msg.Msg) (interface{}, error) {
data := m.Extra.(RankMsg)
// 全球排行榜
if data.RankType == RANK_TYPE_GLOBAL {
return r.getRedisRankInfo(m)
}
// 国家排行榜
if data.RankType == RANK_TYPE_USER {
return r.getRedisCountryRankInfo(m)
}
rankList := r.getRank(data.RankType)
MyRank, MyScore := r.getMyRank(m.From, data.RankType)
return &RankInfo{
List: rankList,
MyRank: MyRank,
MyScore: MyScore,
}, nil
}
func (r *RankMgr) getRedisCountryRankInfo(m *msg.Msg) (interface{}, error) {
RedisKey := fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode)
RedisList, err := db.RedisZRevRangeWithScores(RedisKey, 0, 100)
if err != nil {
return &RankInfo{}, nil
}
sort.Slice(RedisList, func(i, j int) bool { // 排序 从大到小
return RedisList[i].Score > RedisList[j].Score
})
rankList := make([]*Rank, 0)
for _, v := range RedisList {
rankList = append(rankList, &Rank{
Uid: GoUtil.Int(v.Member),
Score: v.Score,
Time: GoUtil.Now(),
})
}
MyRank, MyScore, _ := db.RedisZRankWithScores(RANK_USER, strconv.Itoa(m.From))
return &RankInfo{
List: rankList,
MyRank: int(MyRank),
MyScore: MyScore,
}, nil
}
func (r *RankMgr) getRedisRankInfo(m *msg.Msg) (interface{}, error) {
RedisList, err := db.RedisZRevRangeWithScores(RANK_USER, 0, 100)
if err != nil {
return &RankInfo{}, nil
}
sort.Slice(RedisList, func(i, j int) bool { // 排序 从大到小
return RedisList[i].Score > RedisList[j].Score
})
rankList := make([]*Rank, 0)
for _, v := range RedisList {
rankList = append(rankList, &Rank{
Uid: GoUtil.Int(v.Member),
Score: v.Score,
Time: GoUtil.Now(),
})
}
MyRank, MyScore, _ := db.RedisZRankWithScores(RANK_USER, strconv.Itoa(m.From))
return &RankInfo{
List: rankList,
MyRank: int(MyRank),
MyScore: MyScore,
}, nil
}
// 进入排行榜
func (r *RankMgr) inRank(m *msg.Msg) (interface{}, error) {
data := m.Extra.(RankMsg)
rankList := r.getRank(data.RankType)
inRank := false
for _, v := range rankList {
if v.Uid == data.Uid {
if v.Score < data.Score {
v.Score = data.Score
v.Time = m.SendT
inRank = true
break
}
return nil, nil
}
}
if !inRank {
rankList = append(rankList, &Rank{Uid: data.Uid, Score: data.Score, Time: m.SendT})
}
sort.Slice(rankList, func(i, j int) bool { // 排序 从大到小 数值相等按时间排序
if rankList[i].Score > rankList[j].Score {
return true
} else if rankList[i].Score == rankList[j].Score {
return rankList[i].Time < rankList[j].Time
}
return false
})
r.setRank(data.RankType, rankList)
if data.RankType == RANK_TYPE_USER {
// 全球玩家排行榜
Uid := strconv.Itoa(data.Uid)
TimeSort := fmt.Sprintf("0.%d", RANK_TIME_SORT-GoUtil.Now())
TimeSortF, _ := strconv.ParseFloat(TimeSort, 64)
db.RedisZAdd(RANK_USER, Uid, data.Score+TimeSortF)
// 地区玩家排行榜
RedisKey := fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode)
db.RedisZAdd(RedisKey, Uid, data.Score+TimeSortF)
}
r.update = true
return nil, nil
}
func (r *RankMgr) ClearRank(RankType int) {
// if RankType == RANK_TYPE_GLOBAL {
// db.RedisDel(RANK_USER)
// return
// }
r.setRank(RankType, []*Rank{})
}