Exemple #1
0
        public virtual bool WillInteract(AimApply interaction, NetworkSide side)
        {
            if (!DefaultWillInteract.Default(interaction, side))
            {
                return(false);
            }

            if (CurrentMagazine == null)
            {
                PlayEmptySFX();
                if (side == NetworkSide.Server)
                {
                    Logger.LogTrace("Server rejected shot - No magazine being loaded", Category.Firearms);
                }
                return(false);
            }

            //note: fire count down is only checked local player side, as server processes all the shots in a queue
            //anyway so client cannot exceed that firing rate no matter what. If we validate firing rate server
            //side at the moment of interaction, it will reject client's shots because of lag between server / client
            //firing countdown
            if (side == NetworkSide.Server || FireCountDown <= 0)
            {
                if (CurrentMagazine.ClientAmmoRemains <= 0)
                {
                    if (SmartGun && allowMagazineRemoval)                     // smartGun is forced off when using an internal magazine
                    {
                        RequestUnload(CurrentMagazine);
                        OutOfAmmoSFX();
                    }
                    else
                    {
                        PlayEmptySFX();
                    }
                    if (side == NetworkSide.Server)
                    {
                        Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms);
                    }
                    return(false);
                }

                if (CurrentMagazine.containedBullets[0] != null)
                {
                    if (interaction.MouseButtonState == MouseButtonState.PRESS)
                    {
                        return(true);
                    }
                    else
                    {
                        //being held, only can shoot if this is an automatic
                        return(WeaponType == WeaponType.FullyAutomatic);
                    }
                }
            }

            if (side == NetworkSide.Server)
            {
                Logger.LogTraceFormat("Server rejected shot - unknown reason. MouseButtonState {0} ammo remains {1} weapon type {2}", Category.Firearms,
                                      interaction.MouseButtonState, CurrentMagazine.ClientAmmoRemains, WeaponType);
            }
            return(false);
        }
 /// <summary>
 /// Default WIllInteract logic for PositionalHandApply interactions
 /// </summary>
 public static bool PositionalHandApply(PositionalHandApply interaction, NetworkSide side)
 {
     return(Validations.CanApply(interaction, side));
 }
Exemple #3
0
 /// <summary>
 /// Determines if the interaction request for uncuffing is valid clientside and if true, then serverside
 /// </summary>
 public bool WillInteract(ContextMenuApply interaction, NetworkSide side)
 {
     return(DefaultWillInteract.Default(interaction, side) && IsCuffed);
 }
 //shorthand for calling GetAt at the targeted object's position
 public static List <T> GetAt <T>(GameObject targetObject, NetworkSide side) where T : MonoBehaviour
 {
     return(GetAt <T>((Vector3Int)targetObject.TileWorldPosition(), side == NetworkSide.Server));
 }
 /// <summary>
 /// Default WillInteract logic for MouseDrop
 /// </summary>
 public static bool MouseDrop(MouseDrop interaction, NetworkSide side)
 {
     return(Validations.CanApply(interaction, side));
 }
