Example #1
0
    /// <summary>
    /// Checks both directions of a diagonal movement
    /// to see if movement or a bump resulting in an interaction is possible. Modifies
    /// the move action to switch to that direction, otherwise leaves it unmodified.
    /// Prioritizes the following when there are multiple options:
    /// 1. Move into empty space if either direction has it
    /// 2. Push an object if either direction has it
    /// 3. Open a door if either direction has it
    ///
    /// When both directions have the same condition (both doors or pushable objects), x will be preferred to y
    /// </summary>
    /// <param name="state">current state to try to slide from</param>
    /// <param name="action">current player action (which should have a diagonal movement). Will be modified if a slide is performed</param>
    /// <returns>bumptype of the final direction of movement if action is modified. Null otherwise</returns>
    private BumpType?TrySlide(PlayerState state, ref PlayerAction action)
    {
        Vector2Int direction = action.Direction();

        if (Math.Abs(direction.x) + Math.Abs(direction.y) < 2)
        {
            //not diagonal, do nothing
            return(null);
        }

        Vector2Int xDirection = new Vector2Int(direction.x, 0);
        Vector2Int yDirection = new Vector2Int(0, direction.y);
        BumpType   xBump      = MatrixManager.GetBumpTypeAt(state.WorldPosition.RoundToInt(), xDirection, gameObject);
        BumpType   yBump      = MatrixManager.GetBumpTypeAt(state.WorldPosition.RoundToInt(), yDirection, gameObject);

        MoveAction?newAction = null;
        BumpType?  newBump   = null;

        if (xBump == BumpType.None)
        {
            newAction = PlayerAction.GetMoveAction(xDirection);
            newBump   = xBump;
        }
        else if (yBump == BumpType.None)
        {
            newAction = PlayerAction.GetMoveAction(yDirection);
            newBump   = yBump;
        }
        else if (xBump == BumpType.Push)
        {
            newAction = PlayerAction.GetMoveAction(xDirection);
            newBump   = xBump;
        }
        else if (yBump == BumpType.Push)
        {
            newAction = PlayerAction.GetMoveAction(yDirection);
            newBump   = yBump;
        }
        else if (xBump == BumpType.ClosedDoor)
        {
            newAction = PlayerAction.GetMoveAction(xDirection);
            newBump   = xBump;
        }
        else if (yBump == BumpType.ClosedDoor)
        {
            newAction = PlayerAction.GetMoveAction(yDirection);
            newBump   = yBump;
        }

        if (newAction.HasValue)
        {
            action.moveActions = new int[] { (int)newAction };
            return(newBump);
        }
        else
        {
            return(null);
        }
    }
Example #2
0
    private IEnumerator DoProcess(PlayerAction action)
    {
        MoveCooldown = true;
        //experiment: not enqueueing or processing action if floating.
        //arguably it shouldn't really be like that in the future
        bool isGrounded = !IsNonStickyClient;

        //			bool isAroundPushables = IsAroundPushables( predictedState ); //? trying to remove this because of garbage
        /*(isGrounded || isAroundPushables ) &&*/
        if (!blockClientMovement && (!isPseudoFloatingClient && !isFloatingClient || playerMove.isGhost))
        {
            //				Logger.LogTraceFormat( "{0} requesting {1} ({2} in queue)", Category.Movement, gameObject.name, action.Direction(), pendingActions.Count );

            if (isGrounded && playerState.Active)
            {
                //RequestMoveMessage.Send(action);
                // Fix for #900
                BumpType clientBump = CheckSlideAndBump(predictedState, ref action);
                if (clientBump == BumpType.None || playerMove.isGhost)
                {
                    //move freely
                    pendingActions.Enqueue(action);

                    LastDirection = action.Direction();
                    UpdatePredictedState();
                }
                else
                {
                    //cannot move -> tell server we're just bumping in that direction
                    action.isBump = true;
                    if (pendingActions == null || pendingActions.Count == 0)
                    {
                        PredictiveBumpInteract(Vector3Int.RoundToInt((Vector2)predictedState.WorldPosition + action.Direction()), action.Direction());
                    }
                    if (PlayerManager.LocalPlayer == gameObject)
                    {
                        playerSprites.CmdChangeDirection(Orientation.From(action.Direction()));
                        // Prediction:
                        playerSprites.FaceDirection(Orientation.From(action.Direction()));
                    }
                    //cooldown is longer when humping walls or pushables
                    //					yield return YieldHelper.DeciSecond;
                    //					yield return YieldHelper.DeciSecond;
                }
            }
            else
            {
                action.isNonPredictive = true;
            }
            //Sending action for server approval
            CmdProcessAction(action);
        }

        yield return(YieldHelper.DeciSecond);

        MoveCooldown = false;
    }
