/// <summary> /// 线程安全的操作 /// </summary> /// <param name="msg"></param> /// <returns></returns> public virtual bool PostLocalMessage(ILocalMessage msg) { if (IsAvaliable()) { return(m_client.PostLocalMessage(msg)); } return(false); }
public LocalPublicationFilterEventArgs(ILocalSubscription subscription, ILocalMessage <TPayload> message) { subscription.EnsureNotNull(nameof(subscription)); message.EnsureNotNull(nameof(message)); // _subscription = subscription; _message = message; }
public LocalPublicationFilterState(ILocalMessage message, ILocalSubscription subscription) { message.EnsureNotNull(nameof(message)); subscription.EnsureNotNull(nameof(subscription)); // _message = message; _subscription = subscription; }
/// <summary> /// 将本地消息发送给Client /// Client接收到消息将在虚拟线程的任务1中交给玩家现场处理 /// </summary> /// <param name="msg">Message.</param> public bool PostLocalMessage(ILocalMessage msg) { if (!Closed) { m_localMessages.Enqueue(msg); return(true); } return(false); }
internal LocalPostingToken(ILocalMessage message, bool disposeMessageAtEndOfPosting) { message.EnsureNotNull(nameof(message)); // _disposeMessageAtEndOfPosting = disposeMessageAtEndOfPosting; _postingCount = 0; _message = message; _completedPostingCountdown = 0; }
/// <summary> /// 向功能系统发送本地消息 /// </summary> /// <typeparam name="System"></typeparam> /// <param name="msg"></param> public void PostMessageToSystem <System>(ILocalMessage msg) where System : BaseSystem { BaseSystem baseSystem = m_systemDic[typeof(System)]; if (baseSystem == null) { Log.Fatal("TypeSystem::" + typeof(System) + "不存在,消息Message::" + msg.GetType() + "发送失败"); return; } baseSystem.PostLocalMessage(msg); }
/// <summary> /// 广播localmsg /// </summary> /// <param name="lmsg"></param> /// <param name="filter"></param> public void BroadcastLocalMessage(ILocalMessage msg, BroadcastFilter filter = null) { foreach (var item in m_playerSid2CtxDic) { // 使用过滤器 if (filter != null && !filter(item.Value)) { continue; } item.Value.PostLocalMessage(msg); } }
internal LocalPostingToken(ILocalMessage message, int postingCount, bool disposeMessageAtEndOfPosting) { message.EnsureNotNull(nameof(message)); postingCount .Arg(nameof(postingCount)) .EnsureNotLessThan(operand: 1); // _disposeMessageAtEndOfPosting = disposeMessageAtEndOfPosting; _postingCount = postingCount; _message = message; _completedPostingCountdown = postingCount; }
/// <summary> /// 按照ContextIds 多播数据 /// 适用于contextIds相比于m_playerSid2CtxDic,集合小很多的情况 /// </summary> /// <param name="msg"></param> /// <param name="contextIds"></param> public void BroadcastLocalMessageByContextIds(ILocalMessage msg, List <UInt64> contextIds) { IManagedContext context; foreach (var id in contextIds) { if (m_playerSid2CtxDic.TryGetValue(id, out context)) { context.PostLocalMessage(msg); } } }
/// <summary> /// 向一个玩家发送本地消息 /// </summary> /// <param name="msg"></param> /// <param name="playerId"></param> public void SendSingleLocalMessage(ILocalMessage msg, string playerId) { if (playerId == null || playerId == default) { return; } var playerCtx = FindPlayerContextByString(playerId); if (playerCtx != null) { playerCtx.PostLocalMessage(msg); } }
/// <summary> /// 重写 但要保留基现场的逻辑 /// </summary> /// <param name="msg">本地消息类型</param> /// <returns></returns> public override Task OnMessage(ILocalMessage msg) { switch (msg.MessageId) { case GameServerConstDefine.LocalMsgGameServerContextTransformOK: return(OnLMsgOnContextTransformOk((LocalMessageContextTransformOk)msg)); case GameServerConstDefine.LocalMsgShutdownContext: return(OnLMsgShutdownContext((LocalMessageShutdownContext)msg)); default: return(base.OnMessage(msg)); } }
public static LocalMessageData Create(ILocalMessage data) { if (data is LocalMessageData r) { return(r); } return(new LocalMessageData { Id = data.Id, Channel = data.Channel, MessageType = data.MessageType, Provider = data.Provider, Content = data.Content, Timestamp = data.Timestamp }); }
/// <summary> /// 向多个玩家发送本地消息 /// </summary> /// <param name="msg"></param> /// <param name="playerId"></param> public void BroadcastLocalMessagebyPlayerId(ILocalMessage msg, List <string> playerIds) { if (playerIds == null) { return; } foreach (var id in playerIds) { var playerCtx = FindPlayerContextByString(id); if (playerCtx != null) { playerCtx.PostLocalMessage(msg); } } }
// TODO: Put strings into the resources. // Task P_HandleAppStartedNotificationAsync(ILocalSubscription subscription, ILocalMessage <IXAppStartedEventArgs> message, IContext ctx) { try { subscription.EnsureNotNull(nameof(subscription)); message.EnsureNotNull(nameof(message)); ctx.EnsureNotNull(nameof(ctx)); // if (ctx.IsCancellationRequested()) { return(Task.FromCanceled(cancellationToken: ctx.Ct())); } else if (HasDeactivationRequested || !IsActive || !subscription.IsActive || !ReferenceEquals(subscription, TryReadDA(ref _appStartedSubscription))) { return(Task.CompletedTask); } else { var retryOptions = TryReadDA(ref _retryOptions, considerDisposeRequest: true); if (retryOptions is null) { if (!IsDisposeRequested) { EnsureInitialized(); } return(TaskUtilities.FromCanceled()); } else { #if !DO_NOT_USE_EON_LOGGING_API var logMessagePrologue = $"Отложенная активация. ИД корреляции: {ctx.FullCorrelationId}."; this .IssueInformation( messagePrologue: logMessagePrologue, message: "Получено уведомление о запуске приложения. Начало активации.", severityLevel: SeverityLevel.Medium); #endif P_StartComponentActivationAttempt(retryOptions: retryOptions, rethrowException: false, retryAttemptIndex: -1, correlationId: ctx.FullCorrelationId, ct: message.Payload.App.AppShutdownToken); return(Task.CompletedTask); } } } catch (Exception exception) { return(Task.FromException(exception)); } }
public static LocalMessageDto ToDto(this ILocalMessage localMessage) { LocalMessageChannel channel = LocalMessageChannel.Unspecified; LocalMessageType messageType = LocalMessageType.Info; if (localMessage.Channel.TryParse(out LocalMessageChannel localMessageChannel)) { channel = localMessageChannel; } if (localMessage.MessageType.TryParse(out LocalMessageType localMessageType)) { messageType = localMessageType; } return(new LocalMessageDto { Channel = channel, Content = localMessage.Content, MessageType = messageType, Provider = localMessage.Provider, Timestamp = Timestamp.GetTimestamp(localMessage.Timestamp) }); }
public override Task OnMessage(ILocalMessage msg) { switch (msg.MessageId) { case GameServerConstDefine.BattleSystemCreateBattleBarrier: OnCreateBattleBarrier((CreateBattleBarrierMessage)msg); break; case GameServerConstDefine.BattleSystemCommandUpLoad: var commandBattleLocalMessage = msg as CommandBattleLocalMessage; OnBattleCommand(commandBattleLocalMessage); break; case GameServerConstDefine.BattleSystemExitBattleBarrier: var exitBattleLocal = msg as ExitBattleLocalMessage; OnExitBattle(exitBattleLocal); break; case GameServerConstDefine.BattleSystemClientReadyBattle: var clientReadyBattleLocalMessage = msg as ClientReadyBattleLocalMessage; OnReadyBattle(clientReadyBattleLocalMessage); break; case GameServerConstDefine.BattleSystemPlayerShutdown: var toBattlePlayerShutdownMessage = msg as ToBattlePlayerShutdownMessage; OnPlayerShutdown(toBattlePlayerShutdownMessage.playerId); break; case GameServerConstDefine.BattleSystemNeedReleaseBattleTimer: var releaseBattleTimerLocalMessage = msg as ReleaseBattleTimerLocalMessage; OnReleaseBattleTimer(releaseBattleTimerLocalMessage.TimerId); break; default: return(base.OnMessage(msg)); } return(Task.CompletedTask); }
/// <summary> /// 该方法需要被重写 /// </summary> /// <param name="msg"></param> /// <returns></returns> public virtual Task OnMessage(ILocalMessage msg) { return(Task.CompletedTask); }
public async Task <ILocalMessagePostingToken> PublishMessageAsync(ILocalMessage message, bool disposeMessageAtEndOfPosting) // TODO_HIGH: To implement the forcing of new task for publication. // => await P_PublishMessageAsync(message, disposeMessageAtEndOfPosting).ConfigureAwait(false);
public LocalMessageViewModel(ILocalMessage data) { _data = data; data.MessageType.TryParse(out _messageTypeEnum); data.Channel.TryParse(out _channel); }
// TODO: Put strings into the resources. // static async Task <IList <ILocalSubscription> > P_PublicationFilterAsync(IRunControl publisherRunControl, ILocalMessage msg, IList <ILocalSubscription> sourceSubscriptions) { publisherRunControl.EnsureNotNull(nameof(publisherRunControl)); msg.EnsureNotNull(nameof(msg)); sourceSubscriptions.EnsureNotNull(nameof(sourceSubscriptions)); // if (sourceSubscriptions.Count < 1 || publisherRunControl.HasStopRequested) { return(new ILocalSubscription[0]); } else { var sourceSubscriptionsList = new List <ILocalSubscription>(); var length = sourceSubscriptions.Count; for (var offset = 0; offset < length; offset++) { var subscription = sourceSubscriptions[offset]; if (subscription is null) { throw new ArgumentException( paramName: $"{nameof(sourceSubscriptions)}[{offset:d}]", message: FormatXResource(typeof(Array), "CanNotContainNull/NullAt", offset.ToString("d"))); } sourceSubscriptionsList.Add(subscription); } // var filterResultList = new List <ILocalSubscription>(); for (var i = 0; i < sourceSubscriptionsList.Count; i++) { if (publisherRunControl.HasStopRequested) { break; } // var subscription = sourceSubscriptionsList[i]; var subscriptionFilterResult = await subscription.PublicationFilterAsync(state : new LocalPublicationFilterState(message: msg, subscription: subscription)).ConfigureAwait(false); if (!subscriptionFilterResult.CancelPublication) { filterResultList.Add(subscription); } } // if (publisherRunControl.HasStopRequested) { return(new ILocalSubscription[0]); } else { return(filterResultList); } } }
/// <summary> /// 以下要处理收到的消息 /// </summary> /// <param name="msg"></param> /// <returns></returns> public override Task OnMessage(ILocalMessage msg) { switch (msg.MessageId) { case GameServerConstDefine.MatchSystemCreateMatchTeam: CreateMatchTeamMessage createMatchTeamMessage = msg as CreateMatchTeamMessage; OnCreateMatchTeam(createMatchTeamMessage.playerId); break; case GameServerConstDefine.MatchSystemJoinMatchTeam: JoinMatchTeamMessage joinMatchTeamMessage = msg as JoinMatchTeamMessage; OnJoinMatchTeam(joinMatchTeamMessage.teamId, joinMatchTeamMessage.playerId); break; case GameServerConstDefine.MatchSystemExitMatchTeam: ExitMatchTeamMessage exitMatchTeamMessage = msg as ExitMatchTeamMessage; OnExitMatchTeam(exitMatchTeamMessage.teamId, exitMatchTeamMessage.playerId); break; case GameServerConstDefine.MatchSystemJoinMatchQueue: JoinMatchQueueMessage joinMatchQueueMessage = msg as JoinMatchQueueMessage; OnJoinMatchQueue(joinMatchQueueMessage.teamId, joinMatchQueueMessage.playerId, joinMatchQueueMessage.barrierId); break; case GameServerConstDefine.MatchSystemExitMatchQueue: ExitMatchQueueMessage exitMatchQueueMessage = msg as ExitMatchQueueMessage; OnExitMatchQueue(exitMatchQueueMessage.teamId, exitMatchQueueMessage.playerId); break; case GameServerConstDefine.MatchQueueCompleteSingle: //来自 MatcingSystemQueue 的消息,通知system匹配完成 MatchQueueCompleteSingleMessage matchQueueCompleteSingleMessage = msg as MatchQueueCompleteSingleMessage; OnCompleteMatching(matchQueueCompleteSingleMessage.teamIds, matchQueueCompleteSingleMessage.barrierId); break; case GameServerConstDefine.MatchSysteamMatchTeamUpdateInfo: MatchTeamUpdateInfoMessage matchTeamUpdateInfoMessage = msg as MatchTeamUpdateInfoMessage; OnUpdateMatchTeam(matchTeamUpdateInfoMessage.teamId); break; case GameServerConstDefine.MatchSystemPlayerShutdown: ToMatchPlayerShutdownMessage toMatchPlayerShutdownMessage = msg as ToMatchPlayerShutdownMessage; OnShutdownPlayer(toMatchPlayerShutdownMessage); break; case GameServerConstDefine.UpdateOnlinePlayerList: //更新客户端在线玩家状态 UpdateOnlinePlayerMessage updateOnlinePlayerMessage = msg as UpdateOnlinePlayerMessage; OnUpdateOnlinePlayerRpc(updateOnlinePlayerMessage); break; case GameServerConstDefine.ReleaseBattleToMatchTeam: ReleaseBattleToMatchTeamMessage releaseBattleToMatchTeamMessage = msg as ReleaseBattleToMatchTeamMessage; OnReleaseBattle(releaseBattleToMatchTeamMessage); break; default: break; } return(base.OnMessage(msg)); }
public override bool PostLocalMessage(ILocalMessage msg) { return(base.PostLocalMessage(msg)); }
/// <summary> /// 向多个玩家发送本地消息 /// </summary> /// <param name="msg"></param> /// <param name="playerIds"></param> protected void PostLocalMessageToCtx(ILocalMessage msg, List <string> playerIds) { ServerBase.Instance.PlayerCtxManager.BroadcastLocalMessagebyPlayerId(msg, playerIds); }
/// <summary> /// 向一个玩家发送本地消息 /// </summary> /// <param name="msg"></param> /// <param name="playerId"></param> protected void PostLocalMessageToCtx(ILocalMessage msg, string playerId) { ServerBase.Instance.PlayerCtxManager.SendSingleLocalMessage(msg, playerId); }
/// <summary> /// 接收传入的本地消息,玩家现场向GameServer发送的消息 /// </summary> /// <param name="msg"></param> /// <returns></returns> public virtual bool PostLocalMessage(ILocalMessage msg) { p_localMessages.Enqueue(msg); return(true); }
async Task <ILocalMessagePostingToken> P_PublishMessageAsync(ILocalMessage msg, bool disposeMessageAtEndOfPosting) { msg.EnsureNotNull(nameof(msg)); // ILocalMessagePostingToken postingToken; IRunControl runControl = ReadDA(ref _runControl); IList <ILocalSubscription> subscriptions = ReadDA(ref _subscriptionsSpinLock).Invoke(() => ReadDA(ref _subscriptionsList).Where(i => i.IsActive).ToArray()); subscriptions = await P_PublicationFilterAsync(publisherRunControl : runControl, msg : msg, sourceSubscriptions : subscriptions).ConfigureAwait(false); if (subscriptions.Count > 0 && !runControl.HasStopRequested) { var postingTokenStricted = new LocalPostingToken(message: msg, postingCount: subscriptions.Count, disposeMessageAtEndOfPosting: disposeMessageAtEndOfPosting); postingToken = postingTokenStricted; var postingQueueEntry = default(LocalPostingQueueEntry); try { postingQueueEntry = new LocalPostingQueueEntry(postingToken: postingTokenStricted, postingSubscriptions: subscriptions); var postingQueueLength = ReadDA(ref _postingQueueSpinLock) .Invoke( () => { var locPostingQueue = ReadDA(ref _postingQueue); locPostingQueue.Enqueue(postingQueueEntry); return(locPostingQueue.Count); }); #if TRG_NETFRAMEWORK if (postingQueueLength >= __PostingQueueLengthWarning) { try { throw new InvalidOperationException( message: $"Длина очереди доставки сообщений достигла предела предупреждения '{__PostingQueueLengthWarning:d}' и составляет '{postingQueueLength:d}'.{Environment.NewLine}Слишком большая очередь доставки сообщений свидетельствует о некорректной работе компонентов, выполняющих доставку сообщений, либо о слишком большом потоке сообщений.{Environment.NewLine}Данное событие не прерывает работу, если оно успешно записано в системый журнал событий."); } catch (Exception firstException) { WindowsEventLogUtilities.WriteFaultToEventLog(fault: firstException, failFastOnError: true, faultFormattingOptions: ExceptionInfoFormattingOptions.Full); } } #else // TODO_HIGH: Implement logging (as for TRG_NETFRAMEWORK). // // ... #endif // Уведомление воркеров (рабочих элементов, обрабатывающих доставку сообщений). // var postingWorkers = ReadDA(ref _postingWorkers); for (var i = 0; i < postingWorkers.Length; i++) { ILocalPostingWorker postingWorker = ReadDA(ref postingWorkers[i]); postingWorker.BreakLoopIdle(); #if TRG_NETFRAMEWORK if (!postingWorker.IsLoopAlive) { if (!runControl.HasStopRequested) { try { throw new InvalidOperationException( message: $"Один из рабочих элементов (#{(i + 1):d} из {postingWorkers.Length:d}), выполняющий доставку сообщений, находится в нерабочем состоянии.{Environment.NewLine}Данное событие не прерывает работу, если оно успешно записано в системый журнал событий."); } catch (Exception firstException) { WindowsEventLogUtilities.WriteFaultToEventLog(fault: firstException, failFastOnError: true, faultFormattingOptions: ExceptionInfoFormattingOptions.Full); } } } // TimeSpan?currentPostingDuration; if ((currentPostingDuration = postingWorker.CurrentlyPostingDuration) >= __PostingOperationDurationWarning) { var currentPostingSubscription = postingWorker.CurrentlyPostingSubscription; try { throw new InvalidOperationException( message: $"Время выполнения операции доставки, выполняемой одним из рабочих элементов (#{(i + 1):d} из {postingWorkers.Length:d}), достигло предела предупреждения '{__PostingOperationDurationWarning.ToString("c")}' и составляет '{currentPostingDuration.Value.ToString("c")}'.{Environment.NewLine}\tПодписка, согласно которой выполняется доставка:{currentPostingSubscription.FmtStr().GNLI2()}{Environment.NewLine}Данное событие не прерывает работу, если оно успешно записано в системый журнал событий.{Environment.NewLine}Указанное событие сообщает о том, что один из рабочих элементов уже слишком долго выполняет операцию доставки, что не является нормальным."); } catch (Exception firstException) { WindowsEventLogUtilities.WriteFaultToEventLog(fault: firstException, failFastOnError: true, faultFormattingOptions: ExceptionInfoFormattingOptions.Full); } } #else // TODO_HIGH: Implement logging (as for TRG_NETFRAMEWORK). // // ... #endif } } catch (Exception exception) { postingQueueEntry?.Dispose(exception); throw; } } else { postingToken = new LocalPostingToken(message: msg, disposeMessageAtEndOfPosting: disposeMessageAtEndOfPosting); if (disposeMessageAtEndOfPosting) { msg.Dispose(); } } return(postingToken); }
public AddLocalMessageCommand(ILocalMessage input) { this.Input = input; }
public virtual Task <ILocalMessagePostingToken> PublishMessageAsync(ILocalMessage message, bool disposeMessageAtEndOfPosting) => InnerPublisher.PublishMessageAsync(message: message, disposeMessageAtEndOfPosting: disposeMessageAtEndOfPosting);
/// <summary> /// 消息都走这里,从网络来的消息 或者是内部产生的消息 都走这里 /// </summary> /// <param name="msg"></param> /// <returns></returns> public virtual async Task OnMessage(ILocalMessage msg) { //在这里将处理一系列消息 switch (msg.MessageId) { //AsyncAction消息的回调 case ServerBaseLocalMesssageIDDef.LocalMsgAsyncActionResult: ContextAsyncAction contextAsyncAction = msg as ContextAsyncAction; contextAsyncAction.OnResultInternal(); //执行回调 break; case ServerBaseLocalMesssageIDDef.NetMessage: //如何是网络消息就通过分发器进行分发 NetClientMessage message = msg as NetClientMessage; MessageDispather.Instance.Handle(this, message.MessageInfo); //在这里将消息进行分发 直接调用逻辑handler break; case ServerBaseLocalMesssageIDDef.RpcNetMessage: RpcNetClientMessage rpcmessage = msg as RpcNetClientMessage; var response = (IResponse)rpcmessage.MessageInfo.Message; if (response == null) { throw new Exception($"flag is response, but message is not! {rpcmessage.MessageInfo.Opcode}"); } Action <IResponse> action; if (!m_requestCallback.TryGetValue(response.RpcId, out action)) { return; } m_requestCallback.Remove(response.RpcId); action(response); //这里处理逻辑 返回await break; case ServerBaseLocalMesssageIDDef.LocalMsgPlayCtxTimer: //现场计时任务回调感知 { PlayerTimerMessage timerMsg = msg as PlayerTimerMessage; await OnPlayerContextTimer(timerMsg); return; } case ServerBaseLocalMesssageIDDef.SystemSendNetMessage: var snm = (SystemSendNetMessage)msg; if (snm.Message == null) { Log.Debug("要发送的网络消息为空"); return; } //Log.Info("系统向玩家发送消息 " + snm.PlayerId + " " + snm.Message.GetType()); //S2C_SyncLevelStateBattleMessage syncLevelStateBattleMessage = snm.Message as S2C_SyncLevelStateBattleMessage; //if (syncLevelStateBattleMessage != null) //{ // Log.Info("服务器转发延迟 = "+(DateTime.Now.Ticks - syncLevelStateBattleMessage.Time)/10000); //} Send(snm.Message); break; default: break; } //本地消息和网络消息分开 //收到的如果是网络消息就通过分发器进行分发 分发器由ServerBase维护 //收到的是本地消息就在本地进行处理 return; }
public override Task OnMessage(ILocalMessage msg) { return(base.OnMessage(msg)); }