public void UpdatePlayer(PlayerObjectComponent playerObjectComponent)
    {
        var playerObjectState = playerObjectComponent.State;

        var client = OsFps.Instance?.Client;
        var equippedWeaponComponent = GetEquippedWeaponComponent(playerObjectComponent);

        if (playerObjectState.IsEquippingWeapon)
        {
            playerObjectState.EquipWeaponTimeLeft -= Time.deltaTime;
        }
        else if (playerObjectState.IsReloading)
        {
            playerObjectState.ReloadTimeLeft -= Time.deltaTime;
        }
        else if (playerObjectState.IsWeaponRecoiling)
        {
            playerObjectState.RecoilTimeLeft -= Time.deltaTime;
        }

        if (playerObjectState.CurrentWeapon != null)
        {
            playerObjectState.CurrentWeapon.TimeSinceLastShot += Time.deltaTime;
        }

        if (equippedWeaponComponent != null)
        {
            if (playerObjectState.IsEquippingWeapon)
            {
                var percentDoneEquipping = (OsFps.EquipWeaponTime - playerObjectState.EquipWeaponTimeLeft) / OsFps.EquipWeaponTime;
                GameObjectExtensions.EnsurePlayingInBaseLayerAndSetNormalizedTime(
                    equippedWeaponComponent.Animator, "Equip", percentDoneEquipping
                    );
            }
            else if (playerObjectState.IsReloading)
            {
                var weaponReloadTime     = playerObjectState.CurrentWeapon.Definition.ReloadTime;
                var percentDoneReloading = (weaponReloadTime - playerObjectState.ReloadTimeLeft) / weaponReloadTime;
                GameObjectExtensions.EnsurePlayingInBaseLayerAndSetNormalizedTime(
                    equippedWeaponComponent.Animator, "Reload", percentDoneReloading
                    );
            }
            else if (playerObjectState.IsWeaponRecoiling)
            {
                var recoilTime            = playerObjectState.CurrentWeapon.Definition.RecoilTime;
                var percentDoneWithRecoil = Mathf.Min(
                    (recoilTime - playerObjectState.RecoilTimeLeft) / recoilTime,
                    1
                    );
                GameObjectExtensions.EnsurePlayingInBaseLayerAndSetNormalizedTime(
                    equippedWeaponComponent.Animator, "Recoil", percentDoneWithRecoil
                    );
            }
        }

        // grenade throw interval
        if (playerObjectState.TimeUntilCanThrowGrenade > 0)
        {
            playerObjectState.TimeUntilCanThrowGrenade -= Time.deltaTime;
        }

        // shield regen interval
        float shieldRegenTime;

        if (playerObjectState.TimeUntilShieldCanRegen > 0)
        {
            playerObjectState.TimeUntilShieldCanRegen -= Time.deltaTime;
            shieldRegenTime = (playerObjectState.TimeUntilShieldCanRegen <= 0)
                ? Mathf.Abs(playerObjectState.TimeUntilShieldCanRegen)
                : 0;
        }
        else
        {
            shieldRegenTime = Time.deltaTime;
        }

        var shieldRegenAmount = shieldRegenTime * OsFps.ShieldRegenPerSecond;

        playerObjectState.Shield = Mathf.Min(playerObjectState.Shield + shieldRegenAmount, OsFps.MaxPlayerShield);

        // update movement
        UpdatePlayerMovement(playerObjectState);
    }