Example #3
0
    /// <summary>
    /// Checks if any bump would occur with the movement in the specified action.
    /// If a BumpType.Blocked occurs, attempts to slide (if movement is diagonal). Updates
    /// playerAction's movement if slide occurs.
    /// </summary>
    /// <param name="playerState">state moving from</param>
    /// <param name="playerAction">action indicating the movement, will be modified if slide occurs</param>
    /// <returns>the type of bump that occurs at the final destination (after sliding has been attempted)</returns>
    private BumpType CheckSlideAndBump(PlayerState playerState, ref PlayerAction playerAction)
    {
        BumpType bump = MatrixManager.GetBumpTypeAt(playerState, playerAction, gameObject);

        // if movement is blocked, try to slide
        if (bump == BumpType.Blocked)
        {
            return(TrySlide(playerState, ref playerAction) ?? bump);
        }

        return(bump);
    }
Example #4
0
    private PlayerState NextStateServer(PlayerState state, PlayerAction action)
    {
        //Check if there is a bump interaction according to the server
        BumpType serverBump = CheckSlideAndBump(state, ref action);

        //Client only needs to check whether movement was prevented, specific type of bump doesn't matter
        bool isClientBump = action.isBump;

        //we only lerp back if the client thinks it's passable  but server does not...if client
        //thinks it's not passable and server thinks it's passable, then it's okay to let the client continue
        if (!isClientBump && serverBump != BumpType.None)
        {
            Logger.LogWarningFormat("isBump mismatch, resetting: C={0} S={1}", Category.Movement, isClientBump, serverBump != BumpType.None);
            RollbackPosition();
        }
        if (isClientBump || serverBump != BumpType.None)
        {
            // we bumped something, an interaction might occur
            // try pushing things / opening doors
            BumpInteract(state.WorldPosition, (Vector2)action.Direction());

            playerSprites.FaceDirection(Orientation.From(action.Direction()));
            return(state);
        }

        if (IsNonStickyServer)
        {
            PushPull pushable;
            if (IsAroundPushables(serverState, out pushable))
            {
                StartCoroutine(InteractSpacePushable(pushable, action.Direction()));
            }
            return(state);
        }

        if (action.isNonPredictive)
        {
            Logger.Log("Ignored action marked as Non-predictive while being indoors", Category.Movement);
            return(state);
        }

        bool        matrixChangeDetected;
        PlayerState nextState = NextState(state, action, out matrixChangeDetected);

        if (!matrixChangeDetected)
        {
            return(nextState);
        }

        return(nextState);
    }
    // ---------------------------------------------------------------------------

    private IEnumerator Bump(BumpType bumpType)
    {
        float sign = (bumpType == BumpType.Stone ? 1 : -1);
        float time = 0;

        while (time < bumpDuration)
        {
            float angle = time / bumpDuration * Mathf.PI;
            bumpComponent = new Vector3(0, Mathf.Sin(angle) * bumpIntensity * sign, 0);
            yield return(new WaitForEndOfFrame());

            time += Time.deltaTime;
        }
    }
