/// <summary> /// Deserialize the MmMetadataBlock /// </summary> /// <param name="reader">UNET based deserializer object</param> public virtual void Deserialize(NetworkReader reader) { LevelFilter = (MmLevelFilter)reader.ReadInt16(); ActiveFilter = (MmActiveFilter)reader.ReadInt16(); SelectedFilter = (MmSelectedFilter)reader.ReadInt16(); NetworkFilter = (MmNetworkFilter)reader.ReadInt16(); Tag = (MmTag)reader.ReadInt16(); }
/// <summary> /// Copy Constructor for MmMetadataBlock /// </summary> /// <param name="original">MmMetadataBlock to be copied.</param> public MmMetadataBlock(MmMetadataBlock original) { LevelFilter = original.LevelFilter; ActiveFilter = original.ActiveFilter; SelectedFilter = original.SelectedFilter; NetworkFilter = original.NetworkFilter; Tag = original.Tag; }
/// <summary> /// Deserialize the MmMetadataBlock /// </summary> /// <param name="data">Object array representation of a MmMetadataBlock</param> /// <param name="index">The index of the next element to be read from data</param> /// <returns>The index of the next element to be read from data</returns> public virtual int Deserialize(object[] data, int index) { LevelFilter = (MercuryMessaging.MmLevelFilter)((short)data[index++]); ActiveFilter = (MercuryMessaging.MmActiveFilter)((short)data[index++]); SelectedFilter = (MercuryMessaging.MmSelectedFilter)((short)data[index++]); NetworkFilter = (MercuryMessaging.MmNetworkFilter)((short)data[index++]); Tag = (MercuryMessaging.MmTag)((short)data[index++]); return(index); }
/// <summary> /// Create an MmMetadataBlock /// </summary> /// <param name="tag"></param> /// <param name="levelFilter"><see cref="MmLevelFilter"/></param> /// <param name="activeFilter"><see cref="MmActiveFilter"/></param> /// <param name="selectedFilter"><see cref="MmSelectedFilter"/></param> /// <param name="networkFilter"><see cref="MmNetworkFilter"/></param> public MmMetadataBlock(MmTag tag, MmLevelFilter levelFilter = MmLevelFilterHelper.Default, MmActiveFilter activeFilter = default(MmActiveFilter), MmSelectedFilter selectedFilter = default(MmSelectedFilter), MmNetworkFilter networkFilter = default(MmNetworkFilter)) { LevelFilter = levelFilter; ActiveFilter = activeFilter; SelectedFilter = selectedFilter; NetworkFilter = networkFilter; Tag = tag; }
/// <summary> /// Create an MmMetadataBlock /// </summary> /// <param name="levelFilter"><see cref="MmLevelFilter"/></param> /// <param name="activeFilter"><see cref="MmActiveFilter"/></param> /// <param name="selectedFilter"><see cref="MmSelectedFilter"/></param> /// <param name="networkFilter"><see cref="MmNetworkFilter"/></param> public MmMetadataBlock( MmLevelFilter levelFilter = MmLevelFilterHelper.Default, MmActiveFilter activeFilter = MmActiveFilter.Active, MmSelectedFilter selectedFilter = MmSelectedFilter.All, MmNetworkFilter networkFilter = MmNetworkFilter.All) { LevelFilter = levelFilter; ActiveFilter = activeFilter; SelectedFilter = selectedFilter; NetworkFilter = networkFilter; Tag = MmTagHelper.Everything; }
/// <summary> /// This method determines if a particular MmResponder should /// receive a message via MmInvoke. /// This performs 4 checks: Tag Check, Level Check, Active Check, & Selected Check. /// </summary> /// <param name="levelFilter">Extracted message level filter - before adjust.</param> /// <param name="activeFilter">Extracted message active filter - before adjust.</param> /// <param name="selectedFilter">Extracted message selected filter - before adjust.</param> /// <param name="networkFilter">Extracted message network filter - before adjust.</param> /// <param name="mmRoutingTableItem">RoutingTableItem of currently observed MmResponder</param> /// <param name="message">MmMessage to be checked.</param> /// <returns>Returns whether responder has passed all checks.</returns> protected virtual bool ResponderCheck(MmLevelFilter levelFilter, MmActiveFilter activeFilter, MmSelectedFilter selectedFilter, MmNetworkFilter networkFilter, MmRoutingTableItem mmRoutingTableItem, MmMessage message) { if (!TagCheck(mmRoutingTableItem, message)) { return(false); // Failed TagCheck } return(LevelCheck(levelFilter, mmRoutingTableItem.Responder, mmRoutingTableItem.Level) && ActiveCheck(activeFilter, mmRoutingTableItem.Responder) && SelectedCheck(selectedFilter, mmRoutingTableItem.Responder) && NetworkCheck(mmRoutingTableItem, message)); }
/// <summary> /// Create an MmMessage, with filters defined directly /// </summary> /// <param name="mmMethod">Identifier of target MmMethod</param> /// <param name="levelFilter">Determines direction of messages</param> /// <param name="activeFilter">Determines whether message sent to active and/or inactive objects</param> /// <param name="selectedFilter">Determines whether message sent to objects "selected" as defined by MmRelayNode implementation</param> /// <param name="networkFilter">Determines whether message will remain local or can be sent over the network</param> public MmMessage(MmMethod mmMethod, MmLevelFilter levelFilter, MmActiveFilter activeFilter, MmSelectedFilter selectedFilter, MmNetworkFilter networkFilter) { MmMethod = mmMethod; MetadataBlock = new MmMetadataBlock(); MetadataBlock.LevelFilter = levelFilter; MetadataBlock.ActiveFilter = activeFilter; MetadataBlock.SelectedFilter = selectedFilter; MetadataBlock.NetworkFilter = networkFilter; }
/// <summary> /// Overrides MmRelayNode's Selected check to handle the FSM's current state. /// </summary> /// <param name="selectedFilter"><see cref="SelectedCheck"/></param> /// <param name="responder">Observed MmResponder.</param> /// <returns></returns> protected override bool SelectedCheck(MmSelectedFilter selectedFilter, IMmResponder responder) { return(selectedFilter == MmSelectedFilter.All || (RespondersFSM.Current != null && responder.MmGameObject == RespondersFSM.Current.Responder.MmGameObject)); }
/// <summary> /// Determine if MmResponder passes MmRelayNode selected filter check using value embedded in MmMessage. /// </summary> /// <param name="selectedFilter">Selected filter value extracted from MmMessage.</param> /// <param name="responder">Observed MmResponder</param> /// <returns>Returns whether observed MmResponder has passed selected filter check. /// In base MmRelayNode, this always returns true.</returns> protected virtual bool SelectedCheck(MmSelectedFilter selectedFilter, IMmResponder responder) { return(true); }
/// <summary> /// Invoke an MmMethod. /// </summary> /// <param name="msgType">Type of message. This specifies /// the type of the payload. This is important in /// networked scenarios, when proper deseriaization into /// the correct type requires knowing what was /// used to serialize the object originally. /// </param> /// <param name="message">The message to send. /// This class builds on UNET's MessageBase so it is /// Auto [de]serialized by UNET.</param> public override void MmInvoke(MmMessageType msgType, MmMessage message) { //If the MmRelayNode has not been initialized, initialize it here, // and refresh the parents - to ensure proper routing can occur. InitializeNode(); //TODO: Switch to using mutex for threaded applications doNotModifyRoutingTable = true; MmNetworkFilter networkFilter = message.MetadataBlock.NetworkFilter; //Experimental: Allow forced serial execution (ordered) of messages. //if (serialExecution) //{ // if (!_executing) // { // _executing = true; // } // else // { // MmLogger.LogFramework("<<<<<>>>>>Queueing<<<<<>>>>>"); // KeyValuePair<MmMessageType, MmMessage> newMessage = // new KeyValuePair<MmMessageType, MmMessage>(msgType, message); // SerialExecutionQueue.Enqueue(newMessage); // return; // } //} //MmLogger.LogFramework (gameObject.name + ": MmRelayNode received MmMethod call: " + param.MmMethod.ToString ()); // If an MmNetworkResponder is attached to this object, and the MmMessage has not already been deserialized // then call the MmNetworkResponder's network message invocation function. if (MmNetworkResponder != null && message.MetadataBlock.NetworkFilter != MmNetworkFilter.Local && !message.IsDeserialized) { //if (!dirty) //{ // dirty = true; // message.TimeStamp = DateTime.UtcNow.ToShortTimeString(); // _prevMessageTime = message.TimeStamp; //} //This will ensure that beyond the point at which a message is determined to be sendable, // it will not be treated as networ networkFilter = NetworkFilterAdjust(ref message); MmNetworkResponder.MmInvoke(msgType, message); } //Todo: it's possible to get this to happen only once per graph. Switch Invoke code to support. var upwardMessage = message.Copy(); upwardMessage.MetadataBlock.LevelFilter = MmLevelFilterHelper.SelfAndParents; var downwardMessage = message.Copy(); downwardMessage.MetadataBlock.LevelFilter = MmLevelFilterHelper.SelfAndChildren; MmLevelFilter levelFilter = message.MetadataBlock.LevelFilter; MmActiveFilter activeFilter = ActiveFilterAdjust(ref message); MmSelectedFilter selectedFilter = SelectedFilterAdjust(ref message); //If this message was a network-only message and // this node does not allow for propagation of network messages, // then return. if (!AllowNetworkPropagationLocally && !message.IsDeserialized && message.MetadataBlock.NetworkFilter == MmNetworkFilter.Network) { return; } foreach (var routingTableItem in RoutingTable) { var responder = routingTableItem.Responder; //bool isLocalResponder = responder.MmGameObject == this.gameObject; MmLevelFilter responderLevel = routingTableItem.Level; //Check individual responder level and then call the right param. MmMessage responderSpecificMessage; if ((responderLevel & MmLevelFilter.Parent) > 0) { responderSpecificMessage = upwardMessage; } else if ((responderLevel & MmLevelFilter.Child) > 0) { responderSpecificMessage = downwardMessage; } else { responderSpecificMessage = message; } //MmLogger.LogFramework (gameObject.name + "observing " + responder.MmGameObject.name); if (ResponderCheck(levelFilter, activeFilter, selectedFilter, networkFilter, routingTableItem, responderSpecificMessage)) { responder.MmInvoke(msgType, responderSpecificMessage); } } //if (dirty && _prevMessageTime == message.TimeStamp) //{ // dirty = false; //} doNotModifyRoutingTable = false; while (MmRespondersToAdd.Any()) { var routingTableItem = MmRespondersToAdd.Dequeue(); MmAddToRoutingTable(routingTableItem.Responder, routingTableItem.Level); if (ResponderCheck(levelFilter, activeFilter, selectedFilter, networkFilter, routingTableItem, message)) { routingTableItem.Responder.MmInvoke(msgType, message); } } //if (serialExecution) //{ // if (SerialExecutionQueue.Count != 0) // { // MmLogger.LogFramework("%%%%%%%%%%%Dequeueing%%%%%%%%%"); // KeyValuePair<MmMessageType, MmMessage> DequeuedMessage = SerialExecutionQueue.Dequeue(); // MmInvoke(DequeuedMessage.Key, DequeuedMessage.Value); // } // _executing = false; //} }