초기커밋
This commit is contained in:
162
GameServer/Contents/GameMode/Helper/PingLatencyKicker.cs
Normal file
162
GameServer/Contents/GameMode/Helper/PingLatencyKicker.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
namespace GameServer.Contents.GameMode.Helper;
|
||||
|
||||
using Nettention.Proud;
|
||||
|
||||
public class PingLatencyPolicy
|
||||
{
|
||||
public int PingKickThreshold { get; set; } = 600;
|
||||
public TimeSpan PingKickDuration { get; set; } = TimeSpan.FromSeconds(30);
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// LatencyChecker - 플레이가 불가능한 핑 지연을 체크한다. super peer와의 핑을 체크
|
||||
//=====================================================================
|
||||
public class PingLatencyKicker
|
||||
{
|
||||
public class ClientLatency
|
||||
{
|
||||
public HostID HostId { get; set; }
|
||||
public int PingSum { get; set; }
|
||||
public int PingCheckCount { get; set; }
|
||||
public DateTime PingCheckBeginTime { get; set; } = DateTime.UtcNow;
|
||||
public int PingAverage => PingCheckCount > 0 ? PingSum / PingCheckCount: 0;
|
||||
}
|
||||
|
||||
private readonly PingLatencyPolicy m_ping_latency_policy;
|
||||
private readonly SortedList<HostID, ClientLatency> m_host_latencies = new();
|
||||
private HostID m_group_id;
|
||||
private HostID m_super_peer_id;
|
||||
private readonly NetServer m_server;
|
||||
|
||||
public PingLatencyKicker(NetServer server, PingLatencyPolicy pingLatencyPolicy)
|
||||
{
|
||||
m_ping_latency_policy = pingLatencyPolicy;
|
||||
m_server = server;
|
||||
}
|
||||
|
||||
public void setGroupHostId(HostID groupId)
|
||||
{
|
||||
m_group_id = groupId;
|
||||
}
|
||||
|
||||
public void setSuperPeerId(HostID superPeerId)
|
||||
{
|
||||
m_super_peer_id = superPeerId;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
// 호스트 그룹에 속한 클라이언트의 핑 지연을 체크하여, 게임이 불가한 지연이 발생한 경우 해당 호스트를 반환
|
||||
//==============================================================
|
||||
public IEnumerable<HostID> shouldKick()
|
||||
{
|
||||
if (!isValidGroup())
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
checkAndValidateSuperPeer();
|
||||
|
||||
if (!isValidSuperPeer())
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var kick_host_ids = getGroupMemberHostIds().Where(x => checkLatency(x) == true);
|
||||
return kick_host_ids;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<HostID>> shouldKickAsync()
|
||||
{
|
||||
return await Task.Run(shouldKick);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
// 핑 지연 체크
|
||||
//=================================================================
|
||||
private bool checkLatency(HostID hostId)
|
||||
{
|
||||
var ping_to_super_peer = getP2PRecentPingMs(hostId);
|
||||
m_host_latencies.TryGetValue(hostId, out var client_latency);
|
||||
if (ping_to_super_peer > m_ping_latency_policy.PingKickThreshold)
|
||||
{
|
||||
if (client_latency == null)
|
||||
{
|
||||
client_latency = new ClientLatency
|
||||
{
|
||||
HostId = hostId, PingSum = 0, PingCheckCount = 0, PingCheckBeginTime = DateTime.UtcNow
|
||||
};
|
||||
m_host_latencies.Add(hostId, client_latency);
|
||||
}
|
||||
}
|
||||
|
||||
if (client_latency != null)
|
||||
{
|
||||
if (client_latency.PingCheckBeginTime + m_ping_latency_policy.PingKickDuration > DateTime.UtcNow)
|
||||
{
|
||||
if (client_latency.PingAverage > m_ping_latency_policy.PingKickThreshold)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_host_latencies.Remove(hostId);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getP2PRecentPingMs(HostID hostId)
|
||||
{
|
||||
return m_server.GetP2PRecentPingMs(hostId, m_super_peer_id);
|
||||
}
|
||||
|
||||
private IEnumerable<HostID> getGroupMemberHostIds()
|
||||
{
|
||||
var host_ids = new List<HostID>();
|
||||
var group_info = m_server.GetP2PGroupInfo(m_group_id);
|
||||
for (int i = 0; i < group_info.members.GetCount(); i++)
|
||||
{
|
||||
host_ids.Add(group_info.members.At(i));
|
||||
}
|
||||
|
||||
return host_ids;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
// 호스트 그룹이 삭제됐는 지 확인
|
||||
//=================================================================
|
||||
private bool isValidGroup()
|
||||
{
|
||||
if (m_group_id == HostID.HostID_None)
|
||||
return false;
|
||||
|
||||
var group_info = m_server.GetP2PGroupInfo(m_group_id);
|
||||
if (group_info == null || group_info.members.GetCount() == 0)
|
||||
{
|
||||
m_group_id = HostID.HostID_None;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
// 수퍼 피어가 퇴장한 경우 등을 체크
|
||||
//=================================================================
|
||||
private void checkAndValidateSuperPeer()
|
||||
{
|
||||
// 수퍼 피어가 퇴장한 경우 등을 체크
|
||||
if (m_super_peer_id != HostID.HostID_None && m_server.GetClientInfo(m_super_peer_id) == null)
|
||||
{
|
||||
m_super_peer_id = HostID.HostID_None;
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
// 수퍼 피어가 설정되어 있는지 체크
|
||||
//=================================================================
|
||||
private bool isValidSuperPeer()
|
||||
{
|
||||
return m_super_peer_id != HostID.HostID_None;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user