public bool Interact(PositionalHandApply interaction)
    {
        //translate to the tile interaction system

        //pass the interaction down to the basic tile
        LayerTile tile = LayerTileAt(interaction.WorldPositionTarget);

        if (tile is BasicTile basicTile)
        {
            var tileApply = new TileApply(interaction.Performer, interaction.UsedObject, interaction.Intent,
                                          (Vector2Int)WorldToCell(interaction.WorldPositionTarget), this, basicTile, interaction.HandSlot,
                                          interaction.TargetVector);

            var i = 0;
            foreach (var tileInteraction in basicTile.TileInteractions)
            {
                if (tileInteraction == null)
                {
                    continue;
                }
                if (tileInteraction.WillInteract(tileApply, NetworkSide.Client) &&
                    Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction))
                {
                    //request the tile interaction with this index
                    RequestInteractMessage.SendTileApply(tileApply, this, tileInteraction, i);
                    return(true);
                }

                i++;
            }
        }

        return(false);
    }
    //only intended to be used by core if2 classes
    public static void SendTileApply(TileApply tileApply, InteractableTiles interactableTiles, TileInteraction tileInteraction, int tileInteractionIndex)
    {
        //if we are client and the interaction has client prediction, trigger it.
        //Note that client prediction is not triggered for server player.
        if (!CustomNetworkManager.IsServer)
        {
            Logger.LogTraceFormat("Predicting TileApply interaction {0}", Category.Interaction, tileApply);
            tileInteraction.ClientPredictInteraction(tileApply);
        }
        if (!tileApply.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;
        }

        var msg = new RequestInteractMessage()
        {
            ComponentType        = typeof(InteractableTiles),
            InteractionType      = typeof(TileApply),
            ProcessorObject      = interactableTiles.GetComponent <NetworkIdentity>().netId,
            Intent               = tileApply.Intent,
            TargetVector         = tileApply.TargetVector,
            TileInteractionIndex = tileInteractionIndex
        };

        msg.Send();
    }
Example #3
0
    public bool Interact(MouseDrop interaction)
    {
        Logger.Log("Interaction detected on InteractableTiles.");

        LayerTile tile = LayerTileAt(interaction.ShadowWorldLocation, true);

        if (tile is BasicTile basicTile)
        {
            var tileApply     = new TileApply(interaction.Performer, interaction.UsedObject, interaction.Intent, (Vector2Int)WorldToCell(interaction.ShadowWorldLocation), this, basicTile, null, -((Vector2)interaction.Performer.transform.position - interaction.ShadowWorldLocation), TileApply.ApplyType.MouseDrop);
            var tileMouseDrop = new TileMouseDrop(interaction.Performer, interaction.UsedObject, interaction.Intent, (Vector2Int)WorldToCell(interaction.ShadowWorldLocation), this, basicTile, -((Vector2)interaction.Performer.transform.position - interaction.ShadowWorldLocation));
            foreach (var tileInteraction in basicTile.TileInteractions)
            {
                if (tileInteraction == null)
                {
                    continue;
                }
                if (tileInteraction.WillInteract(tileApply, NetworkSide.Client) &&
                    Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction))
                {
                    //request the tile interaction because we think one will happen
                    RequestInteractMessage.SendTileMouseDrop(tileMouseDrop, this);
                    return(true);
                }
            }
        }

        return(false);
    }
Example #4
0
 /// <summary>
 /// Use this on client side to request an interaction. This can be used to trigger
 /// interactions manually outside of the normal interaction logic.
 /// Request the server to perform the indicated interaction using the specified
 /// component (or let the server determine the component if interactableComponent is null). The server will still validate the interaction and only perform
 /// it if it validates.
 ///
 /// Note that if interactableComponent implements IClientSideInteractable for this interaction type,
 /// nothing will be done.
 /// </summary>
 /// <param name="interaction">interaction to perform</param>
 /// <param name="interactableComponent">component to handle the interaction, null
 /// if the server should determine which component will trigger from the interaction</param>
 /// <typeparam name="T">type of interaction</typeparam>
 public static void RequestInteract <T>(T interaction, IBaseInteractable <T> interactableComponent = null)
     where T : Interaction
 {
     if (!Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction))
     {
         return;
     }
     RequestInteractMessage.Send(interaction, interactableComponent);
 }
    private void OnFlipClicked()
    {
        if (!Validations.IsInReach(gameObject.RegisterTile(), PlayerManager.LocalPlayerScript.registerTile, false))
        {
            return;
        }

        var menuApply = ContextMenuApply.ByLocalPlayer(gameObject, "Flip");

        RequestInteractMessage.Send(menuApply, this);
    }
Example #6
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);
        }
    }
