< Summary

Class:RPC.Services.EmotesRendererServiceImpl
Assembly:RPC.Services.Emotes
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs
Covered lines:0
Uncovered lines:59
Coverable lines:59
Total lines:165
Line coverage:0% (0 of 59)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:7
Method coverage:0% (0 of 7)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EmotesRendererServiceImpl()0%2100%
RegisterService(...)0%2100%
EmotesRendererServiceImpl(...)0%2100%
OnPortClosed()0%12300%
TriggerSelfUserExpression()0%12300%
TriggerSceneExpression()0%2401500%
OnSceneRemoved(...)0%30500%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/RPC/Services/EmotesService/EmotesRendererServiceImpl.cs

#LineLine coverage
 1using AvatarAssets;
 2using AvatarSystem;
 3using Cysharp.Threading.Tasks;
 4using DCL;
 5using DCL.Controllers;
 6using DCL.Emotes;
 7using Decentraland.Renderer.RendererServices;
 8using rpc_csharp;
 9using System;
 10using System.Collections.Generic;
 11using System.Threading;
 12using UnityEngine;
 13using Environment = DCL.Environment;
 14
 15namespace RPC.Services
 16{
 17    public class EmotesRendererServiceImpl : IEmotesRendererService<RPCContext>
 18    {
 019        private static readonly SuccessResponse FAILURE_RESPONSE = new () { Success = false };
 020        private static readonly SuccessResponse SUCCESS_RESPONSE = new () { Success = true };
 21
 22        private readonly IWorldState worldState;
 23        private readonly ISceneController sceneController;
 24        private readonly UserProfile userProfile;
 25        private readonly BaseVariable<Player> ownPlayer;
 26        private readonly IEmotesService emotesService;
 27
 28        private readonly IDictionary<IParcelScene, HashSet<EmoteBodyId>> emotesByScene;
 29        private readonly IDictionary<IParcelScene, CancellationTokenSource> cancellationTokenSources;
 30
 31        private IAvatarEmotesController emotesController;
 32
 33        public static void RegisterService(RpcServerPort<RPCContext> port)
 34        {
 035            EmotesRendererServiceCodeGen.RegisterService(
 36                port,
 37                new EmotesRendererServiceImpl(
 38                    port: port,
 39                    worldState: Environment.i.world.state,
 40                    sceneController: Environment.i.world.sceneController,
 41                    userProfile: UserProfile.GetOwnUserProfile(),
 42                    ownPlayer: DataStore.i.player.ownPlayer,
 43                    emotesService: Environment.i.serviceLocator.Get<IEmotesService>(),
 44                    emotesByScene: new Dictionary<IParcelScene, HashSet<EmoteBodyId>>(),
 45                    cancellationTokenSources: new Dictionary<IParcelScene, CancellationTokenSource>()
 46                ));
 047        }
 48
 049        public EmotesRendererServiceImpl(
 50            RpcServerPort<RPCContext> port,
 51            IWorldState worldState,
 52            ISceneController sceneController,
 53            UserProfile userProfile,
 54            BaseVariable<Player> ownPlayer,
 55            IEmotesService emotesService,
 56            IDictionary<IParcelScene, HashSet<EmoteBodyId>> emotesByScene,
 57            IDictionary<IParcelScene, CancellationTokenSource> cancellationTokenSources
 58        )
 59        {
 060            this.worldState = worldState;
 061            this.sceneController = sceneController;
 062            this.userProfile = userProfile;
 063            this.ownPlayer = ownPlayer;
 064            this.emotesService = emotesService;
 065            this.emotesByScene = emotesByScene;
 066            this.cancellationTokenSources = cancellationTokenSources;
 67
 068            port.OnClose += OnPortClosed;
 069        }
 70
 71        private void OnPortClosed()
 72        {
 073            foreach (var scenes in worldState.GetLoadedScenes())
 74            {
 075                OnSceneRemoved(scenes.Value);
 76            }
 077        }
 78
 79        public async UniTask<TriggerSelfUserExpressionResponse> TriggerSelfUserExpression(TriggerSelfUserExpressionReque
 80        {
 081            await UniTask.SwitchToMainThread(ct);
 082            userProfile.SetAvatarExpression(request.Id, UserProfile.EmoteSource.Command);
 083            return default;
 084        }
 85
 86        public async UniTask<SuccessResponse> TriggerSceneExpression(TriggerSceneExpressionRequest request, RPCContext c
 87        {
 88            // try get loaded scene
 089            if (!worldState.TryGetScene(request.SceneNumber, out IParcelScene scene))
 090                return FAILURE_RESPONSE;
 91
 92            // generates an emote id
 093            if (!SceneEmoteHelper.TryGenerateEmoteId(scene, request.Path, request.Loop, out string emoteId))
 094                return FAILURE_RESPONSE;
 95
 096            emotesController ??= ownPlayer.Get()?.avatar.GetEmotesController();
 97
 098            if (emotesController == null)
 099                return FAILURE_RESPONSE;
 100
 0101            string userBodyShape = userProfile.avatar.bodyShape;
 102
 103            // get hashset for scene emotes that are already equipped
 0104            if (!emotesByScene.TryGetValue(scene, out HashSet<EmoteBodyId> sceneEquippedEmotes))
 105            {
 0106                sceneEquippedEmotes = new HashSet<EmoteBodyId>();
 0107                emotesByScene.Add(scene, sceneEquippedEmotes);
 108            }
 109
 110            // get / create cancellation source for scene
 0111            if (!cancellationTokenSources.TryGetValue(scene, out var cancellationTokenSource))
 112            {
 0113                cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(ct);
 0114                cancellationTokenSources.Add(scene, cancellationTokenSource);
 115            }
 116
 0117            sceneController.OnSceneRemoved -= OnSceneRemoved;
 0118            sceneController.OnSceneRemoved += OnSceneRemoved;
 119
 120            try
 121            {
 0122                await UniTask.SwitchToMainThread(ct);
 123
 0124                var emoteKey = new EmoteBodyId(userBodyShape, emoteId);
 125
 0126                if (!emotesByScene[scene].Contains(emoteKey))
 127                {
 0128                    var result = await emotesService.RequestEmote(emoteKey, cancellationTokenSource.Token, scene.content
 0129                    emotesController.EquipEmote(emoteId, result);
 0130                    emotesByScene[scene].Add(emoteKey);
 131                }
 132
 0133                userProfile.SetAvatarExpression(emoteId, UserProfile.EmoteSource.Command);
 134
 0135                return SUCCESS_RESPONSE;
 136            }
 0137            catch (OperationCanceledException _)
 138            {
 0139                return FAILURE_RESPONSE;
 140            }
 141            catch (Exception e)
 142            {
 0143                Debug.LogException(e);
 0144                return FAILURE_RESPONSE;
 145            }
 0146        }
 147
 148        private void OnSceneRemoved(IParcelScene scene)
 149        {
 0150            if (cancellationTokenSources.TryGetValue(scene, out var cancellationTokenSource))
 151            {
 0152                cancellationTokenSource.Cancel();
 0153                cancellationTokenSource.Dispose();
 0154                cancellationTokenSources.Remove(scene);
 155            }
 156
 0157            if (!emotesByScene.TryGetValue(scene, out var equippedEmotes)) return;
 158
 0159            foreach (var emoteData in equippedEmotes)
 0160                emotesController?.UnEquipEmote(emoteData.EmoteId);
 161
 0162            emotesByScene.Remove(scene);
 0163        }
 164    }
 165}