846 lines
33 KiB
C#
846 lines
33 KiB
C#
using System.Collections.Concurrent;
|
|
|
|
|
|
using Google.Protobuf.WellKnownTypes;
|
|
using Nettention.Proud;
|
|
|
|
|
|
using ServerCore;
|
|
using ServerBase;
|
|
using ServerCommon;
|
|
using ServerCommon.BusinessLogDomain;
|
|
|
|
|
|
using USER_GUID = System.String;
|
|
|
|
|
|
namespace GameServer;
|
|
|
|
public partial class InstanceRoom
|
|
{
|
|
CancellationTokenSource _cts = new CancellationTokenSource();
|
|
|
|
ConcurrentDictionary<string, Player> m_players = new();
|
|
//object memberLock = new object();
|
|
|
|
readonly string _roomId;
|
|
readonly int _instanceId;
|
|
|
|
Map _map = new();
|
|
|
|
EPlaceType _placeType;
|
|
ContentsType _contentsType;
|
|
bool _isFullMemberStart = false;
|
|
|
|
bool _concertStart = false;
|
|
bool _concertEnd = false;
|
|
DateTime _concertStartTime;
|
|
DateTime _concertEndTime;
|
|
int _concertLength;
|
|
int _startBuffID = 0;
|
|
int _concertEnterItemId = 0;
|
|
int _concertEnterItemCount = 0;
|
|
|
|
bool _isPartyInstance = false;
|
|
string _partyGuid = string.Empty;
|
|
|
|
int _screenPageNo = 0;
|
|
|
|
public bool isDestroy { get; private set; }
|
|
|
|
public int SessionCount { get { return m_players.Count; } }
|
|
|
|
public int Capacity { get; private set; }
|
|
|
|
public InstanceRoom(string roomId, int instanceId)
|
|
{
|
|
_roomId = roomId;
|
|
_instanceId = instanceId;
|
|
}
|
|
|
|
public async Task<bool> Init()
|
|
{
|
|
Log.getLogger().info($"InstanceRoom.Init() Start !!! - instanceRoomId:{_roomId}, InstanceMetaId:{_instanceId}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
if (MetaData.Instance._IndunTable.TryGetValue(_instanceId, out var instanceMetaData) == false)
|
|
{
|
|
Log.getLogger().error($"Failed to MetaData.TryGetValue() !!! : instanceMetaId:{_instanceId} - instanceRoomId:{_roomId}");
|
|
return false;
|
|
}
|
|
|
|
if (instanceMetaData.RoomFile.isNullOrWhiteSpace())
|
|
{
|
|
Log.getLogger().error($"Not Exist InstanceMetaData.RoomFile : instanceMetaId:{_instanceId} - instanceRoomId:{_roomId}");
|
|
return false;
|
|
}
|
|
|
|
_contentsType = instanceMetaData.ContentsType;
|
|
_placeType = instanceMetaData.placeType();
|
|
Capacity = instanceMetaData.LimitCount;
|
|
|
|
if (_placeType == EPlaceType.MyHome)
|
|
{
|
|
result = MyhomeHelper.getMyhomeOwnerUserGuidAndMyhomeGuidFromRoomId(_roomId, out var myhomeOwnerUserGuid, out var myhomeGuid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to getMyhomeOwnerUserGuidAndMyhomeGuidFromRoomId() !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
(result, var myhome_attrib) = await MyhomeHelper.getEnterMyhomeAttribFromDynamoDb(myhomeOwnerUserGuid, myhomeGuid);
|
|
if (result.isFail() || null == myhome_attrib)
|
|
{
|
|
err_msg = $"Failed to getEnterMyhomeAttribFromDynamoDb() !!! : {result.toBasicString()} - instanceRoomId:{_roomId}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
(result, var myhome_ugc_info) = await MyhomeHelper.getMyhomeUgcInfo(myhome_attrib);
|
|
if (result.isFail() || null == myhome_ugc_info)
|
|
{
|
|
err_msg = $"Failed to getMyhomeUgcInfo() !!! : {result.toBasicString()} - instanceRoomId:{_roomId}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
await _map.onInitFromMyhomeUgc(myhome_attrib.MyhomeGuid, myhome_ugc_info, _roomId);
|
|
}
|
|
else
|
|
{
|
|
|
|
await _map.onInit(instanceMetaData.RoomFile, _roomId, true);
|
|
|
|
if (true == InstanceRoomHandler.isOnlyOneInstanceRoomID(_roomId))
|
|
{
|
|
var result_farming = await FarmingHelper.tryFinalyzeUncompletedFarmingByMap(_map);
|
|
if (result_farming.isFail())
|
|
{
|
|
err_msg = $"Fail to tryFinalyzeUncompletedFarmingByMap() !!! : {_map.toBasicString()}, {result_farming.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_placeType == EPlaceType.Concert)
|
|
{
|
|
if (MetaData.Instance._ConcertTable.TryGetValue(instanceMetaData.MapId, out var concertInfo) == false)
|
|
{
|
|
Log.getLogger().error($"Failed to MetaData.TryGetValue() !!! : concertMetaId:{instanceMetaData.MapId} - instanceRoomId:{_roomId}");
|
|
return false;
|
|
}
|
|
|
|
_startBuffID = concertInfo.BuffID;
|
|
_concertEnterItemId = concertInfo.DeleteItem;
|
|
_concertEnterItemCount = concertInfo.DeleteItemCount;
|
|
_concertLength = concertInfo.ConcertLength;
|
|
|
|
if (concertInfo.StartRequiredType == "InstanceTimeTarget")
|
|
{
|
|
_isFullMemberStart = true;
|
|
_concertStartTime = DateTime.UtcNow.AddSeconds(concertInfo.ITRequiredDetail);
|
|
_concertEndTime = _concertStartTime.AddSeconds(_concertLength);
|
|
}
|
|
else if (concertInfo.StartRequiredType == "RealTimeTarget")
|
|
{
|
|
_concertStartTime = concertInfo.RTRequiredDetail.UtcDateTime;
|
|
_concertEndTime = _concertStartTime.AddSeconds(_concertLength);
|
|
}
|
|
|
|
var roomIdElemnet = _roomId.Split(":");
|
|
if (roomIdElemnet[0] == ServerCommon.Constant.PREFIX_PARTY_INSTANCE_ROOM_ID)
|
|
{
|
|
var party = server_logic.findGlobalEntity<GlobalParty>()?.getParty(roomIdElemnet[1]);
|
|
var party_instance_action = party?.getEntityAction<GlobalPartyDetailInstanceAction>();
|
|
|
|
if (null == party_instance_action || false == party_instance_action.isExist())
|
|
{
|
|
Log.getLogger().error($"Not Exist partyInstanceAction !!! - instanceRoomId:{_roomId}");
|
|
return false;
|
|
}
|
|
|
|
_isPartyInstance = true;
|
|
_partyGuid = roomIdElemnet[1];
|
|
Capacity = MetaHelper.GameConfigMeta.MaxPartyMembers;
|
|
|
|
_concertStartTime = party_instance_action.getStartTime().ToDateTime();
|
|
_concertEndTime = _concertStartTime.AddSeconds(_concertLength);
|
|
}
|
|
|
|
// instance 정보 추가 등록
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
result = await instance_room_storage.setInstanceRoomExtraInfo(_roomId, _placeType, _concertStartTime);
|
|
if (result.isFail())
|
|
{
|
|
Log.getLogger().error($"Failed to setInstanceRoomExtraInfo() !!! : {result.toBasicString()} - instanceRoomId:{_roomId}");
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
if (_placeType == EPlaceType.Movie)
|
|
{
|
|
if (MetaData.Instance._ConcertTable.TryGetValue(instanceMetaData.MapId, out var concertInfo) == false)
|
|
{
|
|
Log.getLogger().error($"Failed to MetaData.TryGetValue() !!! : concertMetaId:{instanceMetaData.MapId} - instanceRoomId:{_roomId}");
|
|
return false;
|
|
}
|
|
|
|
_startBuffID = concertInfo.BuffID;
|
|
}
|
|
|
|
//GameMode
|
|
(var gamemode_init_result, var gamemode_init_handler) = GameModeHelper.getGameModeInitHandler(this, 1, _roomId);
|
|
if (gamemode_init_result.isSuccess())
|
|
{
|
|
var gamemode_validation_result = gamemode_init_handler.gamedModeInstanceInitValidate();
|
|
if (gamemode_validation_result.isFail()) return false;
|
|
|
|
var init_result = await gamemode_init_handler.gamedModeInstanceInit();
|
|
if (init_result.isFail())
|
|
{
|
|
Log.getLogger().error($"battleInstanceInit error roomId : {_roomId}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Log.getLogger().info($"InstanceRoom.Init() Finish !!! - instanceRoomId:{_roomId}, InstanceMetaId:{_instanceId}");
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool Join(Player player)
|
|
{
|
|
var user_guid = player.getUserGuid();
|
|
|
|
Log.getLogger().info($"InstanceRoom.Join() Start !!! - userGuid:{user_guid}, instanceRoomId:{_roomId}, sessionCount:{SessionCount}");
|
|
|
|
int memberCount = 0;
|
|
{
|
|
m_players.AddOrUpdate(user_guid, player, (key, oldValue) => player);
|
|
memberCount = SessionCount;
|
|
}
|
|
|
|
var location_attribute = player.getEntityAttribute<LocationAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(location_attribute, () => $"location_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
location_attribute.CurrentIndunLocation.InstanceRoomId = _roomId;
|
|
location_attribute.CurrentIndunLocation.InstanceMetaId = _instanceId;
|
|
location_attribute.EnterIndunLocation.clear();
|
|
|
|
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
|
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!! - {player.toBasicString()}");
|
|
|
|
var result = game_zone_action.tryEnterGameZone(_map);
|
|
if (result.isFail())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (memberCount == 1)
|
|
{
|
|
_cts.Dispose();
|
|
// TODO: 위치수정 필요
|
|
_cts = new CancellationTokenSource();
|
|
_ = LogicThread.Factory.StartNew(() => KeepAlive(_cts.Token),
|
|
CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
|
|
|
|
if (_placeType == EPlaceType.Concert)
|
|
{
|
|
_ = LogicThread.Factory.StartNew(() => CheckConcertTime(_cts.Token),
|
|
CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
|
|
}
|
|
|
|
//_ = LogicThread.Factory.StartNew(() => CheckSession(_cts.Token),
|
|
// CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
|
|
}
|
|
|
|
|
|
//GameMode
|
|
(var get_mode_result, var gamemode_join_handler) = GameModeHelper.getGameModeJoinHandler(this, 1, _roomId);
|
|
if (get_mode_result.isFail()) return true; //fail 이면 gamemode 인스턴스가 아니므로 그냥 정상 리턴 처리
|
|
|
|
if (get_mode_result.isSuccess())
|
|
{
|
|
get_mode_result = gamemode_join_handler.gamedModeInstanceJoinValidate();
|
|
if (get_mode_result.isSuccess())
|
|
{
|
|
//successs 면 gamemod join 설정
|
|
var join_result = gamemode_join_handler.gamedModeInstanceJoin(player);
|
|
if (join_result.isFail())
|
|
{
|
|
Log.getLogger().error($"gamedModeInstanceJoin error!!! _placeType : {_placeType}, roomId : {_roomId}, player : {player.toBasicString()}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Log.getLogger().info($"{player.getUserGuid()} JoinInstanceRoom {_roomId}");
|
|
// LogActionType.StageConcertStart 로그 작성은 인스턴룸이 실제로 시작 상태로 전환될 때 작성한다. 추후 LogActionType.StageConcertEnd 도 정의해야 한다.
|
|
//List<ILogInvoker> invokers = new List<ILogInvoker>();
|
|
//var stage_log_info = StageBusinessLogHelper.toStageLogInfo(_instanceId, _contentsType, _roomId, SessionCount, Capacity);
|
|
//invokers.Add(new StageLog(LogActionType.StageConcertStart, stage_log_info));
|
|
//BusinessLogger.collectLogs(LogActionType.StageEnter, session._selectedChar.LastPositionInfo.m_last_stage_exit_tran_guid, session._selectedChar, invokers);
|
|
|
|
//var invokers = new List<ILogInvoker>();
|
|
//var log_action = new LogAction(LogActionType.StageEnter, player._selectedChar.LastPositionInfo.m_last_stage_exit_tran_guid);
|
|
//var stage_log_info = StageBusinessLogHelper.toStageLogInfo(_instanceId, _contentsType, _roomId, SessionCount, Capacity);
|
|
//invokers.Add(new StageLog(stage_log_info));
|
|
//BusinessLogger.collectLogs(log_action, player._selectedChar, invokers);
|
|
|
|
Log.getLogger().info($"InstanceRoom.Join() Finish !!! - userGuid:{user_guid}, instanceRoomId:{_roomId}, sessionCount:{SessionCount}");
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task SendJoinSuccess(Player player)
|
|
{
|
|
// 입장 성공 패킷
|
|
{
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Response = new ClientToGameRes();
|
|
clientToGame.Response.ErrorCode = ServerErrorCode.Success;
|
|
clientToGame.Response.JoinInstanceRoomRes = new ClientToGameRes.Types.JoinInstanceRoomRes();
|
|
|
|
clientToGame.Response.JoinInstanceRoomRes.MeetingRoom = new MeetingRoomInfo();
|
|
clientToGame.Response.JoinInstanceRoomRes.MeetingRoom.ScreenPageNo = _screenPageNo;
|
|
|
|
GameServerApp.getServerLogic().onSendPacket(player, clientToGame);
|
|
|
|
player.send_S2C_NTF_SET_LOCATION();
|
|
}
|
|
|
|
// 기존 맴버 정보 패킷
|
|
{
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.InstanceRoomMember = new ClientToGameMessage.Types.InstanceRoomMember();
|
|
|
|
var instanceRoomMembers = m_players.Values.Where(s => s.getUserGuid() != player.getUserGuid()).Select(s => s.getUserGuid());
|
|
clientToGame.Message.InstanceRoomMember.MemberGuid.Add(instanceRoomMembers);
|
|
|
|
GameServerApp.getServerLogic().onSendPacket(player, clientToGame);
|
|
}
|
|
|
|
// 입장 맴버 정보 패킷
|
|
{
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.JoinInstanceRoomMember = new ClientToGameMessage.Types.JoinInstanceRoomMember();
|
|
clientToGame.Message.JoinInstanceRoomMember.MemberGuid = player.getUserGuid();
|
|
|
|
BroadcastExcept(clientToGame, player);
|
|
}
|
|
|
|
// Concert 정보
|
|
if (_placeType == EPlaceType.Concert)
|
|
{
|
|
if (!_concertStart)
|
|
{
|
|
// 콘서트 정보 패킷
|
|
{
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.ConcertInfo = new ClientToGameMessage.Types.ConcertInfo();
|
|
clientToGame.Message.ConcertInfo.StartTime = _concertStartTime.ToTimestamp();
|
|
clientToGame.Message.ConcertInfo.RemainingSeat = Capacity - SessionCount;
|
|
|
|
Broadcast(clientToGame);
|
|
}
|
|
|
|
if (_isFullMemberStart)
|
|
{
|
|
if (SessionCount == Capacity)
|
|
{
|
|
_concertStart = true;
|
|
_concertStartTime = DateTime.UtcNow.AddSeconds(5);
|
|
_concertEndTime = _concertStartTime.AddSeconds(_concertLength);
|
|
|
|
// 콘서트 시작 패킷
|
|
await SendConcertStartPacket();
|
|
}
|
|
}
|
|
}
|
|
else // 콘서트 시작 후 입장
|
|
{
|
|
// 콘서트 시작 패킷
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.ConcertStart = new ClientToGameMessage.Types.ConcertStart();
|
|
clientToGame.Message.ConcertStart.StartTime = _concertStartTime.ToTimestamp();
|
|
clientToGame.Message.ConcertStart.EndTime = _concertEndTime.ToTimestamp();
|
|
|
|
GameServerApp.getServerLogic().onSendPacket(player, clientToGame);
|
|
}
|
|
}
|
|
|
|
if (_isPartyInstance)
|
|
{
|
|
var party = GameServerApp.getServerLogic().findGlobalEntity<GlobalParty>()?.getParty(_partyGuid);
|
|
var party_instance_action = party?.getEntityAction<GlobalPartyDetailInstanceAction>();
|
|
NullReferenceCheckHelper.throwIfNull(party_instance_action, () => $"GlobalPartyDetailInstanceAction is null !!! - party:{party?.toBasicString()}");
|
|
|
|
if (true == party_instance_action.isExist())
|
|
{
|
|
await party_instance_action.changePartyInstance(_concertStartTime.ToTimestamp(),
|
|
_concertEndTime.ToTimestamp(), m_players.Count, false, true);
|
|
}
|
|
}
|
|
|
|
if (_startBuffID != 0)
|
|
{
|
|
var buff_action = player.getEntityAction<BuffAction>();
|
|
NullReferenceCheckHelper.throwIfNull(buff_action, () => $"buff_action is null !!! - {player.toBasicString()}");
|
|
|
|
var (result, add_buff_attribute, del_buff_attribute) = buff_action.AddBuffProcess((uint)_startBuffID);
|
|
BuffNotifyHelper.send_S2C_NTF_DELETE_BUFF(player, del_buff_attribute);
|
|
BuffNotifyHelper.send_S2C_NTF_START_BUFF(player, add_buff_attribute);
|
|
}
|
|
|
|
|
|
//GameMode
|
|
(var handler_result, var gamemode_join_success_handler) = GameModeHelper.getGameModeJoinSuccessHandler(player, this, 1, _roomId);
|
|
if (handler_result.isFail() || gamemode_join_success_handler == null) return;
|
|
await gamemode_join_success_handler.joinSuccess();
|
|
}
|
|
|
|
async Task SendConcertStartPacket()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
foreach (var player in m_players.Values)
|
|
{
|
|
var fn_transaction_runner = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.ConcertStart = new ClientToGameMessage.Types.ConcertStart();
|
|
|
|
//List<ILogInvoker> invokers = new List<ILogInvoker>();
|
|
//var log_action = new LogAction(LogActionType.StageConcertStart);
|
|
|
|
if (_concertEnterItemId != 0 && _concertEnterItemCount != 0)
|
|
{
|
|
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {player.toBasicString()}");
|
|
|
|
(result, var deleted_items) = await inventory_action.tryDeleteItemByMetaId((uint)_concertEnterItemId, (ushort)_concertEnterItemCount);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
foreach (var deleted_item in deleted_items)
|
|
{
|
|
var deleted_item_attribute = deleted_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(deleted_item_attribute, () => $"deleted_item_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
ItemGuidCount item = new();
|
|
|
|
item.ItemGuid = deleted_item_attribute.ItemGuid;
|
|
item.ItemCount = deleted_item_attribute.ItemStackCount;
|
|
|
|
clientToGame.Message.ConcertStart.Items.Add(item);
|
|
}
|
|
|
|
//invokers.Add(new BusinessLogInvoker.ItemLog(itemlogData));
|
|
}
|
|
|
|
clientToGame.Message.ConcertStart.StartTime = _concertStartTime.ToTimestamp();
|
|
clientToGame.Message.ConcertStart.EndTime = _concertEndTime.ToTimestamp();
|
|
|
|
await QuestManager.It.QuestCheckWithoutTransaction(player, new QuestConcert(EQuestEventTargetType.CONCERT, EQuestEventNameType.STARTED, _instanceId));
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.None, server_logic.getDynamoDbClient());
|
|
{
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
batch.addQuery(new QueryFinal());
|
|
}
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to sendQueryAndBusinessLog() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
GameServerApp.getServerLogic().onSendPacket(player, clientToGame);
|
|
|
|
//var stage_log_info = StageBusinessLogHelper.toStageLogInfo(_instanceId, ContentsType.Concert, _roomId, SessionCount, Capacity);
|
|
|
|
//invokers.Add(new StageLog(stage_log_info));
|
|
|
|
//BusinessLogger.collectLogs(log_action, player._selectedChar, invokers);
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "ItemDelete", fn_transaction_runner);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task Leave(Player player, bool disconnected)
|
|
{
|
|
var user_guid = player.getUserGuid();
|
|
|
|
Log.getLogger().info($"InstanceRoom.Leave() Start !!! - userGuid:{user_guid}, instanceRoomId:{_roomId}, sessionCount:{SessionCount}, addConnectedUser:{getMap().getCurrCountAsAddConnectedUser()}");
|
|
|
|
if (m_players.TryRemove(player.getUserGuid(), out _))
|
|
{
|
|
await InstanceRoomHandler.leaveInstanceRoom(user_guid, _roomId);
|
|
}
|
|
|
|
var location_attribute = player.getEntityAttribute<LocationAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(location_attribute, () => $"LocationAttribute is null !!! - player:{player.toBasicString()}");
|
|
location_attribute.CurrentIndunLocation.clear();
|
|
|
|
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
|
await game_zone_action.tryLeaveGameZone();
|
|
|
|
if (SessionCount + getMap().getCurrCountAsAddConnectedUser() == 0)
|
|
{
|
|
if (!_isPartyInstance || _concertEnd)
|
|
{
|
|
await destroyRoom();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
{
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.LeaveInstanceRoomMember = new ClientToGameMessage.Types.LeaveInstanceRoomMember();
|
|
clientToGame.Message.LeaveInstanceRoomMember.MemberGuid = player.getUserGuid();
|
|
|
|
Broadcast(clientToGame);
|
|
}
|
|
|
|
if (_placeType == EPlaceType.Concert)
|
|
{
|
|
if (!_concertStart)
|
|
{
|
|
// 콘서트 정보 패킷
|
|
{
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.ConcertInfo = new ClientToGameMessage.Types.ConcertInfo();
|
|
clientToGame.Message.ConcertInfo.StartTime = _concertStartTime.ToTimestamp();
|
|
clientToGame.Message.ConcertInfo.RemainingSeat = Capacity - SessionCount;
|
|
|
|
Broadcast(clientToGame);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_isPartyInstance)
|
|
{
|
|
var party = GameServerApp.getServerLogic().findGlobalEntity<GlobalParty>()?.getParty(_partyGuid);
|
|
var party_instance_action = party?.getEntityAction<GlobalPartyDetailInstanceAction>();
|
|
|
|
if (true == party_instance_action?.isExist())
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(party, () => $"GlobalPartyDetail is null !!! - partyGuid:{_partyGuid}");
|
|
|
|
var log_invokers = new List<ILogInvoker>(2);
|
|
|
|
if (SessionCount == 0 && _concertEnd)
|
|
{
|
|
// party Instance Business Log 기록
|
|
var party_instance_log_data = PartyBusinessLogHelper.toPartyInstanceLogData(party.PartyGuid, false);
|
|
var party_instance_business_log = new PartyInstanceBusinessLog(party_instance_log_data);
|
|
log_invokers.Add(party_instance_business_log);
|
|
|
|
await party_instance_action.finishPartyInstance();
|
|
}
|
|
else
|
|
{
|
|
await party_instance_action.changeJoinMemberCount(m_players.Count, true);
|
|
|
|
// party Instance Business Log 기록
|
|
var party_instance_log_data = PartyBusinessLogHelper.toPartyInstanceLogData(party.PartyGuid, false);
|
|
var party_instance_business_log = new PartyInstanceBusinessLog(party_instance_log_data);
|
|
log_invokers.Add(party_instance_business_log);
|
|
}
|
|
|
|
// party member Business Log 기록
|
|
var party_member_log_data = PartyBusinessLogHelper.toPartyMemberLogData(party.PartyGuid, player.getUserGuid(), PartyMemberActionType.PartyInstanceLeave);
|
|
var party_member_business_log = new PartyMemberBusinessLog(party_member_log_data);
|
|
log_invokers.Add(party_member_business_log);
|
|
|
|
BusinessLogger.collectLogs(new LogActionEx(LogActionType.LeavePartyInstance), player, log_invokers);
|
|
}
|
|
}
|
|
|
|
Log.getLogger().info($"InstanceRoom.Leave() Finish !!! - userGuid:{user_guid}, instanceRoomId:{_roomId}, sessionCount:{SessionCount}, addConnectedUser:{getMap().getCurrCountAsAddConnectedUser()}");
|
|
}
|
|
|
|
public async Task<ServerErrorCode> ExchangeMyHome(string myhomeGuid, MyHomeInfo myhomeInfo, string roomId)
|
|
{
|
|
Map new_myhome_map = new();
|
|
await new_myhome_map.onInitFromMyhomeUgc(myhomeGuid, myhomeInfo.MyhomeUgcInfo, roomId);
|
|
|
|
foreach (var player in m_players.Values)
|
|
{
|
|
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
|
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!! - {player.toBasicString()}");
|
|
|
|
await game_zone_action.tryLeaveGameZone();
|
|
|
|
MyhomeNotifyHelper.send_S2C_NTF_MYHOME_UGC_INFO(player, myhomeInfo);
|
|
|
|
game_zone_action.tryEnterGameZone(new_myhome_map);
|
|
}
|
|
|
|
_map = new_myhome_map;
|
|
|
|
return ServerErrorCode.Success;
|
|
}
|
|
|
|
public ServerErrorCode MyhomeHostEnterEditRoom(string exceptUserGuid)
|
|
{
|
|
foreach (var player in m_players.Values)
|
|
{
|
|
if (player.getUserGuid() == exceptUserGuid)
|
|
continue;
|
|
|
|
MyhomeNotifyHelper.send_GS2C_NTF_MYHOME_HOST_ENTER_EDIT_ROOM(player);
|
|
}
|
|
|
|
return ServerErrorCode.Success;
|
|
}
|
|
|
|
public ServerErrorCode ExchangeCraft(string anchorGuid, Timestamp finish_craft_time)
|
|
{
|
|
foreach (var player in m_players.Values)
|
|
{
|
|
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
|
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!! - {player.toBasicString()}");
|
|
|
|
var ntf_packet = CraftNotifyHelper.makeNtfCraftUpdatePacket(anchorGuid, finish_craft_time);
|
|
GameServerApp.getServerLogic().onSendPacket(player, ntf_packet);
|
|
}
|
|
|
|
return ServerErrorCode.Success;
|
|
}
|
|
|
|
async Task SendConcertEnd()
|
|
{
|
|
isDestroy = true;
|
|
|
|
if (_isPartyInstance)
|
|
{
|
|
var party = GameServerApp.getServerLogic().findGlobalEntity<GlobalParty>()?.getParty(_partyGuid);
|
|
var party_instance_action = party?.getEntityAction<GlobalPartyDetailInstanceAction>();
|
|
NullReferenceCheckHelper.throwIfNull(party_instance_action, () => $"party instance action is null !!! - party:{party?.toBasicString()}");
|
|
|
|
if (true == party_instance_action.isExist())
|
|
{
|
|
await party_instance_action.finishPartyInstance(m_players.Count);
|
|
}
|
|
}
|
|
|
|
ClientToGame clientToGame = new ClientToGame();
|
|
clientToGame.Message = new ClientToGameMessage();
|
|
clientToGame.Message.NtfConcertEnd = new ClientToGameMessage.Types.GS2C_NTF_CONCERT_END();
|
|
|
|
Broadcast(clientToGame);
|
|
}
|
|
|
|
public int changeScreenPage(bool isCustom, bool isNext, int customPage)
|
|
{
|
|
if (isCustom)
|
|
{
|
|
_screenPageNo = customPage;
|
|
return _screenPageNo;
|
|
}
|
|
|
|
_screenPageNo = isNext ? _screenPageNo + 1 : _screenPageNo - 1;
|
|
if (_screenPageNo <= 0) _screenPageNo = 0;
|
|
|
|
return _screenPageNo;
|
|
}
|
|
|
|
public void Broadcast(ClientToGame message)
|
|
{
|
|
HostID[] allClients = m_players.Values.Select(s => s.getHostId()).ToArray();
|
|
GameServerApp.getServerLogic().onSendPacketToHosts(allClients, ServerCore.ProudNetHelper.compressRmi(), message);
|
|
}
|
|
|
|
public void BroadcastExcept(ClientToGame message, Player player)
|
|
{
|
|
HostID[] allClients = m_players.Values.Where(s => s.getUserGuid() != player.getUserGuid()).Select(s => s.getHostId()).ToArray();
|
|
GameServerApp.getServerLogic().onSendPacketToHosts(allClients, ServerCore.ProudNetHelper.compressRmi(), message);
|
|
}
|
|
|
|
public void BroadcastExcept(ClientToGame message, USER_GUID userGuid)
|
|
{
|
|
HostID[] allClients = m_players.Values.Where(s => s.getUserGuid() != userGuid).Select(s => s.getHostId()).ToArray();
|
|
GameServerApp.getServerLogic().onSendPacketToHosts(allClients, ServerCore.ProudNetHelper.compressRmi(), message);
|
|
}
|
|
|
|
public async Task KeepAlive(CancellationToken cancelToken)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var instance_room_storage = new InstanceRoomStorage();
|
|
instance_room_storage.Init(server_logic.getRedisDb(), "");
|
|
|
|
while (cancelToken.IsCancellationRequested == false)
|
|
{
|
|
try
|
|
{
|
|
await Task.Delay(ServerCommon.Constant.KEEP_INSTANCE_ROOM_TIME, cancelToken);
|
|
|
|
await instance_room_storage.keepInstanceRoom(_roomId);
|
|
|
|
if (!InstanceRoomHandler.isOnlyOneInstanceRoomID(_roomId))
|
|
{
|
|
var instance_room_id_base = InstanceRoomHandler.getInstanceRoomIdBaseFromInstanceRoomId(_roomId);
|
|
|
|
await instance_room_storage.keepInstanceRoomList(instance_room_id_base);
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.getLogger().error($"{ex}");
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task CheckConcertTime(CancellationToken cancelToken)
|
|
{
|
|
while (cancelToken.IsCancellationRequested == false)
|
|
{
|
|
try
|
|
{
|
|
if (_concertStartTime < DateTime.UtcNow && !_concertStart)
|
|
{
|
|
_concertStart = true;
|
|
|
|
await SendConcertStartPacket();
|
|
}
|
|
|
|
if (_concertEndTime < DateTime.UtcNow && !_concertEnd)
|
|
{
|
|
_concertEnd = true;
|
|
|
|
await SendConcertEnd();
|
|
}
|
|
|
|
if (_concertEnd && SessionCount == 0)
|
|
{
|
|
await destroyRoom();
|
|
|
|
InstanceRoomManager.Instance.DestroyRoom(_roomId);
|
|
}
|
|
|
|
await Task.Delay(1000, cancelToken);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.getLogger().error($"{ex}");
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Map getMap()
|
|
{
|
|
return _map;
|
|
}
|
|
|
|
public int getInstanceId()
|
|
{
|
|
return _instanceId;
|
|
}
|
|
|
|
public async Task destroyRoom()
|
|
{
|
|
isDestroy = true;
|
|
|
|
_cts.Cancel();
|
|
_map.DestroyP2PGroup();
|
|
_map.getCancellationToken().Cancel();
|
|
|
|
await InstanceRoomHandler.deleteInstanceRoom(_roomId);
|
|
|
|
Log.getLogger().info($"InstanceRoom.destroyRoom() Complete !!! - instanceRoomId:{_roomId}");
|
|
}
|
|
|
|
//public async Task CheckSession(CancellationToken cancelToken)
|
|
//{
|
|
// List<Player> errorPlayer = new();
|
|
|
|
// while (cancelToken.IsCancellationRequested == false || SessionCount == 0)
|
|
// {
|
|
// try
|
|
// {
|
|
// foreach (var (key, player) in m_players)
|
|
// {
|
|
// if (player.IsClosedProcessed)
|
|
// {
|
|
// Log.getLogger().error($"{player.getUserGuid()} Closed Session in InstanceRoom");
|
|
// errorPlayer.Add(player);
|
|
|
|
// continue;
|
|
// }
|
|
// }
|
|
|
|
// foreach (var player in errorPlayer)
|
|
// {
|
|
// if (!await InstanceRoomManager.Instance.LeaveRoom(player, _roomId))
|
|
// await Leave(player);
|
|
// }
|
|
|
|
// errorPlayer.Clear();
|
|
|
|
// await Task.Delay(1000, cancelToken);
|
|
// }
|
|
// catch (OperationCanceledException)
|
|
// {
|
|
// break;
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// Log.getLogger().error($"{ex}");
|
|
// throw;
|
|
// }
|
|
// }
|
|
//}
|
|
} |