好友优化

This commit is contained in:
hahwu 2026-03-04 11:34:53 +08:00
parent 8bf48093b7
commit 49b6a6a928
9 changed files with 258 additions and 18 deletions

View File

@ -442,3 +442,13 @@ func GetCommendPlayerFromDb(uid, login int64, level int) ([]int, error) {
}
return res, nil
}
func GetDebugPlayer(uid int) ([]int, error) {
sqlStr := "SELECT dwUin FROM t_player_baseinfo WHERE dwUin != ? ORDER BY login_time DESC LIMIT 1000"
var res []int
if err := SqlDb.Select(&res, sqlStr, uid); err != nil {
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "PlayerBaseInfo", sqlStr, err)
return nil, err
}
return res, nil
}

View File

@ -1,6 +1,7 @@
package game
import (
"math"
"server/db"
"server/game/mod/msg"
GoUtil "server/game_util"
@ -156,43 +157,153 @@ func GetRecommendPlayer(p *Player, Num int) []int {
candidateList = append(candidateList, Uid)
}
}
baseList := make([]*PlayerSimpleData, 0, len(candidateList))
levelFilterList := make([]*PlayerSimpleData, 0, len(candidateList))
for _, uid := range candidateList {
ps := G_GameLogicPtr.GetSimplePlayerByUid(uid)
if ps != nil {
baseList = append(baseList, ps)
levelFilterList = append(levelFilterList, ps)
}
}
if len(baseList) == 0 {
if len(levelFilterList) == 0 {
return nil
}
BaseMod := p.PlayMod.getBaseMod()
level := BaseMod.GetLevel()
diffLimit := 10
filtered := make([]int, 0, len(baseList))
chargeFilterList := make([]*PlayerSimpleData, 0, len(levelFilterList))
breakNum := 100
/*
等级筛选检索与玩家等级差绝对值小于等于10的用户若大于5人则进入下一步筛查否则逐步放宽等级差限制直到等级差绝对值小于等于100仍然无法筛选出5人则进入下一步筛查
*/
for breakNum > 0 {
breakNum--
filtered = filtered[:0]
for _, ps := range baseList {
chargeFilterList = chargeFilterList[:0]
for _, ps := range levelFilterList {
if ps == nil {
continue
}
diff := level - ps.Level
if diff < 0 {
diff = -diff
}
if diff <= diffLimit {
filtered = append(filtered, ps.Uid)
diff := math.Abs(float64(level - ps.Level))
if diff <= float64(diffLimit) {
chargeFilterList = append(chargeFilterList, ps)
}
}
if len(filtered) >= 5 {
if len(chargeFilterList) >= 5 {
break
}
diffLimit++
}
candidateList = filtered
recommendList := GoUtil.RandSliceNum(candidateList, Num)
/*
付费筛查判断自身是否为付费用户若是则优先推荐付费用户若不是则优先推荐非付费用户
*/
endFilterList := make([]int, 0, len(chargeFilterList))
chargeFilterFunc := func(filterlist []*PlayerSimpleData, maxCharge float64) []int {
var res []int
type sortData struct {
uid int
maxCharge float64
}
var filterList2 []sortData
var notChargeList []int
var allList []int
for _, ps := range filterlist {
if ps == nil {
continue
}
allList = append(allList, ps.Uid)
if ps.MaxCharge > 0 {
filterList2 = append(filterList2, sortData{ps.Uid, math.Abs(maxCharge - ps.MaxCharge)})
} else {
notChargeList = append(notChargeList, ps.Uid)
}
}
sort.Slice(filterList2, func(i, j int) bool {
return filterList2[i].maxCharge < filterList2[j].maxCharge
})
if len(filterList2) >= 1 {
res = append(res, filterList2[0].uid)
}
if len(filterList2) >= 2 {
res = append(res, filterList2[1].uid)
}
if len(notChargeList) >= 1 {
res = append(res, notChargeList[0])
}
if len(res) < 3 {
dlist := GoUtil.SubSlices(allList, res)
res = append(res, GoUtil.RandSliceNum(dlist, 3-len(res))...)
}
return res
}
notChargeWatchAdFilterFunc := func(filterlist []*PlayerSimpleData) []int {
var res []int
var notChargeList []int
var chargeList []int
var allList []int
for _, ps := range filterlist {
if ps == nil {
continue
}
allList = append(allList, ps.Uid)
if ps.MaxCharge > 0 {
chargeList = append(chargeList, ps.Uid)
} else {
if ps.AdWatch > 5 {
notChargeList = append(notChargeList, ps.Uid)
}
}
}
if len(notChargeList) >= 1 {
res = append(res, notChargeList[0])
}
if len(notChargeList) >= 2 {
res = append(res, notChargeList[1])
}
if len(chargeList) >= 1 {
res = append(res, chargeList[0])
}
if len(res) < 3 {
dlist := GoUtil.SubSlices(allList, res)
res = append(res, GoUtil.RandSliceNum(dlist, 3-len(res))...)
}
return res
}
notChargeNotWatchAdFilterFunc := func(filterlist []*PlayerSimpleData) []int {
var res []int
var notChargeList []int
var chargeList []int
var allList []int
for _, ps := range filterlist {
if ps == nil {
continue
}
allList = append(allList, ps.Uid)
if ps.MaxCharge > 0 {
chargeList = append(chargeList, ps.Uid)
} else {
notChargeList = append(notChargeList, ps.Uid)
}
}
if len(chargeList) >= 1 {
res = append(res, chargeList[0])
}
dlist := GoUtil.SubSlices(allList, res)
res = append(res, GoUtil.RandSliceNum(dlist, 3-len(res))...)
return res
}
if diffLimit == 10 && len(chargeFilterList) >= 5 {
MaxCharge := p.GetChargeMod().GetMaxCharge()
if MaxCharge > 0 {
endFilterList = chargeFilterFunc(chargeFilterList, MaxCharge)
} else {
if p.GetChargeMod().GetAdWatch() > 5 {
endFilterList = notChargeWatchAdFilterFunc(chargeFilterList)
} else {
endFilterList = notChargeNotWatchAdFilterFunc(chargeFilterList)
}
}
}
recommendList := GoUtil.RandSliceNum(endFilterList, Num)
for _, Uid := range recommendList {
FriendMod.AddRecommend(Uid)
}

View File

@ -40,6 +40,8 @@ type PlayerSimpleData struct {
Lang int
Account string
PetFur int
MaxCharge float64
AdWatch int
}
type VarGoldCard struct {

View File

@ -623,6 +623,27 @@ func ReqGmCommand_(player *Player, Command string) error {
SevenMod.MonthResetTime = 0
PlayerBaseMod := player.GetPlayerBaseMod()
SevenMod.ZeroUpdate(PlayerBaseMod.GetSevenLoginAdd(), PlayerBaseMod.GetLastLoginTime())
case "debugLogoutMsg":
Uid, _ := strconv.Atoi(arg[1])
uidList, err := db.GetDebugPlayer(Uid)
if err != nil {
log.Error("GetDebugPlayer err:%s", err.Error())
return err
}
for _, uid := range uidList {
FriendMgrSend(&MsgMod.Msg{
Type: MsgMod.HANDLE_TYPE_APPLY,
SendT: GoUtil.Now(),
From: uid,
To: Uid,
})
FriendMgrSend(&MsgMod.Msg{
Type: MsgMod.HANDLE_TYPE_HANDBOOK_COLLECTION,
SendT: GoUtil.Now(),
From: Uid,
To: uid,
})
}
default:
return fmt.Errorf("Player %d ReqGmCommand:%v not found", player.M_DwUin, arg)
}

View File

@ -525,7 +525,45 @@ func (p *Player) handle(m *msg.Msg) error {
case msg.HANDLE_TYPE_FRIEND_SPONSOER:
p.AddLog(m.From, friend.LOG_TYPE_FRIEND_SPONSOR_GET, "", m.SendT)
case msg.SERVER_PLAYER_SYNC_LOGOUT_MSG:
//p.LoginBackData()
info, ok := m.Extra.(map[string]interface{})
if !ok {
return nil
}
applyUids, ok := info["applyUids"].([]int64)
if ok && len(applyUids) > 0 {
var faceList []int
var name string
for _, v := range applyUids {
ps := G_GameLogicPtr.GetSimplePlayerByUid(int(v))
if ps != nil {
faceList = append(faceList, ps.Face)
name = ps.Name
}
}
p.PushClientRes(&proto.ResPlayerLougouMsg{
Name: name,
Face: GoUtil.IntToInt32(faceList),
Count: GoUtil.Int32(info["apply_count"]),
})
}
otherUids, ok := info["otherUids"].([]int64)
if ok && len(otherUids) > 0 {
var faceList []int
var name string
for _, v := range otherUids {
ps := G_GameLogicPtr.GetSimplePlayerByUid(int(v))
if ps != nil {
faceList = append(faceList, ps.Face)
name = ps.Name
}
}
p.PushClientRes(&proto.ResPlayerLougouMsg{
Type: 1,
Name: name,
Face: GoUtil.IntToInt32(faceList),
Count: GoUtil.Int32(info["other_count"]),
})
}
default:
log.Debug("uid : %d, handle msg type : %d not exist", p.M_DwUin, m.Type)
}

View File

@ -293,16 +293,43 @@ func PlayerLoginHandler(data *msg.Msg) (interface{}, error) {
messages.mu.Unlock()
ReplyPlayerMsgASync(data, nil)
// 在锁外发送离线消息
var applyUids []int64
var otherUids []int64
for _, message := range messagesToSend {
message.H = msg.MSG_TYPE_OFFLINE // 标记为离线消息
if message.Type == msg.HANDLE_TYPE_APPLY {
applyUids = append(applyUids, int64(message.From))
} else {
otherUids = append(otherUids, int64(message.From))
}
}
for _, message := range messagesToSend {
if message.Type == msg.HANDLE_TYPE_APPLY && len(applyUids) >= 3 {
message.H = msg.MSG_TYPE_OFFLINE // 标记为离线消息
}
if message.Type != msg.HANDLE_TYPE_APPLY && len(otherUids) >= 3 {
message.H = msg.MSG_TYPE_OFFLINE // 标记为离线消息
}
SendMsgToNodeAsync(message, node)
}
applyUidsFive := applyUids
if len(applyUids) > 5 {
applyUidsFive = applyUids[len(applyUids)-5:]
}
otherUidsFive := otherUids
if len(otherUids) > 5 {
otherUidsFive = otherUids[len(otherUids)-5:]
}
SendMsgToNodeAsync(&msg.Msg{
From: data.From,
To: data.From,
Type: msg.SERVER_PLAYER_SYNC_LOGOUT_MSG,
HandleType: msg.HANDLE_MOD_PLAYER_MSG,
Extra: len(messagesToSend),
Extra: map[string]interface{}{
"apply_uids": applyUidsFive,
"apply_count": len(applyUids),
"other_uids": otherUidsFive,
"other_count": len(otherUids),
},
}, node) // 发送离线消息处理完成通知
log.Debug("[Middleware] Player sync logout message player id: %v, len: %d", data.From, len(messagesToSend))
return nil, nil

View File

@ -39,6 +39,8 @@ type ChargeMod struct {
WishList *WishList
WeeklyDiscount map[int]int // 每周折扣购买次数
WeeklyEndTime int64
AdWatch int // 观看广告次数
}
type WishList struct {
@ -132,6 +134,7 @@ func (c *ChargeMod) ZeroUpdate(Emit []int) {
c.FreeShop = 0
SpecialGrade := 1
c.TodayCharge = 0
c.AdWatch = 0
c.SpecialShop = make(map[int]*SepcialShop)
SpecialShopCount := chargeCfg.GetSpecialShopCount()
for i := 1; i <= 2; i++ {
@ -489,3 +492,7 @@ func (c *ChargeMod) GetWeeklyEndTime() int64 {
func (c *ChargeMod) SetWeeklyEndTime(EndTime int64) {
c.WeeklyEndTime = EndTime
}
func (c *ChargeMod) GetAdWatch() int {
return c.AdWatch
}

View File

@ -1081,6 +1081,7 @@ func (p *Player) UpdateUserInfo() {
simple.Lang = int(p.PlayMod.getBaseMod().Lang)
simple.Account = p.PlayMod.getBaseMod().Account
simple.PetFur = p.PlayMod.getFurMod().GetFurSet()
simple.MaxCharge = p.PlayMod.getChargeMod().GetMaxCharge()
//TODO 存储到redis 在新版本中将优化成gob进行压缩
value, _ := json.Marshal(simple)
IdStr := GoUtil.String(p.M_DwUin)

View File

@ -210,6 +210,29 @@ func Int(a interface{}) int {
return 0
}
func Int32(a interface{}) int32 {
if a == nil {
return 0
}
switch v := a.(type) {
case int:
return int32(v)
case int32:
return int32(v)
case int64:
return int32(v)
case float64:
return int32(v)
case string:
r, err := strconv.Atoi(v)
if err != nil {
return 0
}
return int32(r)
}
return 0
}
func String(a interface{}) string {
if a == nil {
return ""