Beispiel #1
0
    private static bool CheckInteractInternal <T>(IBaseInteractable <T> interactable, T interaction,
                                                  NetworkSide side)
        where T : Interaction
    {
        if (Cooldowns.IsOn(interaction, CooldownID.Asset(CommonCooldowns.Instance.Interaction, side)))
        {
            return(false);
        }
        var result = false;

        //check if client side interaction should be triggered
        if (side == NetworkSide.Client && interactable is IClientInteractable <T> clientInteractable)
        {
            result = clientInteractable.Interact(interaction);
            if (result)
            {
                Logger.LogTraceFormat("ClientInteractable triggered from {0} on {1} for object {2}",
                                      Category.Interaction, typeof(T).Name, clientInteractable.GetType().Name,
                                      (clientInteractable as Component).gameObject.name);
                Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction);
                return(true);
            }
        }

        //check other kinds of interactions
        if (interactable is ICheckable <T> checkable)
        {
            result = checkable.WillInteract(interaction, side);
            if (result)
            {
                Logger.LogTraceFormat("WillInteract triggered from {0} on {1} for object {2}", Category.Interaction,
                                      typeof(T).Name, checkable.GetType().Name,
                                      (checkable as Component).gameObject.name);
                return(true);
            }
        }
        else if (interactable is IInteractable <T> )
        {
            //use default logic
            result = DefaultWillInteract.Default(interaction, side);
            if (result)
            {
                Logger.LogTraceFormat("WillInteract triggered from {0} on {1} for object {2}", Category.Interaction,
                                      typeof(T).Name, interactable.GetType().Name,
                                      (interactable as Component).gameObject.name);

                return(true);
            }
        }

        Logger.LogTraceFormat("No interaction triggered from {0} on {1} for object {2}", Category.Interaction,
                              typeof(T).Name, interactable.GetType().Name,
                              (interactable as Component).gameObject.name);

        return(false);
    }
    //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();
    }
Beispiel #3
0
    private static bool CheckInteractInternal <T>(this IBaseInteractable <T> interactable, T interaction,
                                                  NetworkSide side, out bool wasClientInteractable)
        where T : Interaction
    {
        wasClientInteractable = false;
        //interactions targeting an object at hiddenpos are NEVER allowed (except for inventory actions,
        //since they can target an object in inventory which means its at hiddenpos)
        if (!(interaction is InventoryApply) && interaction is TargetedInteraction targetedInteraction)
        {
            if (targetedInteraction.TargetObject != null &&
                targetedInteraction.TargetObject.IsAtHiddenPos())
            {
                Logger.LogTraceFormat("Aborting {0} interaction on object {1} because the object is hidden.",
                                      Category.Interaction, typeof(T).Name, targetedInteraction.TargetObject.name);
                return(false);
            }
        }
        if (Cooldowns.IsOn(interaction, CooldownID.Asset(CommonCooldowns.Instance.Interaction, side)))
        {
            return(false);
        }
        var result = false;

        //check if client side interaction should be triggered
        if (side == NetworkSide.Client && interactable is IClientInteractable <T> clientInteractable)
        {
            result = clientInteractable.Interact(interaction);
            if (result)
            {
                Logger.LogTraceFormat("ClientInteractable triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, clientInteractable.GetType().Name,
                                      (clientInteractable as Component).gameObject.name);
                Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction);
                wasClientInteractable = true;
                return(true);
            }
        }
        //check other kinds of interactions
        if (interactable is ICheckable <T> checkable)
        {
            result = checkable.WillInteract(interaction, side);
            if (result)
            {
                Logger.LogTraceFormat("WillInteract triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, checkable.GetType().Name,
                                      (checkable as Component).gameObject.name);
                wasClientInteractable = false;
                return(true);
            }
        }
        else if (interactable is IInteractable <T> )
        {
            //use default logic
            result = DefaultWillInteract.Default(interaction, side);
            if (result)
            {
                Logger.LogTraceFormat("WillInteract triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, interactable.GetType().Name,
                                      (interactable as Component).gameObject.name);
                wasClientInteractable = false;
                return(true);
            }
        }

        Logger.LogTraceFormat("No interaction triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, interactable.GetType().Name,
                              (interactable as Component).gameObject.name);

        wasClientInteractable = false;
        return(false);
    }
    /// <summary>
    /// Checks if this component would trigger any interaction, also invokes client side logic if it implements IClientInteractable.
    /// </summary>
    /// <param name="interactable"></param>
    /// <param name="interaction"></param>
    /// <param name="side"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static bool CheckInteract <T>(this IBaseInteractable <T> interactable, T interaction, NetworkSide side)
        where T : Interaction
    {
        var result = false;

        //check if client side interaction should be triggered
        if (side == NetworkSide.Client && interactable is IClientInteractable <T> clientInteractable)
        {
            result = clientInteractable.Interact(interaction);
            if (result)
            {
                Logger.LogTraceFormat("ClientInteractable triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, clientInteractable.GetType().Name,
                                      (clientInteractable as Component).gameObject.name);
                return(true);
            }
        }
        else if (interactable is ICheckable <T> checkable)
        {
            result = checkable.WillInteract(interaction, side);
            if (result)
            {
                Logger.LogTraceFormat("WillInteract triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, checkable.GetType().Name,
                                      (checkable as Component).gameObject.name);
                return(true);
            }
        }
        else if (interactable is IInteractable <T> )
        {
            //use default logic
            result = DefaultWillInteract.Default(interaction, side);
            if (result)
            {
                Logger.LogTraceFormat("WillInteract triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, interactable.GetType().Name,
                                      (interactable as Component).gameObject.name);
                return(true);
            }
        }

        Logger.LogTraceFormat("No interaction triggered from {0} on {1} for object {2}", Category.Interaction, typeof(T).Name, interactable.GetType().Name,
                              (interactable as Component).gameObject.name);

        return(false);
    }
