/// <summary>
 /// Create a coordinator which will handle the interaction logic
 /// </summary>
 /// <param name="processor">Should almost always be "this" - the component using this coordinator should
 /// implement IInteractionProcessor and delegate processing to this coordinator.
 /// Component which will process the interaction on the server side.</param>
 /// <param name="willInteract">Can be null. If specified, invoked client side to determine if request
 /// should be sent to server. Invoked server side to see if interaction logic should be invoked.</param>
 /// <param name="interactionLogic">Function to invoke on the server side to perform the interaction logic
 /// if validation succeeds.</param>
 public InteractionCoordinator(IInteractionProcessor <T> processor, Func <T, NetworkSide, bool> willInteract,
                               Action <T> interactionLogic)
 {
     this.processor        = processor;
     this.interactionLogic = interactionLogic;
     this.willInteract     = willInteract;
 }
 /// <summary>
 /// Create a coordinator which will handle the interaction logic
 /// </summary>
 /// <param name="processor">Should almost always be "this" - the component using this coordinator should
 /// implement IInteractionProcessor and delegate processing to this coordinator.
 /// Component which will process the interaction on the server side.</param>
 /// <param name="validations">Validations to perform on client and server side. If any validation fails,
 /// the entire validation will fail.</param>
 /// <param name="interactionLogic">Function to invoke on the server side to perform the interaction logic
 /// if validation succeeds.</param>
 public InteractionCoordinator(IInteractionProcessor <T> processor, IList <IInteractionValidator <T> > validations,
                               Func <T, InteractionResult> interactionLogic)
 {
     this.validations      = validations;
     this.processor        = processor;
     this.interactionLogic = interactionLogic;
 }
Ejemplo n.º 3
0
    /// <summary>
    /// Send a request to the server to validate + perform the interaction.
    /// </summary>
    /// <param name="info">info on the interaction being performed. Each object involved in the interaction
    /// must have a networkidentity.</param>
    /// <param name="processor">component which will process the interaction on the server-side. The processor's
    /// info and result types must match the info and result type of one of the interaction type constants
    /// defined in InteractionType.
    ///
    /// This component
    /// must live on a GameObject with a network identity, and there must only be one instance of this component
    /// on the object. For organization, we suggest that the component which is sending this message
    /// should be the processor, as such this parameter should almost always be passed using the "this" keyword, and
    /// should almost always be either a component on the target object or a component on the used object</param>
    /// <typeparamref name="T">Interaction subtype
    /// for the interaction that the processor can handle (such as MouseDrop for a mouse drop interaction).
    /// Must be a subtype of Interaction.</typeparamref>
    public static void SendRequest <T>(T info, IInteractionProcessor <T> processor)
        where T : Interaction
    {
        if (!info.Performer.Equals(PlayerManager.LocalPlayer))
        {
            Logger.LogError("Client attempting to perform an interaction on behalf of another player." +
                            " This is not allowed. Client can only perform an interaction as themselves. Message" +
                            " will not be sent.", Category.NetMessage);
            return;
        }

        if (!(processor is Component))
        {
            Logger.LogError("processor must be a component, but isn't. The message will not be sent.", Category.NetMessage);
            return;
        }

        //send the message appropriate to the specific interaction type
        var processorObject = (processor as Component).gameObject;

        if (typeof(T) == typeof(PositionalHandApply))
        {
            RequestPositionalHandApplyMessage.Send(info as PositionalHandApply, processorObject);
            return;
        }
        else if (typeof(T) == typeof(HandApply))
        {
            RequestHandApplyMessage.Send(info as HandApply, processorObject);
            return;
        }
        else if (typeof(T) == typeof(AimApply))
        {
            RequestAimApplyMessage.Send(info as AimApply, processorObject);
            return;
        }
        else if (typeof(T) == typeof(MouseDrop))
        {
            RequestMouseDropMessage.Send(info as MouseDrop, processorObject);
            return;
        }
        else if (typeof(T) == typeof(HandActivate))
        {
            RequestHandActivateMessage.Send(info as HandActivate, processorObject);
            return;
        }
        else if (typeof(T) == typeof(InventoryApply))
        {
            RequestInventoryApplyMessage.Send(info as InventoryApply, processorObject);
            return;
        }

        //TODO: Other types

        //we didn't send anything
        Logger.LogErrorFormat("Interaction type was {0} - we couldn't determine what to do for this interaction" +
                              " type, most likely because it hasn't been implemented yet." +
                              " Please implement handling for this interaction type in InteractionMessageUtils.SendRequest()", Category.NetMessage, nameof(T));
    }
 /// <summary>
 /// Create a coordinator which will handle the interaction logic. It is recommended to use the
 /// other constructor so you can use the re-usable IInteractionValidators and avoid code duplication.
 /// </summary>
 /// <param name="processor">Should almost always be "this" - the component using this coordinator should
 /// implement IInteractionProcessor and delegate processing to this coordinator.
 /// Component which will process the interaction on the server side.</param>
 /// <param name="validationLogic">function which will validate the interaction on client and server side.</param>
 /// <param name="interactionLogic">Function to invoke on the server side to perform the interaction logic
 /// if validation succeeds.</param>
 public InteractionCoordinator(IInteractionProcessor <T> processor, Func <T, NetworkSide, ValidationResult> validationLogic,
                               Func <T, InteractionResult> interactionLogic)
 {
     this.validations = new List <IInteractionValidator <T> > {
         new FunctionValidator <T>(validationLogic)
     };
     this.processor        = processor;
     this.interactionLogic = interactionLogic;
 }
