< Summary

Class:DCL.Controllers.WorldBlockersController
Assembly:WorldBlockersController
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/BlockerController/WorldBlockersController.cs
Covered lines:87
Uncovered lines:9
Coverable lines:96
Total lines:230
Line coverage:90.6% (87 of 96)
Covered branches:0
Total branches:0
Covered methods:13
Total methods:14
Method coverage:92.8% (13 of 14)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WorldBlockersController(...)0%110100%
WorldBlockersController()0%110100%
OnRendererStateChange(...)0%3.143075%
SetupWorldBlockers()0%4.074083.33%
SetEnabled(...)0%3.043083.33%
OnWorldReposition(...)0%110100%
Dispose()0%4.024088.89%
Initialize()0%330100%
SetupWorldBlockers(...)0%99096.77%
LookForLimits(...)0%8.078089.47%
OnWorldsBlockerEnabledChange(...)0%2100%
IsSceneKnown(...)0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/BlockerController/WorldBlockersController.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using DCL.Helpers;
 3using System;
 4using UnityEngine;
 5using Object = UnityEngine.Object;
 6
 7namespace DCL.Controllers
 8{
 9    /// <summary>
 10    /// This class is the domain-specific glue for BlockerInstanceHandler.
 11    /// <br/><br/>
 12    /// Responsibilities:<br/>
 13    /// - Spawning blockers depending on scene state<br/>
 14    /// - Moving blockers when the world is repositioned<br/>
 15    /// - Handling lifecycle of BlockerInstanceHandler<br/>
 16    /// </summary>
 17    public class WorldBlockersController : IWorldBlockersController
 18    {
 42919        public bool enabled = true;
 20
 21        Transform blockersParent;
 22
 23        ISceneHandler sceneHandler;
 24        IBlockerInstanceHandler blockerInstanceHandler;
 25
 42926        HashSet<Vector2Int> blockersToRemove = new HashSet<Vector2Int>();
 42927        HashSet<Vector2Int> blockersToAdd = new HashSet<Vector2Int>();
 28
 129        static Vector2Int[] aroundOffsets =
 30        {
 31            new Vector2Int(1, 0),
 32            new Vector2Int(-1, 0),
 33            new Vector2Int(0, 1),
 34            new Vector2Int(0, -1),
 35            new Vector2Int(1, 1),
 36            new Vector2Int(-1, -1),
 37            new Vector2Int(1, -1),
 38            new Vector2Int(-1, 1)
 39        };
 40
 1341        private BaseVariable<int> worldBlockersLimit => DataStore.i.worldBlockers.worldBlockerLimit;
 85942        private BaseVariable<bool> worldBlockersEnabled => DataStore.i.worldBlockers.worldBlockerEnabled;
 43
 44        void OnRendererStateChange(bool newValue, bool oldValue)
 45        {
 54046            blockerInstanceHandler.SetCollision(newValue);
 47
 54048            if (newValue && DataStore.i.debugConfig.isDebugMode.Get())
 049                SetEnabled(false);
 54050        }
 51
 42952        public WorldBlockersController(IBlockerInstanceHandler blockerInstanceHandler = null,
 53            ISceneHandler sceneHandler = null)
 54        {
 42955            this.sceneHandler = sceneHandler;
 42956            this.blockerInstanceHandler = blockerInstanceHandler;
 42957            worldBlockersEnabled.OnChange += OnWorldsBlockerEnabledChange;
 42958        }
 59
 60        public void SetupWorldBlockers()
 61        {
 62#if UNITY_STANDALONE || UNITY_EDITOR
 50063            if (DataStore.i.common.isApplicationQuitting.Get())
 064                return;
 65#endif
 66
 50067            if (!enabled || sceneHandler == null)
 168                return;
 69
 49970            SetupWorldBlockers(sceneHandler.GetAllLoadedScenesCoords());
 49971        }
 72
 73        public void SetEnabled(bool targetValue)
 74        {
 75#if UNITY_STANDALONE || UNITY_EDITOR
 276            if (DataStore.i.common.isApplicationQuitting.Get())
 077                return;
 78#endif
 79
 280            enabled = targetValue;
 81
 282            if (!enabled)
 183                blockerInstanceHandler.DestroyAllBlockers();
 284        }
 85
 86        void OnWorldReposition(Vector3 current, Vector3 previous)
 87        {
 288            var newPosition = PositionUtils.WorldToUnityPosition(Vector3.zero); // Blockers parent original position
 289            blockersParent.position = newPosition;
 290        }
 91
 92        public void Dispose()
 93        {
 94#if UNITY_STANDALONE || UNITY_EDITOR
 43095            if (DataStore.i.common.isApplicationQuitting.Get())
 096                return;
 97#endif
 98
 43099            CommonScriptableObjects.worldOffset.OnChange -= OnWorldReposition;
 430100            worldBlockersEnabled.OnChange -= OnWorldsBlockerEnabledChange;
 430101            blockerInstanceHandler?.DestroyAllBlockers();
 102
 430103            if (blockersParent != null)
 425104                Object.Destroy(blockersParent.gameObject);
 105
 430106            enabled = false;
 430107        }
 108
 109        public void Initialize()
 110        {
 425111            enabled = true;
 425112            blockersParent = new GameObject("WorldBlockers").transform;
 425113            blockersParent.position = Vector3.zero;
 114
 425115            if (blockerInstanceHandler == null)
 116            {
 425117                var blockerAnimationHandler = new BlockerAnimationHandler();
 425118                blockerInstanceHandler = new BlockerInstanceHandler(blockerAnimationHandler);
 119            }
 120
 425121            if (this.sceneHandler == null)
 425122                this.sceneHandler = DCL.Environment.i.world.state;
 123
 425124            blockerInstanceHandler.SetParent(blockersParent);
 125
 425126            CommonScriptableObjects.worldOffset.OnChange -= OnWorldReposition;
 425127            CommonScriptableObjects.worldOffset.OnChange += OnWorldReposition;
 128
 425129            CommonScriptableObjects.rendererState.OnChange -= OnRendererStateChange;
 425130            CommonScriptableObjects.rendererState.OnChange += OnRendererStateChange;
 425131        }
 132
 133        internal void SetupWorldBlockers(HashSet<Vector2Int> allLoadedParcelCoords)
 134        {
 499135            if (allLoadedParcelCoords.Count == 0)
 486136                return;
 137
 13138            blockersToRemove.Clear();
 13139            blockersToAdd.Clear();
 140
 13141            var blockers = blockerInstanceHandler.GetBlockers();
 142
 143            // Detect blockers to be removed
 50144            foreach (var item in blockers)
 145            {
 12146                if (allLoadedParcelCoords.Contains(item.Key))
 147                {
 2148                    blockersToRemove.Add(item.Key);
 149                }
 150                else
 151                {
 10152                    bool foundAroundLoadedScenes = false;
 70153                    for (int i = 0; i < aroundOffsets.Length; i++)
 154                    {
 35155                        Vector2Int offset = aroundOffsets[i];
 35156                        Vector2Int checkedPosition = new Vector2Int(item.Key.x + offset.x, item.Key.y + offset.y);
 157
 35158                        if (allLoadedParcelCoords.Contains(checkedPosition))
 159                        {
 10160                            foundAroundLoadedScenes = true;
 10161                            break;
 162                        }
 163                    }
 164
 10165                    if (!foundAroundLoadedScenes)
 0166                        blockersToRemove.Add(item.Key);
 167                }
 168            }
 169
 13170            blockersToAdd = LookForLimits(dontAddABlockerHere: allLoadedParcelCoords, blockers, 0);
 171
 172            // Remove extra blockers
 30173            foreach (var coords in blockersToRemove)
 2174                blockerInstanceHandler.HideBlocker(coords, false);
 175
 176            // Add missing blockers
 134177            foreach (var coords in blockersToAdd)
 54178                blockerInstanceHandler.ShowBlocker(coords, false, CommonScriptableObjects.rendererState.Get());
 13179        }
 180
 181        private HashSet<Vector2Int> LookForLimits(HashSet<Vector2Int> dontAddABlockerHere, Dictionary<Vector2Int, IPoola
 182        {
 13183            HashSet<Vector2Int> blockersCandidate = new HashSet<Vector2Int>();
 184
 185            // Detect missing blockers to be added
 13186            using (var it = dontAddABlockerHere.GetEnumerator())
 187            {
 39188                while (it.MoveNext())
 189                {
 26190                    Vector2Int pos = it.Current;
 191
 468192                    for (int i = 0; i < aroundOffsets.Length; i++)
 193                    {
 208194                        Vector2Int offset = aroundOffsets[i];
 208195                        int xCandidate = pos.x + offset.x;
 208196                        int yCandidate = pos.y + offset.y;
 208197                        Vector2Int checkedPosition = new Vector2Int(xCandidate, yCandidate);
 198
 208199                        if (!dontAddABlockerHere.Contains(checkedPosition) && !blockers.ContainsKey(checkedPosition))
 200                        {
 201                            // We add a blocker here because it is either part of a World, or because it contains a scen
 144202                            if (DataStore.i.common.isWorld.Get() || IsSceneKnown (checkedPosition))
 80203                                blockersCandidate.Add(checkedPosition);
 204                        }
 205                    }
 206                }
 13207            }
 208
 13209            if (currentLimitIterationEvaluation == worldBlockersLimit.Get())
 13210                return blockersCandidate;
 211            else
 212            {
 0213                blockersCandidate.UnionWith(dontAddABlockerHere);
 0214                return LookForLimits(blockersCandidate, blockers, currentLimitIterationEvaluation + 1);
 215            }
 216        }
 217
 218        private void OnWorldsBlockerEnabledChange(bool newState, bool _)
 219        {
 0220            SetEnabled(newState);
 0221        }
 222
 223        private bool IsSceneKnown(Vector2Int parcel)
 224        {
 225            // Note: This returns false when the set of coordinates is about a parcel
 226            // where the kernel didn't provide yet any information to the renderer
 144227            return sceneHandler.GetScene(parcel) != null;
 228        }
 229    }
 230}