/// <summary> /// Duplicate an MmMessage /// </summary> /// <param name="message">Item to duplicate</param> public MmMessage(MmMessage message) : this(message.MmMethod, message.MetadataBlock) { NetId = message.NetId; IsDeserialized = message.IsDeserialized; root = message.root; TimeStamp = message.TimeStamp; }
/// <summary> /// Invoke an MmMethod with no parameter. /// </summary> /// <param name="mmMethod">MmMethod Identifier - <see cref="MmMethod"/></param> /// <param name="metadataBlock">Object defining the routing of /// Mmessages through MercuryMessaging Hierarchies. <see cref="MmMetadataBlock"/></param> public virtual void MmInvoke(MmMethod mmMethod, MmMetadataBlock metadataBlock = null) { MmMessage msg = new MmMessage(mmMethod, metadataBlock); MmInvoke(MmMessageType.MmVoid, msg); }
/// <summary> /// Send a message to all clients using UNET /// </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="msg">The message to send. /// This utilises UNET's MessageBase so it is /// Auto [de]serialized by UNET. /// This also allows us to send messages that are not /// part of Mercury XM</param> public virtual void MmSendMessageToClient(short msgType, MmMessage msg) { foreach (var connection in NetworkServer.connections) { if (connection != null) { NetworkServer.SendToClient(connection.connectionId, msgType, msg); } } }
/// Invoke a general MmMethod with parameter: MmMessage. /// </summary> /// <param name="mmMethod">MmMethod Identifier - <see cref="MmMethod"/></param> /// <param name="param">MmMethod parameter: MmMessage. <see cref="MmMessage"/> </param> /// <param name="metadataBlock">Object defining the routing of /// Mmessages through MercuryMessaging Hierarchies. <see cref="MmMetadataBlock"/></param> public virtual void MmInvoke(MmMethod mmMethod, MmMessage param, MmMessageType msgType, MmMetadataBlock metadataBlock = null) { MmMessage msg = param.Copy(); msg.MmMethod = mmMethod; msg.MetadataBlock = metadataBlock; MmInvoke(msg); }
/// <summary> /// Send a message to all clients using Photon /// </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="msg">The message to send.</param> public override void MmSendMessageToClient(MmMessage msg) { byte eventCode = (byte)(1); object[] data = msg.Serialize(); RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.All }; PhotonNetwork.RaiseEvent(eventCode, data, raiseEventOptions, SendOptions.SendReliable); }
/// <summary> /// Allows modification of network filter in message /// as it gets passed between MmRelayNodes. /// </summary> /// <param name="message">MmMessage to be adjusted.</param> /// <returns>Base implementation returns messages's network filter.</returns> protected virtual MmNetworkFilter NetworkFilterAdjust(ref MmMessage message) { MmNetworkFilter original = message.MetadataBlock.NetworkFilter; if (FlipNetworkFlagOnSend && message.MetadataBlock.NetworkFilter != MmNetworkFilter.Local) { message.MetadataBlock.NetworkFilter = MmNetworkFilter.Local; } return(original); }
public override void MmInvoke (MmMessageType msgType, MmMessage message) { switch (message.MmMethod) { case MmMethod.Transform: MmMessageTransform newMsg = message as MmMessageTransform; HandleTransform (newMsg); break; default: base.MmInvoke(msgType, message); break; } }
/// <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> /// Send a message to a specific client over chosen Photon. /// </summary> /// <param name="channelId">Client connection ID</param> /// <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="msg">The message to send.</param> public override void MmSendMessageToClient(int channelId, MmMessage msg) { byte eventCode = (byte)(1); object[] data = msg.Serialize(); RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.All }; SendOptions sendOptions = new SendOptions { Reliability = true, Channel = (byte)channelId }; PhotonNetwork.RaiseEvent(eventCode, data, raiseEventOptions, sendOptions); }
/// <summary> /// Determine if MmResponder passes MmRelayNode tag filter check using value embedded in MmMessage. /// </summary> /// <param name="mmRoutingTableItem">RoutingTableItem of currently observed MmResponder</param> /// <param name="message">MmMessage to be checked.</param> /// <returns>Returns whether observed MmResponder has passed tag check.</returns> protected virtual bool TagCheck(MmRoutingTableItem mmRoutingTableItem, MmMessage message) { //var text = string.Format("Tag Check (GO: {0}, ListItem: {1}, msgType:{2}, msgTag={3}, responderTag={4}", // gameObject.name, // mmRoutingTableItem.Name, // param.MmMethod, // MmTagHelper.ToString(param.MetadataBlock.Tag), // MmTagHelper.ToString(mmRoutingTableItem.Tags)); // Responder's TagCheck toggle is not enabled, this passes if (!mmRoutingTableItem.Responder.TagCheckEnabled) { //Debug.Log(text + ") Passed -- TagCheckEnabled: FALSE"); return(true); } var msgTag = message.MetadataBlock.Tag; // This is "Everything" by default, will by-pass Tag-Check var responderTag = mmRoutingTableItem.Tags; // This is "Nothing" by default, if a message *has* a specific tag, // i.e. something other than "Everything", it won't pass // unless it has that tag's flag set to 1 // This message applies to everyone, this passes if (msgTag == MmTagHelper.Everything) { //Debug.Log(text + ") Passed -- msgTag = Everything"); return(true); } // This message has a tag, other than "Everything", but it matches responder's tag, so it passes if ((msgTag & responderTag) > 0) { //Debug.Log(text + ") Passed -- tag match"); return(true); } // This message has a tag, other than "Everything", and it doesn't match responder's tag, so it fails //Debug.Log(text + ") FAILED"); return(false); }
/// <summary> /// This is the network equivalent of IMmResponder's MmInvoke. /// The difference is this class allows specification of connectionIDs /// which can be used to ensure messages are routed to the correct /// objects on network clients. /// </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="msg">The message to send.</param> /// <param name="connectionId">Connection ID - use to identify clients.</param> public override void MmInvoke(MmMessage msg, int connectionId = -1) { msg.NetId = (uint)photonView.ViewID; // If the connection ID is defined, only send it there, // otherwise, it follows the standard execution flow for the chosen // network solution. if (connectionId != -1) { MmSendMessageToClient(connectionId, msg); return; } // Need to call the right method based on whether this object // is a client or a server. if (IsActiveAndEnabled) { MmSendMessageToClient(msg); } else if (AllowClientToSend) { MmSendMessageToServer(msg); } }
/// <summary> /// This is the network equivalent of IMmResponder's MmInvoke. /// The difference is this class allows specification of connectionIDs /// which can be used to ensure messages are routed to the correct /// objects on network clients. /// </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="msg">The message to send. /// This class builds on UNET's MessageBase so it is /// Auto [de]serialized by UNET.</param> /// <param name="connectionId">Connection ID - use to identify clients.</param> public virtual void MmInvoke(MmMessageType msgType, MmMessage message, int connectionId = -1) { message.NetId = netId.Value; //If the connection ID is defined, only send it there, // otherwise, it follows the standard execution flow for the chosen // network solution. if (connectionId != -1) { MmSendMessageToClient(connectionId, (short)msgType, message); return; } //Need to call the right method based on whether this object // is a client or a server. if (NetworkServer.active) { MmSendMessageToClient((short)msgType, message); } else if (allowClientToSend) { MmSendMessageToServer((short)msgType, message); } }
/// <summary> /// Checks if a responder should recieve a message based on /// the network flag in a control block. /// Network messages can go to other nodes, but not to self responders. /// </summary> /// <param name="mmRoutingTableItem">Observed MmResponder</param> /// <param name="message">Input message.</param> /// <returns></returns> protected virtual bool NetworkCheck(MmRoutingTableItem mmRoutingTableItem, MmMessage message) { //Need to check if the message is executing locally on a host (server + client). //If this occurs, two instances of a message will be seen in this node: // 1. The message originally passed in, that has just been sent over the network // 2. The message handled by the network and received by the client instance. //The first instance of a message should not execute locally. Instead, only the second instance // should. The Node needs to know if this is executing locally as a host, and if the // message has been deserialized (indicating receipt by the client instance). if ((mmRoutingTableItem.Level == MmLevelFilter.Self && message.MetadataBlock.NetworkFilter == MmNetworkFilter.Network && !message.IsDeserialized) || (message.MetadataBlock.NetworkFilter != MmNetworkFilter.Local && MmNetworkResponder != null && MmNetworkResponder.OnClient && MmNetworkResponder.OnServer && !message.IsDeserialized)) { return(false); } return(true); }
/// <summary> /// Method serializes message and sends it to server. /// </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="msg">The message to send.</param> public abstract void MmSendMessageToServer(MmMessage msg);
/// <summary> /// Allows modification of selected filter in message /// as it gets passed between MmRelayNodes. /// </summary> /// <param name="message">MmMessage to be adjusted.</param> /// <returns>Base implementation returns messages's selected filter.</returns> protected virtual MmSelectedFilter SelectedFilterAdjust(ref MmMessage message) { return(message.MetadataBlock.SelectedFilter); }
/// <summary> /// Allows modification of active filter in message /// as it gets passed between MmRelayNodes. /// </summary> /// <param name="message">MmMessage to be adjusted.</param> /// <returns>Base implementation returns messages's active filter.</returns> protected virtual MmActiveFilter ActiveFilterAdjust(ref MmMessage message) { return(message.MetadataBlock.ActiveFilter); }
/// <summary> /// If the level filter is designated 'Child', then it is recorded locally, /// but converted to a 'Child+Self' for use by the RoutingTable /// (which need to pass the message on to all children, but still need to be able /// to execute the message on their own responders, otherwise, it just goes /// to the terminal points of the graph without ever executing). /// </summary> /// <param name="message">MmMessage to be adjusted.</param> /// <param name="direction">Intended direction of message</param> /// <returns>Base implementation returns messages's level filter.</returns> protected virtual MmLevelFilter LevelFilterAdjust(ref MmMessage message, MmLevelFilter direction) { return(message.MetadataBlock.LevelFilter); }
/// <summary> /// Invoke an MmMethod with any message type. /// </summary> /// <param name="mmMethod">MmMethod Identifier - <see cref="MmMethod"/></param> /// <param name="param">MmMethod parameter: Any Message type.</param> /// <param name="msgType">Type of MmMessage parameter.</param> /// <param name="metadataBlock">Object defining the routing of /// Mmessages through MercuryMessaging Hierarchies. <see cref="MmMetadataBlock"/></param> public virtual void MmInvoke(MmMethod mmMethod, MmMessage param, MmMessageType msgType, MmMetadataBlock metadataBlock = null) { param.MmMethod = mmMethod; param.MetadataBlock = metadataBlock; MmInvoke(msgType, param); }
/// <summary> /// Send a message to all clients. /// </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="msg">The message to send.</param> public abstract void MmSendMessageToClient(MmMessage msg);
/// <summary> /// Duplicate an MmMessage /// </summary> /// <param name="message">Item to duplicate</param> public MmMessageBool(MmMessage message) : base(message) { }
/// <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 virtual void MmInvoke(MmMessage message) { }
/// <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 virtual void MmInvoke(MmMessageType msgType, MmMessage message) { }
/// <summary> /// Handle MmMethod: Base MmMessage. /// Override this to handle base Mercury Messages. /// </summary> /// <param name="message"><see cref="MmMessage"/></param> protected virtual void ReceivedMessage(MmMessage message) { }
/// <summary> /// Send a message to a specific client over chosen UNET. /// </summary> /// <param name="channelId">Client connection ID</param> /// <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="msg">The message to send. /// This utilises UNET's MessageBase so it is /// Auto [de]serialized by UNET. /// This also allows us to send messages that are not /// part of Mercury XM</param> public virtual void MmSendMessageToClient(int channelId, short msgType, MmMessage msg) { NetworkServer.SendToClient(channelId, msgType, msg); }
/// <summary> /// This is the network equivalent of IMmResponder's MmInvoke. /// The difference is this class allows specification of connectionIDs /// which can be used to ensure messages are routed to the correct /// objects on network clients. /// </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="msg">The message to send.</param> /// <param name="connectionId">Connection ID - use to identify clients.</param> public abstract void MmInvoke(MmMessage msg, int connectionId = -1);
/// <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; //} }
public override void MmSendMessageToClient(MmMessage msg) { }
/// <summary> /// Send a message to a specific client. /// </summary> /// <param name="channelId">Client connection ID</param> /// <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="msg">The message to send.</param> public abstract void MmSendMessageToClient(int channelId, MmMessage msg);
/// <summary> /// Process a message and send it to the associated object. /// </summary> /// <param name="netMsg">UNET network message</param> public virtual void ReceivedMessage(NetworkMessage netMsg) { MmMessageType mmMessageType = (MmMessageType)netMsg.msgType; try { switch (mmMessageType) { case MmMessageType.MmVoid: MmMessage msg = netMsg.ReadMessage <MmMessage>(); MmRelayNodes[msg.NetId].MmInvoke(mmMessageType, msg); break; case MmMessageType.MmInt: MmMessageInt msgInt = netMsg.ReadMessage <MmMessageInt>(); MmRelayNodes[msgInt.NetId].MmInvoke(mmMessageType, msgInt); break; case MmMessageType.MmBool: MmMessageBool msgBool = netMsg.ReadMessage <MmMessageBool>(); MmRelayNodes[msgBool.NetId].MmInvoke(mmMessageType, msgBool); break; case MmMessageType.MmFloat: MmMessageFloat msgFloat = netMsg.ReadMessage <MmMessageFloat>(); MmRelayNodes[msgFloat.NetId].MmInvoke(mmMessageType, msgFloat); break; case MmMessageType.MmVector3: MmMessageVector3 msgVector3 = netMsg.ReadMessage <MmMessageVector3>(); MmRelayNodes[msgVector3.NetId].MmInvoke(mmMessageType, msgVector3); break; case MmMessageType.MmVector4: MmMessageVector4 msgVector4 = netMsg.ReadMessage <MmMessageVector4>(); MmRelayNodes[msgVector4.NetId].MmInvoke(mmMessageType, msgVector4); break; case MmMessageType.MmString: MmMessageString msgString = netMsg.ReadMessage <MmMessageString>(); MmRelayNodes[msgString.NetId].MmInvoke(mmMessageType, msgString); break; case MmMessageType.MmByteArray: MmMessageByteArray msgByteArray = netMsg.ReadMessage <MmMessageByteArray>(); MmRelayNodes[msgByteArray.NetId].MmInvoke(mmMessageType, msgByteArray); break; case MmMessageType.MmTransform: MmMessageTransform msgTransform = netMsg.ReadMessage <MmMessageTransform>(); MmRelayNodes[msgTransform.NetId].MmInvoke(mmMessageType, msgTransform); break; case MmMessageType.MmTransformList: MmMessageTransformList msgTransformList = netMsg.ReadMessage <MmMessageTransformList>(); MmRelayNodes[msgTransformList.NetId].MmInvoke(mmMessageType, msgTransformList); break; case MmMessageType.MmSerializable: MmMessageSerializable msgSerializable = netMsg.ReadMessage <MmMessageSerializable>(); MmRelayNodes[msgSerializable.NetId].MmInvoke(mmMessageType, msgSerializable); break; case MmMessageType.MmGameObject: MmMessageGameObject msgGameObject = netMsg.ReadMessage <MmMessageGameObject>(); MmRelayNodes[msgGameObject.NetId].MmInvoke(mmMessageType, msgGameObject); break; default: throw new ArgumentOutOfRangeException(); } } catch (Exception e) { MmLogger.LogError(e.Message); } }
/// <summary> /// Invoke an MmMethod. /// Implements a switch that handles the different MmMethods /// defined by default set in MmMethod <see cref="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. <see cref="MmMessageType"/> /// </param> /// <param name="message">The message to send. /// This class builds on UNET's MessageBase so it is /// Auto [de]serialized by UNET. <see cref="MmMessage"/></param> public override void MmInvoke(MmMessageType msgType, MmMessage message) { var type = message.MmMethod; switch (type) { case MmMethod.NoOp: break; case MmMethod.SetActive: var messageBool = (MmMessageBool)message; SetActive(messageBool.value); break; case MmMethod.Refresh: var messageTransform = (MmMessageTransformList)message; Refresh(messageTransform.transforms); break; case MmMethod.Initialize: Initialize(); break; case MmMethod.Switch: var messageString = (MmMessageString)message; Switch(messageString.value); break; case MmMethod.Complete: var messageCompleteBool = (MmMessageBool)message; Complete(messageCompleteBool.value); break; case MmMethod.TaskInfo: var messageSerializable = (MmMessageSerializable)message; ApplyTaskInfo(messageSerializable.value); break; case MmMethod.Message: ReceivedMessage(message); break; case MmMethod.MessageBool: ReceivedMessage((MmMessageString)message); break; case MmMethod.MessageByteArray: ReceivedMessage((MmMessageByteArray)message); break; case MmMethod.MessageFloat: ReceivedMessage((MmMessageFloat)message); break; case MmMethod.MessageInt: ReceivedMessage((MmMessageInt)message); break; case MmMethod.MessageSerializable: ReceivedMessage((MmMessageSerializable)message); break; case MmMethod.MessageString: ReceivedMessage((MmMessageString)message); break; case MmMethod.MessageTransform: ReceivedMessage((MmMessageTransform)message); break; case MmMethod.MessageTransformList: ReceivedMessage((MmMessageTransformList)message); break; case MmMethod.MessageVector3: ReceivedMessage((MmMessageVector3)message); break; case MmMethod.MessageVector4: ReceivedMessage((MmMessageVector4)message); break; default: Debug.Log(message.MmMethod.ToString()); throw new ArgumentOutOfRangeException(); } }