Files
caliverse_server/GameServer/Contents/GameMode/Helper/HostMigrationFactory.cs
2025-05-01 07:20:41 +09:00

240 lines
7.0 KiB
C#

using Nettention.Proud;
using ServerCore;
using ServerBase;
using ServerCommon;
using MetaAssets;
namespace GameServer;
public class HostMigrationFactory
{
public static IHostMigrator createCommonHostMigrator(int battleModeId, GameServerLogic gameServerLogic)
{
// battleModeId <- 게임 모드 ID 테이블 참조용
// TODO: battleModeId를 사용하여 HostMigrationPolicy 생성하는 것으로 변경 예정
int game_mode_option_data_id = 1;
var host_migration_policy = createHostMigrationPolicyByMeta(game_mode_option_data_id);
var net_server = gameServerLogic.getProudNetListener().getNetServer();
NullReferenceCheckHelper.throwIfNull(net_server, () => $"net_server is null !!!!");
var host_migration_system = new HostMigrationSystem(net_server, host_migration_policy);
var host_migrator = new CommonHostMigrator(host_migration_system, gameServerLogic);
return host_migrator;
}
private static HostMigrationPolicy createHostMigrationPolicyByMeta(int gameModeOptionDataId)
{
var meta = getMeta(gameModeOptionDataId);
return new HostMigrationPolicy
{
HostKickFpsThreshold = meta.HostKickFpsThreshold,
HostKickFpsDuration = TimeSpan.FromSeconds(meta.HostKickFpsDuration),
HostKickPingThreshold = meta.HostKickPingThreshold,
HostKickPingDuration = TimeSpan.FromSeconds(meta.HostKickPingDuration),
};
GameModeOptionMetaData getMeta(int gameModeOptionDataId)
{
var game_mode_option_meta_table = MetaData.Instance.Meta.GameModeOptionMetaTable;
game_mode_option_meta_table.GameModeOptionDataListbyGameModeOptionId.TryGetValue(gameModeOptionDataId,
out var game_mode_option_meta);
NullReferenceCheckHelper.throwIfNull(game_mode_option_meta, () => $"game_mode_option_meta is null !!!!");
return game_mode_option_meta;
}
}
}
public class CommonHostMigrator : IHostMigrator
{
private readonly HostMigrationSystem m_host_migration_system;
private string m_host_user_guid = string.Empty;
private readonly GameServerLogic m_game_server_logic;
private DateTime m_last_loop_time = DateTime.MinValue;
private readonly TimeSpan m_loop_interval = TimeSpan.FromSeconds(1);
public HostID SuperPeerHostId => m_host_migration_system.SuperPeerHostId;
public HostMigrationSystem HostMigrationSystem => m_host_migration_system;
public CommonHostMigrator(HostMigrationSystem hostMigrationSystem, GameServerLogic gameServerLogic)
{
m_host_migration_system = hostMigrationSystem;
m_game_server_logic = gameServerLogic;
}
public (Result, bool) migrateCheck(bool ignoreInterval = false)
{
if (!ignoreInterval && isOnMigrationLoopInterval())
{
return (new Result(), false);
}
var (is_migrated, new_super_peer_id) = m_host_migration_system.migrateCheck();
if (is_migrated)
{
var (result, user_guid) = getUserGuidByHostId(new_super_peer_id);
if (result.isFail())
{
return (result, is_migrated);
}
var host_change_success = m_host_migration_system.changeSuperPeerHostId(new_super_peer_id);
if (!host_change_success)
{
return (new Result
{
ErrorCode = ServerErrorCode.NotFoundUser, ResultString = "Failed to change super peer."
}, is_migrated);
}
m_host_user_guid = user_guid;
return (result, is_migrated);
}
return (new Result(), false);
}
public void setGroupHostId(HostID groupId)
{
m_host_migration_system.setGroupHostId(groupId);
}
//=================================================================
// 삭제 예정
//=================================================================
public Result defineHost(HostID p2pGroupId = HostID.HostID_None, SuperPeerSelectionPolicy policy = null!, HostID[] excludes = null!)
{
// m_host_migration_system.setGroupHostId(p2pGroupId);
//
// var (is_migrated, new_super_peer_id) = m_host_migration_system.migrateCheck();
//
// if (is_migrated)
// {
// var (result, user_guid) = getUserGuidByHostId(new_super_peer_id);
// if (result.isFail())
// {
// return result;
// }
//
// var host_change_success = m_host_migration_system.changeSuperPeerHostId(new_super_peer_id);
// if (!host_change_success)
// {
// return new Result
// {
// ErrorCode = ServerErrorCode.NotFoundUser, ResultString = "Failed to change super peer."
// };
// }
// m_host_user_guid = user_guid;
// return result;
// }
return new Result();
}
public Result modifyHost(string userGuid)
{
var (result, host_id) = getHostIdByUserGuid(userGuid);
if (result.isFail())
{
return result;
}
if (m_host_migration_system.changeSuperPeerHostId(host_id))
{
m_host_user_guid = userGuid;
return result;
}
return new Result { ErrorCode = ServerErrorCode.NotFoundUser, ResultString = "Failed to change super peer." };
}
public Result removeHost()
{
m_host_migration_system.changeSuperPeerHostId(HostID.HostID_None);
m_host_user_guid = string.Empty;
return new Result();
}
public string getHostUserGuid()
{
return m_host_user_guid;
}
private (Result, string) getUserGuidByHostId(HostID hostId)
{
string err_msg;
var result = new Result();
if (hostId == HostID.HostID_None)
{
err_msg = $"there is not suitable super peer !!!! host_id : {hostId}";
result.setFail(ServerErrorCode.NotFoundUser, err_msg);
return (result, string.Empty);
}
var session = m_game_server_logic.getProudNetListener().onLookupEntityWithSession((int)hostId);
if (session is null)
{
err_msg = $"session is null!!!! host_id : {hostId}";
result.setFail(ServerErrorCode.NotFoundUser, err_msg);
return (result, string.Empty);
}
var player = session as Player;
if (player is null)
{
err_msg = $"player is null!!!! host_id : {hostId}";
result.setFail(ServerErrorCode.NotFoundUser, err_msg);
return (result, string.Empty);
}
return (result, player.getUserGuid());
}
private (Result, HostID) getHostIdByUserGuid(string userGuid)
{
string err_msg;
var result = new Result();
// todo: 임시 다른 방법 모색 - 비용이 비쌀 수 있음
var session_pair = m_game_server_logic.getProudNetListener()
.getEntityWithSessions()
.FirstOrDefault(x => x.Value.getUserGuid() == userGuid);
var session = session_pair.Value;
if (session is null)
{
err_msg = $"session is null!!!! user_guid : {userGuid}";
result.setFail(ServerErrorCode.NotFoundUser, err_msg);
return (result, HostID.HostID_None);
}
if (session is not Player player)
{
err_msg = $"player is null!!!! user_guid : {userGuid}";
result.setFail(ServerErrorCode.NotFoundUser, err_msg);
return (result, HostID.HostID_None);
}
return (result, player.getHostId());
}
//=================================================================
// 호스트 마이그레이션 루프 인터벌 중인지 여부
//=================================================================
private bool isOnMigrationLoopInterval()
{
if (m_last_loop_time == DateTime.MinValue)
{
m_last_loop_time = DateTime.UtcNow;
return false;
}
if (m_last_loop_time.Add(m_loop_interval) < DateTime.UtcNow)
{
return true;
}
m_last_loop_time = DateTime.UtcNow;
return false;
}
}