240 lines
7.0 KiB
C#
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;
|
|
}
|
|
}
|