Example #6
0
        static void TestBump(BumpType bumpType, string fileContainingExpectedContents)
        {
            // Arrange
            File.Delete(Config.Releases.Files.AssemblyInfo.After);
            File.Copy(Config.Releases.Files.AssemblyInfo.Before, Config.Releases.Files.AssemblyInfo.After);

            var bump = Task.New<BumpAssemblyInfo>();
            bump.In.FileName = Config.Releases.Files.AssemblyInfo.After;
            bump.In.BumpType = bumpType;

            // Act
            bump.Execute();

            // Assert
            var afterContents = File.ReadAllText(Config.Releases.Files.AssemblyInfo.After);
            var expectedContents = File.ReadAllText(fileContainingExpectedContents);
            Assert.That(afterContents, Is.EqualTo(expectedContents));
        }
        static void TestBump(BumpType bumpType, string fileContainingExpectedContents)
        {
            // Arrange
            File.Delete(Config.Releases.Files.AssemblyInfo.After);
            File.Copy(Config.Releases.Files.AssemblyInfo.Before, Config.Releases.Files.AssemblyInfo.After);

            var bump = Task.New <BumpAssemblyInfo>();

            bump.In.FileName = Config.Releases.Files.AssemblyInfo.After;
            bump.In.BumpType = bumpType;

            // Act
            bump.Execute();

            // Assert
            var afterContents    = File.ReadAllText(Config.Releases.Files.AssemblyInfo.After);
            var expectedContents = File.ReadAllText(fileContainingExpectedContents);

            Assert.That(afterContents, Is.EqualTo(expectedContents));
        }
 // Methods for car
 // ----------------------------------------------------------------------------
 public void DoBump(BumpType bumpType)
 {
     StartCoroutine(Bump(bumpType));
 }
    private PlayerState NextStateServer(PlayerState state, PlayerAction action)
    {
        //Check if there is a bump interaction according to the server
        BumpType serverBump = CheckSlideAndBump(state, ref action);

        //Client only needs to check whether movement was prevented, specific type of bump doesn't matter
        bool isClientBump = action.isBump;

        //we only lerp back if the client thinks it's passable  but server does not...if client
        //thinks it's not passable and server thinks it's passable, then it's okay to let the client continue
        if (!isClientBump && serverBump != BumpType.None)
        {
            Logger.LogWarningFormat("isBump mismatch, resetting: C={0} S={1}", Category.Movement, isClientBump, serverBump != BumpType.None);
            RollbackPosition();
        }
        if (isClientBump || serverBump != BumpType.None)
        {
            // we bumped something, an interaction might occur
            // try pushing things / opening doors
            BumpInteract(state.WorldPosition, (Vector2)action.Direction());

            playerSprites.FaceDirection(Orientation.From(action.Direction()));
            return(state);
        }

        if (IsNonStickyServer)
        {
            PushPull pushable;
            if (IsAroundPushables(serverState, out pushable))
            {
                StartCoroutine(InteractSpacePushable(pushable, action.Direction()));
            }
            return(state);
        }

        if (action.isNonPredictive)
        {
            Logger.Log("Ignored action marked as Non-predictive while being indoors", Category.Movement);
            return(state);
        }

        bool        matrixChangeDetected;
        PlayerState nextState = NextState(state, action, out matrixChangeDetected);

        if (!matrixChangeDetected)
        {
            return(nextState);
        }

        //todo: subscribe to current matrix rotations on spawn
        var newMatrix = MatrixManager.Get(nextState.MatrixId);

        Logger.Log($"Matrix will change to {newMatrix}", Category.Movement);
        if (newMatrix.MatrixMove)
        {
            //Subbing to new matrix rotations
            newMatrix.MatrixMove.OnRotate.AddListener(OnRotation);
            //				Logger.Log( $"Registered rotation listener to {newMatrix.MatrixMove}" );
        }

        //Unsubbing from old matrix rotations
        MatrixMove oldMatrixMove = MatrixManager.Get(Matrix).MatrixMove;

        if (oldMatrixMove)
        {
            //				Logger.Log( $"Unregistered rotation listener from {oldMatrixMove}" );
            oldMatrixMove.OnRotate.RemoveListener(OnRotation);
        }

        return(nextState);
    }
Example #10
0
 public DateTime BumpDate(DateTime date, BumpType bumpType)
 {
     throw new NotImplementedException();
 }