< Summary

Class:PlayerAvatarController
Assembly:PlayerAvatarController
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.cs
Covered lines:46
Uncovered lines:83
Coverable lines:129
Total lines:336
Line coverage:35.6% (46 of 129)
Covered branches:0
Total branches:0
Covered methods:11
Total methods:22
Method coverage:50% (11 of 22)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
PlayerAvatarController()0%110100%
Start()0%3.073080%
PlayerClicked()0%6200%
GetStandardAvatar()0%110100%
GetAvatarWithHologram()0%6200%
OnBaseWereablesFail()0%6200%
ShowWearablesWarning()0%2100%
Update()0%24.436020%
SetAvatarVisibility(...)0%6200%
OnEnable()0%110100%
OnAvatarEmote(...)0%3.023087.5%
OnUserProfileOnUpdate(...)0%330100%
LoadingAvatarRoutine()0%182.881509.3%
ApplyHideAvatarModifier()0%6200%
RemoveHideAvatarModifier()0%6200%
ApplyHidePassportModifier()0%2100%
RemoveHidePassportModifier()0%2100%
OnDisable()0%110100%
OnDestroy()0%440100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PlayerAvatarController/PlayerAvatarController.cs

#LineLine coverage
 1using AvatarSystem;
 2using Cysharp.Threading.Tasks;
 3using DCL;
 4using DCL.Components;
 5using DCL.FatalErrorReporter;
 6using DCL.Interface;
 7using DCL.NotificationModel;
 8using SocialFeaturesAnalytics;
 9using System;
 10using System.Collections.Generic;
 11using System.Linq;
 12using System.Threading;
 13using UnityEngine;
 14using Environment = DCL.Environment;
 15using Type = DCL.NotificationModel.Type;
 16
 17public class PlayerAvatarController : MonoBehaviour, IHideAvatarAreaHandler, IHidePassportAreaHandler
 18{
 19    private const string LOADING_WEARABLES_ERROR_MESSAGE = "There was a problem loading your wearables";
 20    private const string IN_HIDE_AREA = "IN_HIDE_AREA";
 21    private const string INSIDE_CAMERA = "INSIDE_CAMERA";
 22    private const string OPEN_PASSPORT_SOURCE = "World";
 23
 24    private CancellationTokenSource avatarLoadingCts;
 25    public GameObject avatarContainer;
 26    public StickersController stickersControllers;
 34127    private readonly AvatarModel currentAvatar = new AvatarModel { wearables = new List<string>() };
 28
 29    public Collider avatarCollider;
 30    [SerializeField] private GameObject loadingParticlesPrefab;
 34131    public float cameraDistanceToDeactivate = 1.0f;
 32    [SerializeField] internal AvatarOnPointerDown onPointerDown;
 33    [SerializeField] internal AvatarOutlineOnHoverEvent outlineOnHover;
 34    [SerializeField] internal Transform baseAvatarContainer;
 35    [SerializeField] internal BaseAvatarReferences baseAvatarReferencesPrefab;
 36
 120837    private UserProfile userProfile => UserProfile.GetOwnUserProfile();
 038    private bool repositioningWorld => DCLCharacterController.i.characterPosition.RepositionedWorldLastFrame();
 39    private bool enableCameraCheck;
 40    private Camera mainCamera;
 41    private IFatalErrorReporter fatalErrorReporter; // TODO?
 42    private string visibilityConstrain;
 43    private BaseRefCounter<AvatarModifierAreaID> currentActiveModifiers;
 44    private Service<IEmotesCatalogService> emotesCatalog;
 45    private ISocialAnalytics socialAnalytics;
 46    private BaseVariable<(string playerId, string source)> currentPlayerInfoCardId;
 47    private IAvatar avatar;
 48    private IBaseAvatarReferences baseAvatarReferences;
 34149    private readonly OnPointerEvent.Model pointerEventModel = new ()
 50    {
 51        type = OnPointerDown.NAME,
 52        button = WebInterface.ACTION_BUTTON.POINTER.ToString(),
 53        hoverText = "View My Profile",
 54    };
 55
 056    public IAvatar Avatar => avatar;
 57
 58    private void Start()
 59    {
 30160        DataStore.i.common.isPlayerRendererLoaded.Set(false);
 61
 30162        socialAnalytics = new SocialAnalytics(
 63            Environment.i.platform.serviceProviders.analytics,
 64            new UserProfileWebInterfaceBridge());
 65
 30166        if (DataStore.i.avatarConfig.useHologramAvatar.Get())
 067            avatar = GetAvatarWithHologram();
 68        else
 30169            avatar = GetStandardAvatar();
 70
 30171        if (UserProfileController.i != null)
 72        {
 073            UserProfileController.i.OnBaseWereablesFail -= OnBaseWereablesFail;
 074            UserProfileController.i.OnBaseWereablesFail += OnBaseWereablesFail;
 75        }
 76
 30177        CommonScriptableObjects.rendererState.AddLock(this);
 78
 30179        mainCamera = Camera.main;
 30180        currentActiveModifiers = new BaseRefCounter<AvatarModifierAreaID>();
 30181        currentPlayerInfoCardId = DataStore.i.HUDs.currentPlayerId;
 82
 30183        onPointerDown.OnPointerDownReport -= PlayerClicked;
 30184        onPointerDown.OnPointerDownReport += PlayerClicked;
 30185    }
 86
 87    private void PlayerClicked()
 88    {
 089        if (currentAvatar == null) return;
 090        currentPlayerInfoCardId.Set((currentAvatar.id, OPEN_PASSPORT_SOURCE));
 091    }
 92
 93    private IAvatar GetStandardAvatar()
 94    {
 30195        return Environment.i.serviceLocator.Get<IAvatarFactory>().CreateAvatar(
 96            avatarContainer,
 97            GetComponentInChildren<AvatarAnimatorLegacy>(),
 98            NoLODs.i,
 99            new Visibility());
 100    }
 101
 102    private IAvatar GetAvatarWithHologram()
 103    {
 0104        baseAvatarReferences = baseAvatarContainer.GetComponentInChildren<IBaseAvatarReferences>() ?? Instantiate(baseAv
 105
 0106        return Environment.i.serviceLocator.Get<IAvatarFactory>().CreateAvatarWithHologram(
 107            avatarContainer,
 108            new BaseAvatar(baseAvatarReferences),
 109            GetComponentInChildren<AvatarAnimatorLegacy>(),
 110            NoLODs.i,
 111            new Visibility());
 112    }
 113
 114    private void OnBaseWereablesFail()
 115    {
 0116        UserProfileController.i.OnBaseWereablesFail -= OnBaseWereablesFail;
 117
 0118        if (enableCameraCheck)
 0119            ShowWearablesWarning();
 0120    }
 121
 122    private void ShowWearablesWarning()
 123    {
 0124        NotificationsController.i.ShowNotification(new Model
 125        {
 126            message = LOADING_WEARABLES_ERROR_MESSAGE,
 127            type = Type.GENERIC,
 128            timer = 10f,
 129            destroyOnFinish = true
 130        });
 0131    }
 132
 133    private void Update()
 134    {
 6051135        if (!enableCameraCheck || repositioningWorld)
 6051136            return;
 137
 0138        if (mainCamera == null)
 139        {
 0140            mainCamera = Camera.main;
 141
 0142            if (mainCamera == null)
 0143                return;
 144        }
 145
 0146        if (Vector3.Distance(mainCamera.transform.position, transform.position) > cameraDistanceToDeactivate)
 0147            avatar.RemoveVisibilityConstrain(INSIDE_CAMERA);
 148        else
 0149            avatar.AddVisibilityConstraint(INSIDE_CAMERA);
 0150    }
 151
 152    public void SetAvatarVisibility(bool isVisible)
 153    {
 0154        visibilityConstrain = "own_player_invisible";
 155
 0156        if (isVisible)
 0157            avatar.RemoveVisibilityConstrain(visibilityConstrain);
 158        else
 0159            avatar.AddVisibilityConstraint(visibilityConstrain);
 0160    }
 161
 162    private void OnEnable()
 163    {
 302164        userProfile.OnUpdate += OnUserProfileOnUpdate;
 302165        userProfile.OnAvatarEmoteSet += OnAvatarEmote;
 302166    }
 167
 168    private void OnAvatarEmote(string id, long timestamp, UserProfile.EmoteSource source)
 169    {
 1170        avatar.GetEmotesController().PlayEmote(id, timestamp);
 171
 1172        bool found = DataStore.i.common.wearables.TryGetValue(id, out WearableItem emoteItem);
 173
 1174        if (!found)
 175        {
 1176            var emotesCatalog = Environment.i.serviceLocator.Get<IEmotesCatalogService>();
 1177            emotesCatalog.TryGetLoadedEmote(id, out emoteItem);
 178        }
 179
 1180        if (emoteItem != null)
 181        {
 0182            socialAnalytics.SendPlayEmote(
 183                emoteItem.id,
 184                emoteItem.GetName(),
 185                emoteItem.rarity,
 186                emoteItem.data.tags.Contains(WearableLiterals.Tags.BASE_WEARABLE),
 187                source,
 188                $"{CommonScriptableObjects.playerCoords.Get().x},{CommonScriptableObjects.playerCoords.Get().y}");
 189        }
 1190    }
 191
 192    private void OnUserProfileOnUpdate(UserProfile profile)
 193    {
 1194        avatarLoadingCts?.Cancel();
 1195        avatarLoadingCts?.Dispose();
 1196        avatarLoadingCts = new CancellationTokenSource();
 1197        LoadingAvatarRoutine(profile, avatarLoadingCts.Token);
 1198    }
 199
 200    private async UniTaskVoid LoadingAvatarRoutine(UserProfile profile, CancellationToken ct)
 201    {
 1202        if (string.IsNullOrEmpty(profile.avatar.bodyShape) || profile.avatar.wearables == null)
 203        {
 1204            avatar.Dispose();
 1205            return;
 206        }
 207
 208        try
 209        {
 0210            ct.ThrowIfCancellationRequested();
 211
 0212            if (avatar.status != IAvatar.Status.Loaded || !profile.avatar.HaveSameWearablesAndColors(currentAvatar))
 213            {
 0214                currentAvatar.CopyFrom(profile.avatar);
 215                // profile.avatar.id is a null string, so override it with a valid profile id for further usage
 0216                currentAvatar.id = profile.userId;
 217
 0218                List<string> wearableItems = profile.avatar.wearables.ToList();
 0219                wearableItems.Add(profile.avatar.bodyShape);
 220
 0221                HashSet<string> emotes = new HashSet<string>(currentAvatar.emotes.Select(x => x.urn));
 0222                var embeddedEmotesSo = await emotesCatalog.Ref.GetEmbeddedEmotes();
 0223                string[] emoteIds = embeddedEmotesSo.GetAllIds();
 0224                emotes.UnionWith(emoteIds);
 0225                wearableItems.AddRange(emoteIds);
 226
 0227                await avatar.Load(wearableItems, emotes.ToList(), new AvatarSettings
 228                {
 229                    bodyshapeId = profile.avatar.bodyShape,
 230                    eyesColor = profile.avatar.eyeColor,
 231                    skinColor = profile.avatar.skinColor,
 232                    hairColor = profile.avatar.hairColor,
 233                    forceRender = new HashSet<string>(profile.avatar.forceRender)
 234                }, ct);
 235
 0236                if (avatar.lodLevel <= 1)
 0237                    AvatarSystemUtils.SpawnAvatarLoadedParticles(avatarContainer.transform, loadingParticlesPrefab);
 238
 0239                avatar.GetEmotesController().PlayEmote(profile.avatar.expressionTriggerId, profile.avatar.expressionTrig
 0240            }
 0241        }
 0242        catch (Exception e) when (e is not OperationCanceledException)
 243        {
 0244            Debug.LogException(e);
 245
 246            //WebInterface.ReportAvatarFatalError(e.ToString());
 0247            return;
 248        }
 249        finally
 250        {
 0251            IAvatarAnchorPoints anchorPoints = new AvatarAnchorPoints();
 0252            anchorPoints.Prepare(avatarContainer.transform, baseAvatarReferences.Anchors, AvatarSystemUtils.AVATAR_Y_OFF
 253
 0254            var player = new Player
 255            {
 256                id = userProfile.userId,
 257                name = userProfile.name,
 258                avatar = avatar,
 259                anchorPoints = anchorPoints,
 260                collider = avatarCollider
 261            };
 262
 0263            DataStore.i.player.ownPlayer.Set(player);
 264
 0265            enableCameraCheck = true;
 0266            avatarCollider.gameObject.SetActive(true);
 0267            CommonScriptableObjects.rendererState.RemoveLock(this);
 0268            DataStore.i.common.isPlayerRendererLoaded.Set(true);
 269
 0270            onPointerDown.Initialize(
 271                pointerEventModel,
 272                null,
 273                player
 274            );
 275
 0276            onPointerDown.ShouldBeInteractableWhenMouseIsLocked = false;
 277
 0278            outlineOnHover.Initialize(null, avatar);
 0279            outlineOnHover.ShouldBeHoveredWhenMouseIsLocked = false;
 280
 0281            bool isClickingOwnAvatarEnabled = DataStore.i.featureFlags.flags.Get().IsFeatureEnabled("click_own_avatar_pa
 0282            onPointerDown.enabled = isClickingOwnAvatarEnabled;
 0283            outlineOnHover.enabled = isClickingOwnAvatarEnabled;
 284        }
 1285    }
 286
 287    public void ApplyHideAvatarModifier()
 288    {
 0289        if (!currentActiveModifiers.ContainsKey(AvatarModifierAreaID.HIDE_AVATAR))
 290        {
 0291            avatar.AddVisibilityConstraint(IN_HIDE_AREA);
 0292            stickersControllers.ToggleHideArea(true);
 293        }
 294
 0295        currentActiveModifiers.AddRefCount(AvatarModifierAreaID.HIDE_AVATAR);
 0296        DataStore.i.HUDs.avatarAreaWarnings.AddRefCount(AvatarModifierAreaID.HIDE_AVATAR);
 0297    }
 298
 299    public void RemoveHideAvatarModifier()
 300    {
 0301        DataStore.i.HUDs.avatarAreaWarnings.RemoveRefCount(AvatarModifierAreaID.HIDE_AVATAR);
 0302        currentActiveModifiers.RemoveRefCount(AvatarModifierAreaID.HIDE_AVATAR);
 303
 0304        if (!currentActiveModifiers.ContainsKey(AvatarModifierAreaID.HIDE_AVATAR))
 305        {
 0306            avatar.RemoveVisibilityConstrain(IN_HIDE_AREA);
 0307            stickersControllers.ToggleHideArea(false);
 308        }
 0309    }
 310
 311    public void ApplyHidePassportModifier()
 312    {
 0313        DataStore.i.HUDs.avatarAreaWarnings.AddRefCount(AvatarModifierAreaID.DISABLE_PASSPORT);
 0314        currentActiveModifiers.AddRefCount(AvatarModifierAreaID.DISABLE_PASSPORT);
 0315    }
 316
 317    public void RemoveHidePassportModifier()
 318    {
 0319        DataStore.i.HUDs.avatarAreaWarnings.RemoveRefCount(AvatarModifierAreaID.DISABLE_PASSPORT);
 0320        currentActiveModifiers.RemoveRefCount(AvatarModifierAreaID.DISABLE_PASSPORT);
 0321    }
 322
 323    private void OnDisable()
 324    {
 302325        userProfile.OnUpdate -= OnUserProfileOnUpdate;
 302326        userProfile.OnAvatarEmoteSet -= OnAvatarEmote;
 302327    }
 328
 329    private void OnDestroy()
 330    {
 324331        avatarLoadingCts?.Cancel();
 324332        avatarLoadingCts?.Dispose();
 324333        avatarLoadingCts = null;
 324334        avatar?.Dispose();
 301335    }
 336}