Exemple #6
0
        public bool StartNetworking(NetworkSide _side, bool clientDefaultReconnect = false, bool dontUseNetworkStream = false)
        {
            if (supposedToBeConnected && !(side == NetworkSide.DISCONNECTED || side == NetworkSide.CONNECTIONLOST))
            {
                return(false);
            }

            //if (side != NetworkSide.CONNECTIONLOST)
            //{
            //	CommandQueue.Clear();
            //	PeerCommandQueue.Clear();
            //}

            if (CommandQueueProcessorTimer == null)
            {
                CommandQueueProcessorTimer          = new System.Windows.Forms.Timer();
                CommandQueueProcessorTimer.Interval = 5;
                CommandQueueProcessorTimer.Tick    += CommandQueueProcessorTimer_Tick;
                CommandQueueProcessorTimer.Start();
            }

            if (_side == NetworkSide.CLIENT)
            {
                side         = NetworkSide.CLIENT;
                expectedSide = NetworkSide.CLIENT;
                if (!StartClient(clientDefaultReconnect))
                {
                    return(false);
                }

                OnClientConnecting(null);
            }
            else if (_side == NetworkSide.SERVER)
            {
                side         = NetworkSide.SERVER;
                expectedSide = NetworkSide.SERVER;

                StartServer(dontUseNetworkStream);

                OnServerStarted(null);
            }
            else
            {
                return(false);
            }

            KeepAliveCounter = DefaultKeepAliveCounter;

            if (KeepAliveTimer == null)
            {
                KeepAliveTimer          = new System.Windows.Forms.Timer();
                KeepAliveTimer.Interval = 666;
                KeepAliveTimer.Tick    += KeepAliveTimer_Tick;
                KeepAliveTimer.Start();
            }

            if (_side == NetworkSide.SERVER)
            {
                expectingSomeone = false;
            }

            supposedToBeConnected = true;

            return(true);
        }
 /// <summary>
 /// Decides if interaction logic should proceed. On client side, the interaction
 /// request will only be sent to the server if this returns true. On server side,
 /// the interaction will only be performed if this returns true.
 ///
 /// Each interaction has a default implementation of this which should apply for most cases.
 /// By overriding this and adding more specific logic, you can reduce the amount of messages
 /// sent by the client to the server, decreasing overall network load.
 /// </summary>
 /// <param name="interaction">interaction to validate</param>
 /// <param name="side">which side of the network this is being invoked on</param>
 /// <returns>True/False based on whether the interaction logic should proceed as described above.</returns>
 protected virtual bool WillInteract(HandApply interaction, NetworkSide side)
 {
     return(DefaultWillInteract.Default(interaction, side));
 }
Exemple #8
0
 /// <summary>
 /// Allow honking when barely conscious
 /// </summary>
 public bool WillInteract(HandActivate interaction, NetworkSide side)
 {
     return(Validations.CanInteract(interaction.Performer, side, true) &&
            allowUse);
 }
 /// <summary>
 /// Starts the cooldown if it's not currently on.
 /// </summary>
 /// <param name="cooldown">cooldown to try</param>
 /// <param name="side">indicates which side's cooldown should be started</param>
 /// <param name="secondsOverride">custom cooldown time in seconds</param>
 /// <returns>true if cooldown was successfully started, false if cooldown was already on.</returns>
 public bool TryStart(ICooldown cooldown, NetworkSide side, float secondsOverride = float.NaN)
 {
     return(TryStart(CooldownID.Asset(cooldown, side), float.IsNaN(secondsOverride) ? cooldown.DefaultTime : secondsOverride));
 }
 public NetworkState ReadPacket(PacketByteBuf packet, NetworkState state, NetworkSide side)
 {
     compressionThreshold = packet.ReadVarInt();
     Debug.LogWarning($"JDJDDJJDDJJD {compressionThreshold}");
     return(state);
 }
 public NetworkState WritePacket(PacketByteBuf packet, NetworkState state, NetworkSide side)
 {
     packet.WriteVarInt(compressionThreshold);
     return(state);
 }
    private static bool CanInteractByConsciousState(PlayerHealth playerHealth, bool allowSoftCrit, NetworkSide side)
    {
        if (side == NetworkSide.Client)
        {
            //we only know our own conscious state, so assume true if it's not our local player
            if (playerHealth.gameObject != PlayerManager.LocalPlayer)
            {
                return(true);
            }
        }

        return(playerHealth.ConsciousState == ConsciousState.CONSCIOUS ||
               playerHealth.ConsciousState == ConsciousState.BARELY_CONSCIOUS && allowSoftCrit);
    }
