You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

201 lines
6.9 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Sog;
using ProtoCSStruct;
using Google.Protobuf.Collections;
namespace Friend
{
/// <summary>
/// 好友推荐
/// </summary>
public static class FriendRecommenTableSvc
{
public static void Tick(long nowSec)
{
var m_allTable = FriendServerUtils.GetFriendRecommendTable();
if (nowSec < m_allTable.nextTickSec)
{
return;
}
TraceLog.Trace("FriendRecommenTableSvc.Tick {0}", m_allTable.m_recommendInfoTable.Count);
// 1分钟更新一次
m_allTable.nextTickSec = nowSec + 60;
foreach(FriendRecommendInfo m_table in m_allTable.m_recommendInfoTable.Values)
{
for (int i = 0; i < m_table.uidHash.Length; i++)
{
m_table.uidList[i].Clear();
foreach (long uid in m_table.uidHash[i].ToList())
{
ref FriendCacheInfoStruct friendInfo = ref FriendOp.GetFriendInfoByUid(uid);
if (friendInfo.IsNull())
{
TraceLog.Trace("FriendRecommenTableSvc.Tick uid {0} no friendInfo", uid);
m_table.uidHash[i].Remove(uid);
continue;
}
// 淘汰离线玩家
PlayerInfoFriend player = FriendServerUtils.GetPlayerTableOp().GetPlayerInfo(uid);
if (player == null || player.IsOnline == false)
{
m_table.uidHash[i].Remove(uid);
continue;
}
TraceLog.Trace("FriendRecommenTableSvc.Tick uid {0} friendList {1}"
, friendInfo.Self.Uid, friendInfo.FriendList.iCount);
if (FriendSvc.IsFriendListFull(ref friendInfo))
{
m_table.uidHash[i].Remove(friendInfo.Self.Uid);
continue;
}
int idx = friendInfo.Self.Level / 10;
if (idx != i)
{
m_table.uidHash[i].Remove(friendInfo.Self.Uid);
continue;
}
m_table.uidList[i].Add(ref friendInfo.Self.Uid);
}
if (m_table.uidList[i].Count > 0)
{
TraceLog.Trace("FriendRecommenTableSvc.Tick level {0} list count {1} hash count {2}"
, i, m_table.uidList[i].Count, m_table.uidHash[i].Count);
}
}
}
}
public static FriendRecommendInfo GetOrCreateRecommendInfo(int logicWorldId)
{
var m_logicTable = FriendServerUtils.GetFriendRecommendTable().m_recommendInfoTable;
if (!m_logicTable.ContainsKey(logicWorldId))
{
FriendRecommendInfo newInfo = new FriendRecommendInfo(logicWorldId);
m_logicTable.Add(logicWorldId, newInfo);
TraceLog.Debug("FriendRecommenTableSvc.GetOrCreateRecommendInfo create FriendRecommendInfo {0}", logicWorldId);
}
return m_logicTable[logicWorldId];
}
// add的时候只要新队列里面没有就加入, 不处理老队列, 等tick时移除
public static void Add(ref FriendCacheInfoStruct friendInfo)
{
if (FriendSvc.IsFriendListFull(ref friendInfo))
{
return;
}
int logicWorldId = FriendServerUtils.GetLogicWorldId(friendInfo.Self.RealmId);
if(logicWorldId <= 0)
{
return;
}
var m_table = GetOrCreateRecommendInfo(logicWorldId);
int idx = friendInfo.Self.Level / 10;
if (idx < m_table.uidHash.Length
&& m_table.uidHash[idx].Count < FriendRecommendInfo.NumPerLevel
&& !m_table.uidHash[idx].Contains(friendInfo.Self.Uid))
{
m_table.uidHash[idx].Add(friendInfo.Self.Uid);
if (!m_table.uidList[idx].IsFull())
{
m_table.uidList[idx].Add(ref friendInfo.Self.Uid);
}
TraceLog.Trace("FriendRecommenTableSvc.Add idx {0} uid {1} hash count {2} uidList count {3}"
, idx, friendInfo.Self.Uid, m_table.uidHash[idx].Count, m_table.uidList[idx].Count);
}
}
public static List<long> GetRecommendUid(ref FriendCacheInfoStruct selfInfo, int level, int need)
{
if (need <= 0)
{
return null;
}
int logicWorldId = FriendServerUtils.GetLogicWorldId(selfInfo.Self.RealmId);
if (logicWorldId <= 0)
{
return null;
}
var m_table = GetOrCreateRecommendInfo(logicWorldId);
int idx = level / 10;
if (idx >= m_table.uidList.Length)
{
return null;
}
if (m_table.uidList[idx].Count == 0)
{
return null;
}
var uidPool = new List<long>(m_table.uidList[idx].Count);
// 去掉自己和好友,以及黑名单的
for (int i = 0; i < m_table.uidList[idx].Count; i++)
{
if (m_table.uidList[idx][i] != selfInfo.Self.Uid
&& FriendOp.IsAlreadyBeenFriend(ref selfInfo, m_table.uidList[idx][i]) != 1
&& !selfInfo.Self.BlackList.Contains(m_table.uidList[idx][i]))
{
uidPool.Add(m_table.uidList[idx][i]);
}
}
// 推荐列表不够
if (uidPool.Count <= need)
{
return uidPool;
}
var random = FriendServerUtils.GetApp().Rand;
// gap是随机间隔
int gap = uidPool.Count / need - 1;
if (gap <= 0)
{
gap = 1;
}
else if (gap > 1)
{
gap = random.Next(gap) + 1;
}
// 随机开始位置和间隔
return GetRandList(uidPool, random.Next(uidPool.Count), gap, need);
}
private static List<long> GetRandList(List<long> uidPool, int startIdx, int gap, int need)
{
gap = gap <= 0 ? 1 : gap;
var list = new List<long>(need);
for (int i = 0; i < need; i++)
{
startIdx = (startIdx + gap) % uidPool.Count;
list.Add(uidPool[startIdx]);
}
return list;
}
}
}