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 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 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()?.getParty(roomIdElemnet[1]); var party_instance_action = party?.getEntityAction(); 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(); 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(); 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 invokers = new List(); //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(); //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()?.getParty(_partyGuid); var party_instance_action = party?.getEntityAction(); 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(); 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 invokers = new List(); //var log_action = new LogAction(LogActionType.StageConcertStart); if (_concertEnterItemId != 0 && _concertEnterItemCount != 0) { var inventory_action = player.getEntityAction(); 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(); 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(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(); NullReferenceCheckHelper.throwIfNull(location_attribute, () => $"LocationAttribute is null !!! - player:{player.toBasicString()}"); location_attribute.CurrentIndunLocation.clear(); var game_zone_action = player.getEntityAction(); 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()?.getParty(_partyGuid); var party_instance_action = party?.getEntityAction(); if (true == party_instance_action?.isExist()) { NullReferenceCheckHelper.throwIfNull(party, () => $"GlobalPartyDetail is null !!! - partyGuid:{_partyGuid}"); var log_invokers = new List(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 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(); 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(); 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()?.getParty(_partyGuid); var party_instance_action = party?.getEntityAction(); 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 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; // } // } //} }