Exemple #13
0
 /// <summary>
 /// A cooldown which is identified by a particular TYPE of interactable component. Useful for
 /// creating interactable components with their own specific cooldown without needing to create
 /// an actual cooldown asset. The specific instance
 /// doesn't matter - this cooldown is shared by all instances of that type. For example, you'd always get
 /// the same CooldownIdentifier regardless of which object's Meleeable component you passed to this.
 /// </summary>
 /// <param name="interactable"></param>
 /// <param name="side">network side this cooldown is for</param>
 /// <returns></returns>
 public static CooldownID Interaction <T>(IInteractable <T> interactable, NetworkSide side) where T : Interaction
 {
     return(new CooldownID(null, interactable.GetType(),
                           side, CooldownType.Interaction));
 }
Exemple #14
0
 /// <summary>
 /// Cooldown identified by a particular cooldown asset.
 /// </summary>
 /// <param name="cooldownAsset"></param>
 /// <param name="side">network side this cooldown is for</param>
 /// <returns></returns>
 public static CooldownID Asset(Cooldown cooldownAsset, NetworkSide side)
 {
     return(new CooldownID(cooldownAsset, null, side, CooldownType.Asset));
 }
Exemple #15
0
        public void StoreCommands(NetworkStream providedStream, bool dontCreateNetworkStream = false)
        {
            var binaryFormatter = new BinaryFormatter();

            TcpListener   server        = null;
            Socket        socket        = null;
            NetworkStream networkStream = null;

            if (providedStream != null)
            {
                networkStream = providedStream;
            }

            try
            {
                if (networkStream == null && !dontCreateNetworkStream)
                {
                    server = new TcpListener(IPAddress.Any, port);
                    server.Start();
                    socket        = KillableAcceptSocket(server);
                    networkStream = new NetworkStream(socket);
                    server.Stop();
                }

                networkStream.ReadTimeout  = DefaultNetworkStreamTimeout;
                networkStream.WriteTimeout = DefaultNetworkStreamTimeout;

                if (side == NetworkSide.CLIENT)
                {
                    SendCommand(new RTC_Command(CommandType.HI), false, true);
                }

                while (true)
                {
                    if (networkStream != null && networkStream.DataAvailable)
                    {
                        RTC_Command cmd;

                        try
                        {
                            cmd = (RTC_Command)binaryFormatter.Deserialize(networkStream);
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }

                        if (cmd != null)
                        {
                            if (cmd.Type == CommandType.RETURNVALUE)
                            {
                                ReturnWatch.SyncReturns.Add((Guid)cmd.requestGuid, cmd.objectValue);
                            }
                            else
                            {
                                CommandQueue.AddLast(cmd);
                            }
                        }
                    }

                    while (PeerCommandQueue.Count > 0)
                    {
                        RTC_Command backCmd;

                        lock (CommandQueueLock)
                        {
                            backCmd = PeerCommandQueue.First.Value;
                            PeerCommandQueue.RemoveFirst();
                        }

                        try
                        {
                            binaryFormatter.Serialize(networkStream, backCmd);
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }

                        if (backCmd.Type == CommandType.BYE)
                        {
                            CommandQueue.AddFirst(new RTC_Command(CommandType.SAIDBYE));
                            PeerCommandQueue.Clear();
                            throw new Exception("SAIDBYE");
                        }

                        if (side == NetworkSide.DISCONNECTED || side == NetworkSide.CONNECTIONLOST)
                        {
                            if (side == NetworkSide.DISCONNECTED)
                            {
                                CommandQueue.Clear();
                                PeerCommandQueue.Clear();
                            }

                            throw new Exception(side.ToString());
                        }
                    }

                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                OutputException(ex);

                if (side == NetworkSide.CLIENT || side == NetworkSide.SERVER)
                {
                    side = NetworkSide.CONNECTIONLOST;
                }
            }
            finally
            {
                if (networkStream != null)
                {
                    try
                    {
                        networkStream.Close();
                        networkStream.Dispose();
                    }
                    catch (Exception ex2) { OutputException(ex2); }
                }

                if (socket != null)
                {
                    //socket.Close();
                    try
                    {
                        socket.Shutdown(SocketShutdown.Both);
                        socket.Dispose();
                    }
                    catch (Exception ex2) { OutputException(ex2); }
                }

                if (server != null)
                {
                    try
                    {
                        server.Stop();
                    }
                    catch (Exception ex2) { OutputException(ex2); }
                }

                isStreamReadingThreadAlive = false;
            }
        }
 /// <summary>
 /// Starts a cooldown (if it's not already on) which is identified by a particular TYPE of interactable component. The specific instance
 /// doesn't matter - this cooldown is shared by all instances of that type. For example, you'd always start
 /// the same cooldown regardless of which object's Meleeable component you passed to this (this is
 /// usually the intended behavior for interactable components - you don't care which object's interaction
 /// you are triggering - you should still have the same cooldown for melee regardless of who you are hitting).
 /// Intended for convenience / one-off usage in small interactable components so you don't need
 /// to create an asset.
 /// </summary>
 /// <param name="cooldown">interactable component whose cooldown should be started</param>
 /// <param name="seconds">how many seconds the cooldown should take</param>
 /// <param name="side">indicates which side's cooldown should be started</param>
 /// <returns>true if cooldown was successfully started, false if cooldown was already on.</returns>
 public bool TryStart <T>(IInteractable <T> interactable, float seconds, NetworkSide side)
     where T : Interaction
 {
     return(TryStart(CooldownID.Interaction(interactable, side), seconds));
 }
Exemple #17
0
        public void StopNetworking(bool fromBye = false, bool stayConnected = false)
        {
            //if ((side == NetworkSide.CONNECTIONLOST || side == NetworkSide.DISCONNECTED) && stayConnected)
            //	return;

            //supposedToBeConnected = stayConnected;

            if (!fromBye)
            {
                SendCommand(new RTC_Command(CommandType.SAYBYE), true, true);
                return;
            }

            if (!stayConnected)
            {
                expectingSomeone = false;
            }

            if (expectedSide == NetworkSide.CLIENT)
            {
                if (stayConnected)
                {
                    OnClientConnectionLost(null);
                }
                else
                {
                    OnClientDisconnected(null);
                }
            }
            else if (expectedSide == NetworkSide.SERVER)
            {
                if (!stayConnected)
                {
                    OnServerDisconnected(null);
                }
            }

            side = (stayConnected ? NetworkSide.CONNECTIONLOST : NetworkSide.DISCONNECTED);

            if (side == NetworkSide.DISCONNECTED)
            {
                CommandQueue.Clear();
                PeerCommandQueue.Clear();
            }

            if (streamReadingThread != null)
            {
                streamReadingThread.Abort();
                streamReadingThread = null;
            }


            if (clientStream != null)
            {
                clientStream.Close();
                clientStream = null;
            }

            if (client != null)
            {
                client.Close();
                client = null;
            }

            /*
             * if (CommandQueueProcessorTimer != null)
             * {
             *      CommandQueueProcessorTimer.Stop();
             *      CommandQueueProcessorTimer = null;
             * }
             */

            if (!stayConnected)
            {
                if (KeepAliveTimer != null)
                {
                    KeepAliveTimer.Stop();
                    KeepAliveTimer = null;
                }
            }

            if (!stayConnected)
            {
                supposedToBeConnected = false;
            }
        }
    /// <summary>
    /// Validates if the performer is in range and not in crit, which are typical requirements for all
    /// various interactions. Works properly even if player is hidden in a ClosetControl. Can also optionally allow soft crit.
    ///
    /// For PositionalHandApply, reach range is based on how far away they are clicking from themselves
    /// </summary>
    /// <param name="player">player performing the interaction</param>
    /// <param name="target">target object</param>
    /// <param name="side">side of the network this is being checked on</param>
    /// <param name="allowSoftCrit">whether to allow interaction while in soft crit</param>
    /// <param name="reachRange">range to allow</param>
    /// <param name="targetVector">target vector pointing from performer to the position they are trying to click,
    /// if specified will use this to determine if in range rather than target object position.</param>
    /// <returns></returns>
    public static bool CanApply(GameObject player, GameObject target, NetworkSide side, bool allowSoftCrit = false,
                                ReachRange reachRange = ReachRange.Standard, Vector2?targetVector = null)
    {
        if (player == null)
        {
            return(false);
        }
        var playerScript      = player.GetComponent <PlayerScript>();
        var playerObjBehavior = player.GetComponent <ObjectBehaviour>();

        if (!CanInteract(player, side, allowSoftCrit))
        {
            return(false);
        }

        //no matter what, if player is in closet, they can only reach the closet
        if (playerScript.IsHidden)
        {
            //Client does not seem to know what they are hidden in (playerObjBehavior.parentContianer is not set clientside),
            //so in this case they simply validate this and defer to the server to decide if it's valid
            //TODO: Correct this if there is a way for client to know their container.
            if (side == NetworkSide.Client)
            {
                return(true);
            }
            else
            {
                //server checks if player is trying to click the container they are in.
                var parentObj = playerObjBehavior.parentContainer != null
                                        ? playerObjBehavior.parentContainer.gameObject
                                        : null;
                return(parentObj == target);
            }
        }

        var result = false;

        if (reachRange == ReachRange.Unlimited)
        {
            result = true;
        }
        else if (reachRange == ReachRange.Standard)
        {
            var targetWorldPosition =
                targetVector != null ? player.transform.position + targetVector : target.transform.position;
            result = playerScript.IsInReach((Vector3)targetWorldPosition, side == NetworkSide.Server);
        }
        else if (reachRange == ReachRange.ExtendedServer)
        {
            //we don't check range client-side for this case.
            if (side == NetworkSide.Client)
            {
                result = true;
            }
            else
            {
                var cnt = target.GetComponent <CustomNetTransform>();
                if (cnt == null)
                {
                    var targetWorldPosition =
                        targetVector != null ? player.transform.position + targetVector : target.transform.position;
                    //fallback to standard range check if there is no CNT
                    result = playerScript.IsInReach((Vector3)targetWorldPosition, side == NetworkSide.Server);
                }
                else
                {
                    result = ServerCanReachExtended(playerScript, cnt.ServerState);
                }
            }
        }

        if (!result && side == NetworkSide.Server)
        {
            //client tried to do something out of range, report it
            var cnt = target.GetComponent <CustomNetTransform>();
            Logger.LogTraceFormat("Not in reach! server pos:{0} player pos:{1} (floating={2})", Category.Security,
                                  cnt.ServerState.WorldPosition, player.transform.position, cnt.IsFloatingServer);
        }

        return(result);
    }
 /// <summary>
 /// Decides if interaction logic should proceed. On client side, the interaction
 /// request will only be sent to the server if this returns true. On server side,
 /// the interaction will only be performed if this returns true.
 ///
 /// Each interaction has a default implementation of this which should apply for most cases.
 /// By overriding this and adding more specific logic, you can reduce the amount of messages
 /// sent by the client to the server, decreasing overall network load.
 /// </summary>
 /// <param name="interaction">interaction to validate</param>
 /// <param name="side">which side of the network this is being invoked on</param>
 /// <returns>True/False based on whether the interaction logic should proceed as described above.</returns>
 protected virtual bool WillInteract(MouseDrop interaction, NetworkSide side)
 {
     return(DefaultWillInteract.Default(interaction, side));
 }
 /// <summary>
 /// Validates if the performer is in range and not in crit for a PositionalHandApply interaction.
 /// Range check is based on the target vector of toValidate, not the distance to the object.
 /// </summary>
 /// <param name="toValidate">interaction to validate</param>
 /// <param name="side">side of the network this is being checked on</param>
 /// <param name="allowSoftCrit">whether to allow interaction while in soft crit</param>
 /// <param name="reachRange">range to allow</param>
 /// <returns></returns>
 public static bool CanApply(PositionalHandApply toValidate, NetworkSide side, bool allowSoftCrit = false, ReachRange reachRange = ReachRange.Standard) =>
 CanApply(toValidate.Performer, toValidate.TargetObject, side, allowSoftCrit, reachRange, toValidate.TargetVector);
Exemple #21
0
 public bool WillInteract(HandActivate interaction, NetworkSide side)
 {
     return(DefaultWillInteract.Default(interaction, side));
 }
 /// <summary>
 /// Validates if the performer is in range and not in crit for a MouseDrop interaction.
 /// </summary>
 /// <param name="toValidate">interaction to validate</param>
 /// <param name="side">side of the network this is being checked on</param>
 /// <param name="allowSoftCrit">whether to allow interaction while in soft crit</param>
 /// <param name="reachRange">range to allow</param>
 /// <returns></returns>
 public static bool CanApply(MouseDrop toValidate, NetworkSide side, bool allowSoftCrit = false, ReachRange reachRange = ReachRange.Standard) =>
 CanApply(toValidate.Performer, toValidate.TargetObject, side, allowSoftCrit, reachRange);
 /// <summary>
 /// Default WillInteract logic for Activate
 /// </summary>
 public static bool HandActivate(HandActivate interaction, NetworkSide side)
 {
     return(Validations.CanInteract(interaction.Performer, side));
 }
 /// <summary>
 /// Checks if the player can currently put the indicated item in this slot. Correctly handles logic for client / server side, so is
 /// recommended to use in WillInteract rather than other ways of checking fit.
 /// </summary>
 /// <param name="player">player to check</param>
 /// <param name="itemSlot">slot to check</param>
 /// <param name="toCheck">item to check for fit</param>
 /// <param name="side">network side check is happening on</param>
 /// <param name="ignoreOccupied">if true, does not check if an item is already in the slot</param>
 /// <param name="examineRecipient">if not null, when validation fails, will output an appropriate examine message to this recipient</param>
 /// <returns></returns>
 public static bool CanPutItemToSlot(PlayerScript playerScript, ItemSlot itemSlot, Pickupable toCheck, NetworkSide side,
                                     bool ignoreOccupied = false, GameObject examineRecipient = null)
 {
     if (toCheck == null || itemSlot.Item != null)
     {
         Logger.LogTrace("Cannot put item to slot because the item or slot are null", Category.Inventory);
         return(false);
     }
     if (playerScript.canNotInteract())
     {
         Logger.LogTrace("Cannot put item to slot because the player cannot interact", Category.Inventory);
         return(false);
     }
     if (!CanFit(itemSlot, toCheck, side, ignoreOccupied, examineRecipient))
     {
         Logger.LogTraceFormat("Cannot put item to slot because the item {0} doesn't fit in the slot {1}", Category.Inventory,
                               toCheck.name, itemSlot);
         return(false);
     }
     return(true);
 }
 /// <summary>
 /// Default WillInteract logic for AimApply
 /// </summary>
 public static bool AimApply(AimApply interaction, NetworkSide side)
 {
     return(Validations.CanInteract(interaction.Performer, side));
 }
    /// <summary>
    /// Client:
    /// Allow items to be stored by clicking on bags with item in hand
    /// and clicking items with bag in hand if CanClickPickup is enabled
    /// </summary>
    public bool WillInteract(PositionalHandApply interaction, NetworkSide side)
    {
        if (allowedToInteract == false)
        {
            return(false);
        }
        // Use default interaction checks
        if (DefaultWillInteract.Default(interaction, side) == false)
        {
            return(false);
        }

        // See which item needs to be stored
        if (Validations.IsTarget(gameObject, interaction))
        {
            // We're the target
            // If player's hands are empty let Pickupable handle the interaction
            if (interaction.HandObject == null)
            {
                return(false);
            }

            // There's something in the player's hands
            // Check if item from the hand slot fits in this storage sitting in the world
            if (Validations.CanPutItemToStorage(interaction.PerformerPlayerScript,
                                                itemStorage, interaction.HandObject, side, examineRecipient: interaction.Performer) == false)
            {
                Chat.AddExamineMsgToClient($"The {interaction.HandObject.ExpensiveName()} doesn't fit!");
                return(false);
            }

            return(true);
        }
        else if (canClickPickup)
        {
            // If we can click pickup then try to store the target object
            switch (pickupMode)
            {
            case PickupMode.Single:
                // See if there's an item to pickup
                if (interaction.TargetObject == null ||
                    interaction.TargetObject.Item() == null)
                {
                    Chat.AddExamineMsgToClient("There's nothing to pickup!");
                    return(false);
                }

                if (!Validations.CanPutItemToStorage(interaction.PerformerPlayerScript,
                                                     itemStorage, interaction.TargetObject, side, examineRecipient: interaction.Performer))
                {
                    // In Single pickup mode if the target item doesn't
                    // fit then don't interact
                    Chat.AddExamineMsgToClient($"The {interaction.TargetObject.ExpensiveName()} doesn't fit!");
                    return(false);
                }

                break;

            case PickupMode.Same:
                if (interaction.TargetObject == null)
                {
                    // If there's nothing to compare then don't interact
                    Chat.AddExamineMsgToClient("There's nothing to pickup!");
                    return(false);
                }

                break;
            }

            // In Same and All pickup modes other items on the
            // tile could still be picked up, so we interact
            return(true);
        }
        else
        {
            // We're not the target and we can't click pickup so don't do anything
            return(false);
        }
    }
Exemple #27
0
 public NetworkState WritePacket(PacketByteBuf packet, NetworkState state, NetworkSide side)
 {
     return(state);
 }
Exemple #28
0
 public bool WillInteract(HandApply interaction, NetworkSide side)
 {
     return(DefaultWillInteract.Default(interaction, side) &&
            (interaction.HandObject == null ||
             (interaction.Intent == Intent.Help || interaction.Intent == Intent.Grab)));
 }
Exemple #29
0
 /// <summary>
 /// Gets the interactable tiles for the matrix at the indicated world position. Never returns null - always
 /// returns the interactable tiles for the appropriate matrix.
 /// </summary>
 /// <param name="worldPos"></param>
 /// <returns></returns>
 public static InteractableTiles GetAt(Vector2 worldPos, NetworkSide side)
 {
     return(GetAt(worldPos, side == NetworkSide.Server));
 }
Exemple #30
0
        public bool WillInteract(HandApply interaction, NetworkSide side)
        {
            if (!DefaultWillInteract.Default(interaction, side))
            {
                return(false);
            }

            if (!Validations.IsTarget(gameObject, interaction))
            {
                return(false);
            }

            //Anchor or disassemble
            if (CurrentState == initialState)
            {
                return(Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench) ||
                       Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar));
            }

            //Adding metal or unanchor
            if (CurrentState == anchoredState)
            {
                return(Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.MetalSheet) ||
                       Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench));
            }

            //Wrench or remove metal
            if (CurrentState == metalAddedState)
            {
                return(Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench) ||
                       Validations.HasUsedActiveWelder(interaction));
            }

            //Add gun or unwrench
            if (CurrentState == wrenchState)
            {
                return(Validations.HasUsedItemTrait(interaction, gunTrait) ||
                       Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench));
            }

            //Add prox or remove gun
            if (CurrentState == gunAddedState)
            {
                return(Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.ProximitySensor) ||
                       interaction.HandObject == null);
            }

            //Screw or remove prox
            if (CurrentState == proxAddedState)
            {
                return(Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver) ||
                       interaction.HandObject == null);
            }

            //Add metal or unscrew
            if (CurrentState == screwState)
            {
                return(Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.MetalSheet) ||
                       Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver));
            }

            //Finish construction or remove metal
            if (CurrentState == secondMetalAddedState)
            {
                return(Validations.HasUsedActiveWelder(interaction) ||
                       Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar));
            }

            return(false);
        }