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
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;
|
|
}
|
|
}
|
|
}
|
|
|