초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

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