Example #7
0
    public InteractionResult Interact(HandApply interaction)
    {
        ValidationResult validationResult = CanApply.ONLY_IF_CONSCIOUS.Validate(interaction, NetworkSide.CLIENT);

        if (validationResult == ValidationResult.SUCCESS)
        {
            RequestInteractMessage.Send(interaction, this);
            return(InteractionResult.SOMETHING_HAPPENED);
        }
        return(InteractionResult.NOTHING_HAPPENED);
    }
    /// <summary>
    /// Coordinator will perform client side validation of the interaction using its validators. If any
    /// validator fails, validation will fail and NOTHING_HAPPENED will be returned.
    /// If validation succeeds, it will send RequestInteractMessage to the server to request the server
    /// to perform the interaction.
    /// </summary>
    /// <param name="interaction">interaction being performed.</param>
    /// <returns>SOMETHING_HAPPENED if interaction validated and message was sent, NOTHING_HAPPENED otherwise</returns>
    public InteractionResult ClientValidateAndRequest(T interaction)
    {
        foreach (var validator in validations)
        {
            if (validator.Validate(interaction, NetworkSide.CLIENT) == ValidationResult.FAIL)
            {
                return(InteractionResult.NOTHING_HAPPENED);
            }
        }

        RequestInteractMessage.Send(interaction, processor);
        return(InteractionResult.SOMETHING_HAPPENED);
    }
Example #9
0
    private bool TryInteractWithTile(TileApply interaction)
    {
        // Iterate over the interactions for the given tile until a valid one is found.
        foreach (var tileInteraction in interaction.BasicTile.TileInteractions)
        {
            if (tileInteraction == null)
            {
                continue;
            }
            if (tileInteraction.WillInteract(interaction, NetworkSide.Client) &&
                Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction))
            {
                //request the tile interaction with this index
                RequestInteractMessage.SendTileApply(interaction, this, tileInteraction);
                return(true);
            }
        }

        return(false);
    }
Example #10
0
    public static void SendTileMouseDrop(TileMouseDrop mouseDrop, InteractableTiles interactableTiles)
    {
        if (!mouseDrop.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;
        }

        var msg = new RequestInteractMessage()
        {
            ComponentType   = typeof(InteractableTiles),
            InteractionType = typeof(TileMouseDrop),
            ProcessorObject = interactableTiles.GetComponent <NetworkIdentity>().netId,
            Intent          = mouseDrop.Intent,
            UsedObject      = mouseDrop.UsedObject.NetId(),
            TargetVector    = mouseDrop.TargetVector
        };

        msg.Send();
    }