Ejemplo n.º 5
0
    /// <summary>
    /// Send a request to the server to validate + perform the interaction.
    /// </summary>
    /// <param name="info">info on the interaction being performed. Each object involved in the interaction
    /// must have a networkidentity.</param>
    /// <param name="processor">component which will process the interaction on the server-side. The processor's
    /// info and result types must match the info and result type of one of the interaction type constants
    /// defined in InteractionType.
    ///
    /// This component
    /// must live on a GameObject with a network identity, and there must only be one instance of this component
    /// on the object. For organization, we suggest that the component which is sending this message
    /// should be the processor, as such this parameter should almost always be passed using the "this" keyword, and
    /// should almost always be either a component on the target object or a component on the used object</param>
    /// <typeparamref name="T">Interaction subtype
    /// for the interaction that the processor can handle (such as MouseDrop for a mouse drop interaction).
    /// Must be a subtype of Interaction.</typeparamref>
    /// <returns></returns>
    public static RequestInteractMessage Send <T>(T info, IInteractionProcessor <T> processor)
        where T : Interaction
    {
        if (!info.Performer.Equals(PlayerManager.LocalPlayer))
        {
            Logger.LogError("Client attempting to perform an interaction on behalf of another player." +
                            " This is not allowed. Client can only perform an interaction as themselves. Message" +
                            " will not be sent.", Category.NetMessage);
            return(null);
        }

        if (!(processor is Component))
        {
            Logger.LogError("processor must be a component, but isn't. The message will not be sent.", Category.NetMessage);
            return(null);
        }

        short typeID;
        var   processorObject = (processor as Component).gameObject;

        if (InteractionTypeToID.TryGetValue(typeof(T), out typeID))
        {
            RequestInteractMessage msg = null;
            //send the message appropriate to the specific interaction type
            if (typeof(T) == typeof(MouseDrop))
            {
                msg = CreateMouseDropMessage(info as MouseDrop, processorObject, typeID);
            }
            else if (typeof(T) == typeof(HandApply))
            {
                msg = CreateHandApplyMessage(info as HandApply, processorObject, typeID);
            }
            //TODO: Other types

            if (msg != null)
            {
                msg.Send();
                return(msg);
            }
            else
            {
                Logger.LogErrorFormat("Interaction type was {0} - we couldn't determine what to do for this interaction" +
                                      " type, most likely because it hasn't been implemented yet." +
                                      " Please implement handling for this interaction type in RequestInteractMessage.Send()", Category.NetMessage, nameof(T));
                return(null);
            }
        }
        else
        {
            Logger.LogError("Interaction's concrete type could not be mapped to an ID, this is most likely" +
                            " a programming error. Message will not be sent", Category.NetMessage);
            return(null);
        }
    }