Beispiel #5
0
        //only intended to be used by core if2 classes, please use InteractionUtils.RequestInteract instead.
        //pass null for interactableComponent if you want the server to determine which component of the involved objects should be triggered.
        //(which can be useful when client doesn't have enough info to know which one to trigger)
        public static void Send <T>(T interaction, IBaseInteractable <T> interactableComponent)
            where T : global::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.Exploits);
                return;
            }

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

            var comp = interactableComponent as Component;
            var msg  = new NetMessage()
            {
                ComponentType   = interactableComponent == null ? null : interactableComponent.GetType(),
                InteractionType = typeof(T),
                ProcessorObject = comp == null ? NetId.Invalid : GetNetId(comp.gameObject),
                Intent          = interaction.Intent
            };

            if (typeof(T) == typeof(PositionalHandApply))
            {
                var casted = interaction as PositionalHandApply;
                msg.TargetObject   = GetNetId(casted.TargetObject);
                msg.TargetPosition = casted.TargetPosition;
                msg.TargetBodyPart = casted.TargetBodyPart;
                msg.IsAltUsed      = casted.IsAltClick;
            }
            else if (typeof(T) == typeof(HandApply))
            {
                var casted = interaction as HandApply;
                msg.TargetObject   = GetNetId(casted.TargetObject);
                msg.TargetBodyPart = casted.TargetBodyPart;
                msg.IsAltUsed      = casted.IsAltClick;
            }
            else if (typeof(T) == typeof(AimApply))
            {
                var casted = interaction as AimApply;
                msg.TargetPosition   = casted.TargetPosition;               //TODO add client Origin
                msg.MouseButtonState = casted.MouseButtonState;
                msg.TargetBodyPart   = casted.TargetBodyPart;
            }
            else if (typeof(T) == typeof(MouseDrop))
            {
                var casted = interaction as MouseDrop;
                msg.TargetObject = GetNetId(casted.TargetObject);
                msg.UsedObject   = GetNetId(casted.UsedObject);
            }
            else if (typeof(T) == typeof(InventoryApply))
            {
                var casted = interaction as InventoryApply;

                //StorageIndexOnGameObject
                msg.StorageIndexOnGameObject = 0;
                foreach (var itemStorage in NetworkIdentity.spawned[casted.TargetSlot.ItemStorageNetID].GetComponents <ItemStorage>())
                {
                    if (itemStorage == casted.TargetSlot.ItemStorage)
                    {
                        break;
                    }

                    msg.StorageIndexOnGameObject++;
                }
                msg.Storage    = casted.TargetSlot.ItemStorageNetID;
                msg.SlotIndex  = casted.TargetSlot.SlotIdentifier.SlotIndex;
                msg.NamedSlot  = casted.TargetSlot.SlotIdentifier.NamedSlot.GetValueOrDefault(NamedSlot.none);
                msg.UsedObject = GetNetId(casted.UsedObject);
                msg.IsAltUsed  = casted.IsAltClick;
            }
            else if (typeof(T) == typeof(ConnectionApply))
            {
                var casted = interaction as ConnectionApply;
                msg.TargetObject     = GetNetId(casted.TargetObject);
                msg.TargetPosition   = casted.TargetPosition;
                msg.connectionPointA = casted.WireEndA;
                msg.connectionPointB = casted.WireEndB;
            }
            else if (typeof(T) == typeof(ContextMenuApply))
            {
                var casted = interaction as ContextMenuApply;
                msg.TargetObject    = GetNetId(casted.TargetObject);
                msg.RequestedOption = casted.RequestedOption;
            }
            else if (typeof(T) == typeof(AiActivate))
            {
                var casted = interaction as AiActivate;
                msg.TargetObject = GetNetId(casted.TargetObject);
                msg.ClickTypes   = casted.ClickType;
            }

            Send(msg);
        }
    //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();
    }