Inheritance: NetworkBehaviour
    /// <summary>
    /// Called when a state is received from server
    /// </summary>
    /// <param name="newState"></param>
    public void ReceiveState(CharacterNetworkSync.CharacterState newState)
    {
        //Other Clients: Shift buffer and store at first position
        for (int i = bufferedStates.Length - 1; i >= 1; i--)
        {
            bufferedStates[i] = bufferedStates[i - 1];
        }
        bufferedStates[0] = newState;
        bufferedStatesCount = Mathf.Min(bufferedStatesCount + 1, bufferedStates.Length);

        //Other Clients: Check that states are in good order
        for (int i = 0; i < bufferedStatesCount - 1; i++)
        {
            if (bufferedStates[i].state < bufferedStates[i + 1].state)
            {
                Debug.LogWarning("Warning, State are in wrong order");

            }
        }

        lastBufferedStateTime = Time.time;
    }
    /// <summary>
    /// Receive a good state from the server
    /// Discard input older than this good state
    /// Replay missing inputs on top of it
    /// </summary>
    /// <param name="serverRecvState"></param>
    /// <param name="serverRecvPosition"></param>
    /// <param name="serverRecvRotation"></param>
    void ServerState(CharacterNetworkSync.CharacterState characterState)
    {
        int serverRecvState = characterState.state;
        Vector3 serverRecvPosition = characterState.position;
        Quaternion serverRecvRotation = characterState.rotation;

        //Client: Check that we received a new state from server (not some delayed packet)
        if (clientAckState < serverRecvState)
        {
            //Client: Set the last server ack state
            clientAckState = serverRecvState;

            //Client: Discard all input states where state are before the ack state
            bool loop = true;
            while (loop && inputStates.Count > 0)
            {
                CharacterInput.InputState state = inputStates.Peek();
                if (state.inputState <= clientAckState)
                {
                    inputStates.Dequeue();
                }
                else
                {
                    loop = false;
                }
            }

            //Client: store actual Character position, rotation and velocity along with current input
            CharacterInput.InputState oldState = characterInput.currentInput;
            Vector3 oldPos = transform.position;
            Quaternion oldRot = transform.rotation;

            //Client: move back the player to the received server position
            serverLastRecvPosition = serverRecvPosition;
            serverLastRecvRotation = serverRecvRotation;
            transform.position = serverLastRecvPosition;
            transform.rotation = serverLastRecvRotation;

            //Client: replay all input based on new correct position
            foreach(CharacterInput.InputState state in inputStates)
            {
                //Set the input
                characterInput.currentInput = state;
                //Run the simulation
                characterMovement.RunUpdate(Time.fixedDeltaTime);
                characterRotation.RunUpdate(Time.fixedDeltaTime);
            }
            //Client: save the new predicted character position
            serverLastPredPosition = transform.position;
            serverLastPredRotation = transform.rotation;

            //Client: restore initial position, rotation and velocity
            characterInput.currentInput = oldState;
            transform.position = oldPos;
            transform.rotation = oldRot;

            //Client: Check if a prediction error occured in the past
            //Debug.Log("States in queue: " + inputStates.Count + " Predicted distance: " + Vector3.Distance(transform.position, serverLastPredPosition));
            if (Vector3.Distance(transform.position, serverLastPredPosition) > MAX_SERVER_DISTANCE_SNAP)
            {
                //Client: Snap to correct position
                Debug.LogWarning("Prediction error!");
                transform.position = Vector3.Lerp(transform.position, serverLastPredPosition, Time.fixedDeltaTime * 10);
                transform.rotation = Quaternion.Lerp(transform.rotation, serverLastPredRotation, Time.fixedDeltaTime * 10);
            }
        }
    }