private void SendIMCMessage(string _target, IMCMessage message, float timeout, UnityAction<IMCMessage> onReceive, UnityAction onTimeout) { var target = GetIMCPort(_target); if (target == null) throw new SendMessageException("Target not set"); if (!target.gameObject.activeInHierarchy) throw new SendMessageException($"Receiving GameObject \"{target.name}\" is inactive"); if (onReceive != null && onTimeout != null) { pendingResponses.Add(new IMCWait( message.ID, Time.time + timeout, onReceive, onTimeout) ); } target.SendMessage(nameof(ReceiveMessage), message.ToObjects()); }
/// <summary> /// Calls a remote function without payload, expecting a return value of a specific type /// </summary> /// <typeparam name="R">The type of the return value of the called function</typeparam> /// <param name="target">The target port to send the message to</param> /// <param name="name">The name of the remote function</param> /// <param name="payload">The payload to pass to the function</param> /// <param name="timeout">The amount of time, in seconds, to wait for a response</param> /// <param name="callback">The callback to call upon receiving a response</param> /// <param name="error">The callback to call upon encountering errors</param> public void RPC <R>(string target, string name, float timeout, UnityAction <R> callback, UnityAction <Exception> error) { try { var message = IMCMessage.CreateRequest(this.name, name); SendIMCMessage( target, message, timeout, (msg) => { callback?.Invoke(msg.ParsePayload <R>()); }, () => { error.Invoke(TimeoutException.Instance); }); } catch (Exception ex) { error?.Invoke(ex); } }
/// <summary> /// Calls a remote function using the given payload, expecting no return value /// </summary> /// <typeparam name="P">The type of the payload to pass to the function</typeparam> /// <param name="target">The target port to send the message to</param> /// <param name="name">The name of the remote function</param> /// <param name="payload">The payload to pass to the function</param> /// <param name="timeout">The amount of time, in seconds, to wait for a response</param> /// <param name="callback">The callback to call upon receiving a response</param> /// <param name="error">The callback to call upon encountering errors public void RPC <P>(string target, string name, P payload, float timeout, UnityAction callback, UnityAction <Exception> error) { try { var message = IMCMessage.CreateRequest(this.name, name, JsonConvert.SerializeObject(payload)); SendIMCMessage( target, message, timeout, (msg) => { callback?.Invoke(); }, () => { error.Invoke(TimeoutException.Instance); }); } catch (Exception ex) { error?.Invoke(ex); } }
/// <summary> /// Called by Component.SendMessage /// </summary> /// <param name="data">Object array that can be unpacked to an IMCMessage</param> private void ReceiveMessage(object[] data) { try { var message = IMCMessage.FromUnityMessage(data); if (message.Type == IMCMessage.MessageType.Response) { var pending = pendingResponses.FirstOrDefault(p => p.ID == message.ID); if (pending == null) { //TODO: Error handling: Received a response to a request that we didn't send! return; } pending.OnReceive(message); pendingResponses.Remove(pending); } else { var handler = new IMCRequestHandler(message); if (!receiveListeners.ContainsKey(message.Name)) { throw new Exception($"Unhandled request: {message.ToString()}"); } else { receiveListeners[message.Name]?.Invoke(handler, message); if (handler.Response != null) { SendIMCMessage(message.Source, handler.Response, 0f, null, null); } } } } catch (Exception ex) { if (helper != null) { helper.Log($"Failed to process message: {ex.Message}"); helper.Log($"Failed to process message: {ex.StackTrace}"); } } }
public void SendError(string source, string error) { Response = message.RespondError(source, error); }
public void SendResponse <T>(string source, T payload) { Response = message.RespondPayload(source, payload); }
public void SendResponse(string source) { Response = message.RespondPayload(source); }
public IMCRequestHandler(IMCMessage message) { this.message = message; }