Example #11
0
        private void OnRotateClicked()
        {
            var menuApply = ContextMenuApply.ByLocalPlayer(gameObject, "Rotate");

            RequestInteractMessage.Send(menuApply, this);
        }
    //only intended to be used by core if2 classes, please use InteractionUtils.RequestInteract instead.
    public static void Send <T>(T interaction, IBaseInteractable <T> interactableComponent)
        where T : Interaction
    {
        if (typeof(T) == typeof(TileApply))
        {
            Logger.LogError("Cannot use Send with TileApply, please use SendTileApply instead.", Category.Interaction);
            return;
        }
        //never send anything for client-side-only interactions
        if (interactableComponent is IClientInteractable <T> && !(interactableComponent is IInteractable <T>))
        {
            Logger.LogWarningFormat("Interaction request {0} will not be sent because interactable component {1} is" +
                                    " IClientInteractable only (client-side only).", Category.Interaction, interaction, interactableComponent);
            return;
        }
        //if we are client and the interaction has client prediction, trigger it.
        //Note that client prediction is not triggered for server player.
        if (!CustomNetworkManager.IsServer && interactableComponent is IPredictedInteractable <T> predictedInteractable)
        {
            Logger.LogTraceFormat("Predicting {0} interaction for {1} on {2}", Category.Interaction, typeof(T).Name, interactableComponent.GetType().Name, ((Component)interactableComponent).gameObject.name);
            predictedInteractable.ClientPredictInteraction(interaction);
        }
        if (!interaction.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 (!(interactableComponent is Component))
        {
            Logger.LogError("interactableComponent must be a component, but isn't. The message will not be sent.",
                            Category.NetMessage);
            return;
        }

        var comp = interactableComponent as Component;
        var msg  = new RequestInteractMessage()
        {
            ComponentType   = interactableComponent.GetType(),
            InteractionType = typeof(T),
            ProcessorObject = comp.GetComponent <NetworkIdentity>().netId,
            Intent          = interaction.Intent
        };

        if (typeof(T) == typeof(PositionalHandApply))
        {
            var casted = interaction as PositionalHandApply;
            msg.TargetObject   = casted.TargetObject.NetId();
            msg.TargetVector   = casted.TargetVector;
            msg.TargetBodyPart = casted.TargetBodyPart;
        }
        else if (typeof(T) == typeof(HandApply))
        {
            var casted = interaction as HandApply;
            msg.TargetObject   = casted.TargetObject.NetId();
            msg.TargetBodyPart = casted.TargetBodyPart;
            msg.IsAltUsed      = casted.IsAltClick;
        }
        else if (typeof(T) == typeof(AimApply))
        {
            var casted = interaction as AimApply;
            msg.TargetVector     = casted.TargetVector;
            msg.MouseButtonState = casted.MouseButtonState;
        }
        else if (typeof(T) == typeof(MouseDrop))
        {
            var casted = interaction as MouseDrop;
            msg.TargetObject = casted.TargetObject.NetId();
            msg.UsedObject   = casted.UsedObject.NetId();
        }
        else if (typeof(T) == typeof(InventoryApply))
        {
            var casted = interaction as InventoryApply;
            msg.Storage    = casted.TargetSlot.ItemStorageNetID;
            msg.SlotIndex  = casted.TargetSlot.SlotIdentifier.SlotIndex;
            msg.NamedSlot  = casted.TargetSlot.SlotIdentifier.NamedSlot.GetValueOrDefault(NamedSlot.none);
            msg.UsedObject = casted.UsedObject.NetId();
            msg.IsAltUsed  = casted.IsAltClick;
        }
        msg.Send();
    }
Example #13
0
 /// <summary>
 /// Used for the right click action, sends a message requesting uncuffing
 /// </summary>
 public void OnUncuffClicked()
 {
     RequestInteractMessage.Send(ContextMenuApply.ByLocalPlayer(gameObject, "Uncuff"), this);
 }
 /// <summary>
 /// Use this on client side to request an interaction. This can be used to trigger
 /// interactions manually outside of the normal interaction logic.
 /// Request the server to perform the indicated interaction using the specified
 /// component. The server will still validate the interaction and only perform
 /// it if it validates.
 ///
 /// Note that if interactableComponent implements IClientSideInteractable for this interaction type,
 /// nothing will be done.
 /// </summary>
 /// <param name="interaction">interaction to perform</param>
 /// <param name="interactableComponent">component to handle the interaction</param>
 /// <typeparam name="T"></typeparam>
 public static void RequestInteract <T>(T interaction, IBaseInteractable <T> interactableComponent)
     where T : Interaction
 {
     RequestInteractMessage.Send(interaction, interactableComponent);
 }
    //only intended to be used by core if2 classes, please use InteractionUtils.RequestInteract instead.
    public static void Send <T>(T interaction, IBaseInteractable <T> interactableComponent)
        where T : Interaction
    {
        //never send anything for client-side-only interactions
        if (interactableComponent is IClientInteractable <T> )
        {
            return;
        }
        //if we are client and the interaction has client prediction, trigger it.
        //Note that client prediction is not triggered for server player.
        if (!CustomNetworkManager.IsServer && interactableComponent is IPredictedInteractable <T> predictedInteractable)
        {
            Logger.LogTraceFormat("Predicting {0} interaction for {1} on {2}", Category.Interaction, typeof(T).Name, interactableComponent.GetType().Name, ((Component)interactableComponent).gameObject.name);
            predictedInteractable.ClientPredictInteraction(interaction);
        }
        if (!interaction.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 (!(interactableComponent is Component))
        {
            Logger.LogError("interactableComponent must be a component, but isn't. The message will not be sent.",
                            Category.NetMessage);
            return;
        }

        var comp = interactableComponent as Component;
        var msg  = new RequestInteractMessage()
        {
            ComponentType   = interactableComponent.GetType(),
            InteractionType = typeof(T),
            ProcessorObject = comp.GetComponent <NetworkIdentity>().netId
        };

        if (typeof(T) == typeof(PositionalHandApply))
        {
            var casted = interaction as PositionalHandApply;
            msg.TargetObject = casted.TargetObject.GetComponent <NetworkIdentity>().netId;
            msg.TargetVector = casted.TargetVector;
        }
        else if (typeof(T) == typeof(HandApply))
        {
            var casted = interaction as HandApply;
            msg.TargetObject   = casted.TargetObject.GetComponent <NetworkIdentity>().netId;
            msg.TargetBodyPart = casted.TargetBodyPart;
        }
        else if (typeof(T) == typeof(AimApply))
        {
            var casted = interaction as AimApply;
            msg.TargetVector     = casted.TargetVector;
            msg.MouseButtonState = casted.MouseButtonState;
        }
        else if (typeof(T) == typeof(MouseDrop))
        {
            var casted = interaction as MouseDrop;
            msg.TargetObject = casted.TargetObject.GetComponent <NetworkIdentity>().netId;
            msg.UsedObject   = casted.UsedObject.GetComponent <NetworkIdentity>().netId;
        }
        msg.Send();
    }