< Summary

Class:DCL.Controllers.ParcelScene
Assembly:DCL.Runtime
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/ParcelScene.cs
Covered lines:237
Uncovered lines:61
Coverable lines:298
Total lines:687
Line coverage:79.5% (237 of 298)
Covered branches:0
Total branches:0
Covered methods:57
Total methods:66
Method coverage:86.3% (57 of 66)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ParcelScene()0%110100%
Awake()0%110100%
OnDestroy()0%220100%
OnDisable()0%220100%
Update()0%330100%
SetData()0%220100%
SetupPositionAndParcels()0%220100%
OnWorldReposition(...)0%110100%
SetUpdateData(...)0%2100%
InitializeDebugPlane()0%440100%
RemoveDebugPlane()0%6200%
Cleanup(...)0%6.016094.44%
ToString()0%12300%
GetSceneName()0%6200%
GetParcels()0%110100%
IsInsideSceneBoundaries(...)0%4.054085.71%
IsInsideSceneBoundaries(...)0%4.254075%
IsInsideSceneBoundaries(...)0%9.599080.65%
IsInsideSceneOuterBoundaries(...)0%3.043083.33%
IsInsideSceneOuterBoundaries(...)0%2.062075%
OnDrawGizmosSelected()0%12300%
GetEntityById(...)0%2100%
GetSceneTransform()0%110100%
CreateEntity(...)0%44095%
OnEntityShapeUpdated(...)0%110100%
RemoveEntity(...)0%4.024090%
CleanUpEntityRecursively(...)0%550100%
RemoveAllEntities(...)0%770100%
RemoveAllEntitiesImmediate()0%110100%
SetEntityParent(...)0%15.8215084.62%
SendMetricsEvent()0%220100%
GetEntityById(...)0%64050%
GetStateString()0%12.3310071.43%
RefreshLoadingState()0%2.032080%
GetWaitingComponentsDebugInfo()0%6200%
GetSceneDebugInfo()0%2100%
CalculateSceneLoadingState()0%4.134080%
IsInitMessageDone()0%220100%
SetContentCategory(...)0%110100%
SetAssociatedPlace(...)0%110100%

File(s)

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

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Configuration;
 3using DCL.Helpers;
 4using DCL.Models;
 5using DCL.Controllers.ParcelSceneDebug;
 6using System.Collections.Generic;
 7using DCL.Interface;
 8using MainScripts.DCL.Controllers.AssetManager.AssetBundles.SceneAB;
 9using System;
 10using System.Linq;
 11using UnityEngine;
 12using UnityEngine.Assertions;
 13
 14namespace DCL.Controllers
 15{
 16    public class ParcelScene : MonoBehaviour, IParcelScene
 17    {
 18        private const string NEW_CDN_FF = "ab-new-cdn";
 19
 20        [Header("Debug")]
 21        [SerializeField]
 43322        private bool renderOuterBoundsGizmo = true;
 23
 378224        public Dictionary<long, IDCLEntity> entities { get; private set; } = new Dictionary<long, IDCLEntity>();
 609525        public IECSComponentsManagerLegacy componentsManagerLegacy { get; private set; }
 1048826        public LoadParcelScenesMessage.UnityParcelScene sceneData { get; protected set; }
 43327        public HashSet<Vector2Int> parcels = new HashSet<Vector2Int>();
 370228        public ISceneMetricsCounter metricsCounter { get; set; }
 29        public event System.Action<IDCLEntity> OnEntityAdded;
 30        public event System.Action<IDCLEntity> OnEntityRemoved;
 31        public event System.Action<LoadParcelScenesMessage.UnityParcelScene> OnSetData;
 32        public event System.Action<float> OnLoadingStateUpdated;
 33
 102634        public ContentProvider contentProvider { get; set; }
 35
 81836        public bool isTestScene { get; set; } = false;
 384237        public bool isPersistent { get; set; } = false;
 60038        public bool isPortableExperience { get; set; } = false;
 39
 121440        public float loadingProgress { get; private set; }
 62141        public SceneContentCategory contentCategory { get; private set; }
 9342        public string associatedPlaceId { get; private set; }
 43
 44        [System.NonSerialized]
 45        public string sceneName;
 46
 47        [System.NonSerialized]
 43348        public bool unloadWithDistance = true;
 49
 50        SceneDebugPlane sceneDebugPlane = null;
 51
 52        public SceneLifecycleHandler sceneLifecycleHandler;
 53
 58854        public bool isReleased { get; private set; }
 55
 56        private Bounds outerBounds = new Bounds();
 57
 058        private FeatureFlag featureFlags => DataStore.i.featureFlags.flags.Get();
 59
 60        public void Awake()
 61        {
 43362            CommonScriptableObjects.worldOffset.OnChange += OnWorldReposition;
 43363            componentsManagerLegacy = new ECSComponentsManagerLegacy(this);
 43364            sceneLifecycleHandler = new SceneLifecycleHandler(this);
 43365            metricsCounter = new SceneMetricsCounter(DataStore.i.sceneWorldObjects);
 43366        }
 67
 68        private void OnDestroy()
 69        {
 43370            CommonScriptableObjects.worldOffset.OnChange -= OnWorldReposition;
 43371            metricsCounter?.Dispose();
 43372        }
 73
 74        void OnDisable()
 75        {
 43376            metricsCounter?.Disable();
 43377        }
 78
 79        private void Update()
 80        {
 1356381            if (sceneLifecycleHandler.state == SceneLifecycleHandler.State.READY
 82                && CommonScriptableObjects.rendererState.Get())
 1308283                SendMetricsEvent();
 1356384        }
 85
 82086        protected virtual string prettyName => sceneData.basePosition.ToString();
 87
 88        public virtual async UniTask SetData(LoadParcelScenesMessage.UnityParcelScene data)
 89        {
 42690            Assert.IsTrue(data.sceneNumber > 0, "Scene must have a valid scene number!");
 91
 42692            this.sceneData = data;
 93
 42694            contentProvider = new ContentProvider
 95            {
 96                baseUrl = data.baseUrl,
 97                contents = data.contents,
 98                sceneCid = data.id,
 99                baseUrlBundles = data.baseUrlBundles,
 100            };
 101
 426102            contentProvider.BakeHashes();
 103
 426104            SetupPositionAndParcels();
 105
 426106            DataStore.i.sceneWorldObjects.AddScene(sceneData.sceneNumber);
 107
 426108            metricsCounter.Configure(sceneData.sceneNumber, sceneData.basePosition, sceneData.parcels.Length);
 426109            metricsCounter.Enable();
 110
 426111            OnSetData?.Invoke(data);
 426112        }
 113
 114        void SetupPositionAndParcels()
 115        {
 426116            gameObject.transform.position = PositionUtils.WorldToUnityPosition(Utils.GridToWorldPosition(sceneData.baseP
 117
 426118            parcels.Clear();
 119
 120            // The scene's gameobject position should already be in 'unityposition'
 426121            Vector3 baseParcelWorldPos = gameObject.transform.position;
 122
 426123            outerBounds.SetMinMax(new Vector3(baseParcelWorldPos.x, 0f, baseParcelWorldPos.z),
 124                new Vector3(baseParcelWorldPos.x + ParcelSettings.PARCEL_SIZE, 0f, baseParcelWorldPos.z + ParcelSettings
 125
 1728126            for (int i = 0; i < sceneData.parcels.Length; i++)
 127            {
 128                // 1. Update outer bounds with parcel's size
 438129                var parcel = sceneData.parcels[i];
 130
 438131                Vector3 parcelWorldPos = PositionUtils.WorldToUnityPosition(Utils.GridToWorldPosition(parcel.x, parcel.y
 438132                outerBounds.Encapsulate(new Vector3(parcelWorldPos.x, 0, parcelWorldPos.z));
 438133                outerBounds.Encapsulate(new Vector3(parcelWorldPos.x + ParcelSettings.PARCEL_SIZE, 0, parcelWorldPos.z +
 134
 135                // 2. add parcel to collection
 438136                parcels.Add(parcel);
 137            }
 138
 139            // Apply outer bounds extra threshold
 426140            outerBounds.SetMinMax(new Vector3(outerBounds.min.x - ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD, 0f, outerB
 141                new Vector3(outerBounds.max.x + ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD, 0f, outerBounds.max.z + Parc
 426142        }
 143
 144        void OnWorldReposition(Vector3 current, Vector3 previous)
 145        {
 2146            Vector3 currentSceneWorldPos = Utils.GridToWorldPosition(sceneData.basePosition.x, sceneData.basePosition.y)
 2147            Vector3 oldSceneUnityPos = gameObject.transform.position;
 2148            Vector3 newSceneUnityPos = PositionUtils.WorldToUnityPosition(currentSceneWorldPos);
 149
 2150            gameObject.transform.position = newSceneUnityPos;
 2151            outerBounds.center += newSceneUnityPos - oldSceneUnityPos;
 2152        }
 153
 154        public virtual void SetUpdateData(LoadParcelScenesMessage.UnityParcelScene data)
 155        {
 0156            contentProvider = new ContentProvider();
 0157            contentProvider.baseUrl = data.baseUrl;
 0158            contentProvider.contents = data.contents;
 0159            contentProvider.BakeHashes();
 0160        }
 161
 162        public void InitializeDebugPlane()
 163        {
 498164            if (EnvironmentSettings.DEBUG && sceneData.parcels != null && sceneDebugPlane == null) { sceneDebugPlane = n
 249165        }
 166
 167        public void RemoveDebugPlane()
 168        {
 0169            if (sceneDebugPlane != null)
 170            {
 0171                sceneDebugPlane.Dispose();
 0172                sceneDebugPlane = null;
 173            }
 0174        }
 175
 176        public void Cleanup(bool immediate)
 177        {
 293178            if (isReleased || gameObject == null)
 0179                return;
 180
 293181            if (sceneDebugPlane != null)
 182            {
 249183                sceneDebugPlane.Dispose();
 249184                sceneDebugPlane = null;
 185            }
 186
 293187            componentsManagerLegacy.DisposeAllSceneComponents();
 188
 293189            if (immediate) //!CommonScriptableObjects.rendererState.Get())
 190            {
 273191                RemoveAllEntitiesImmediate();
 273192                PoolManager.i.Cleanup(true, true);
 273193                DataStore.i.sceneWorldObjects.RemoveScene(sceneData.sceneNumber);
 194            }
 195            else
 196            {
 20197                if (entities.Count > 0)
 198                {
 3199                    this.gameObject.transform.position = EnvironmentSettings.MORDOR;
 3200                    this.gameObject.SetActive(false);
 201
 3202                    RemoveAllEntities();
 203                }
 204                else
 205                {
 17206                    Destroy(this.gameObject);
 17207                    DataStore.i.sceneWorldObjects.RemoveScene(sceneData.sceneNumber);
 208                }
 209            }
 210
 293211            isReleased = true;
 293212        }
 213
 214        public override string ToString()
 215        {
 0216            return "Parcel Scene: " + base.ToString() + "\n" + sceneData;
 217        }
 218
 219        public string GetSceneName()
 220        {
 0221            return string.IsNullOrEmpty(sceneName) ? "Unnamed" : sceneName;
 222        }
 223
 224        public HashSet<Vector2Int> GetParcels() =>
 696225            parcels;
 226
 227        public bool IsInsideSceneBoundaries(Bounds objectBounds)
 228        {
 103229            if (isPersistent)
 0230                return true;
 231
 103232            if (!IsInsideSceneBoundaries(objectBounds.min + CommonScriptableObjects.worldOffset, objectBounds.max.y))
 56233                return false;
 234
 47235            if (!IsInsideSceneBoundaries(objectBounds.max + CommonScriptableObjects.worldOffset, objectBounds.max.y))
 6236                return false;
 237
 41238            return true;
 239        }
 240
 241        public virtual bool IsInsideSceneBoundaries(Vector2Int gridPosition, float height = 0f)
 242        {
 138243            if (isPersistent)
 110244                return true;
 245
 28246            if (parcels.Count == 0)
 0247                return false;
 248
 28249            float heightLimit = metricsCounter.maxCount.sceneHeight;
 250
 28251            if (height > heightLimit)
 0252                return false;
 253
 28254            return parcels.Contains(gridPosition);
 255        }
 256
 257        public virtual bool IsInsideSceneBoundaries(Vector3 worldPosition, float height = 0f)
 258        {
 156259            if (isPersistent)
 0260                return true;
 261
 156262            if (parcels.Count == 0)
 0263                return false;
 264
 156265            float heightLimit = metricsCounter.maxCount.sceneHeight;
 266
 156267            if (height > heightLimit)
 8268                return false;
 269
 148270            int noThresholdZCoordinate = Mathf.FloorToInt(worldPosition.z / ParcelSettings.PARCEL_SIZE);
 148271            int noThresholdXCoordinate = Mathf.FloorToInt(worldPosition.x / ParcelSettings.PARCEL_SIZE);
 272
 273            // We check the target world position
 148274            Vector2Int targetCoordinate = new Vector2Int(noThresholdXCoordinate, noThresholdZCoordinate);
 275
 148276            if (parcels.Contains(targetCoordinate))
 92277                return true;
 278
 279            // We need to check using a threshold from the target point, in order to cover correctly the parcel "border/
 56280            Vector2Int coordinateMin = new Vector2Int();
 56281            coordinateMin.x = Mathf.FloorToInt((worldPosition.x - ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 56282            coordinateMin.y = Mathf.FloorToInt((worldPosition.z - ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 283
 56284            Vector2Int coordinateMax = new Vector2Int();
 56285            coordinateMax.x = Mathf.FloorToInt((worldPosition.x + ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 56286            coordinateMax.y = Mathf.FloorToInt((worldPosition.z + ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 287
 288            // We check the east/north-threshold position
 56289            targetCoordinate.Set(coordinateMax.x, coordinateMax.y);
 290
 56291            if (parcels.Contains(targetCoordinate))
 0292                return true;
 293
 294            // We check the east/south-threshold position
 56295            targetCoordinate.Set(coordinateMax.x, coordinateMin.y);
 296
 56297            if (parcels.Contains(targetCoordinate))
 0298                return true;
 299
 300            // We check the west/north-threshold position
 56301            targetCoordinate.Set(coordinateMin.x, coordinateMax.y);
 302
 56303            if (parcels.Contains(targetCoordinate))
 0304                return true;
 305
 306            // We check the west/south-threshold position
 56307            targetCoordinate.Set(coordinateMin.x, coordinateMin.y);
 308
 56309            if (parcels.Contains(targetCoordinate))
 0310                return true;
 311
 56312            return false;
 313        }
 314
 315        public bool IsInsideSceneOuterBoundaries(Bounds objectBounds)
 316        {
 199317            if (isPersistent)
 0318                return true;
 319
 199320            Vector3 objectBoundsMin = new Vector3(objectBounds.min.x, 0f, objectBounds.min.z);
 199321            Vector3 objectBoundsMax = new Vector3(objectBounds.max.x, 0f, objectBounds.max.z);
 199322            bool isInsideOuterBoundaries = outerBounds.Contains(objectBoundsMin) && outerBounds.Contains(objectBoundsMax
 323
 80324            return isInsideOuterBoundaries;
 325        }
 326
 327        public bool IsInsideSceneOuterBoundaries(Vector3 objectUnityPosition)
 328        {
 63329            if (isPersistent)
 0330                return true;
 331
 63332            objectUnityPosition.y = 0f;
 63333            return outerBounds.Contains(objectUnityPosition);
 334        }
 335
 336        private void OnDrawGizmosSelected()
 337        {
 0338            if (!renderOuterBoundsGizmo) return;
 339
 0340            Gizmos.color = new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, 0.5f);
 0341            Gizmos.DrawCube(outerBounds.center, outerBounds.size + Vector3.up);
 342
 0343            Gizmos.color = new Color(Color.green.r, Color.green.g, Color.green.b, 0.5f);
 0344            Bounds parcelBounds = new Bounds();
 345
 0346            foreach (Vector2Int parcel in parcels)
 347            {
 0348                Vector3 parcelSceneUnityPos = PositionUtils.WorldToUnityPosition(Utils.GridToWorldPosition(parcel.x, par
 0349                parcelBounds.center = parcelSceneUnityPos + new Vector3(8f, 0f, 8f);
 0350                parcelBounds.size = new Vector3(16f, 0.1f, 16f);
 0351                Gizmos.DrawCube(parcelBounds.center, parcelBounds.size);
 352            }
 0353        }
 354
 355        public IDCLEntity GetEntityById(string entityId)
 356        {
 0357            throw new System.NotImplementedException();
 358        }
 359
 360        public Transform GetSceneTransform()
 361        {
 51362            return transform;
 363        }
 364
 365        public IDCLEntity CreateEntity(long id)
 366        {
 303367            if (entities.ContainsKey(id)) { return entities[id]; }
 368
 303369            var newEntity = new DecentralandEntity();
 303370            newEntity.entityId = id;
 371
 303372            PoolManagerFactory.EnsureEntityPool(false);
 373
 374            // As we know that the pool already exists, we just get one gameobject from it
 303375            PoolableObject po = PoolManager.i.Get(PoolManagerFactory.EMPTY_GO_POOL_NAME);
 376
 303377            newEntity.meshesInfo.innerGameObject = po.gameObject;
 303378            newEntity.gameObject = po.gameObject;
 379
 380#if UNITY_EDITOR
 303381            newEntity.gameObject.name = "ENTITY_" + id;
 382#endif
 303383            newEntity.gameObject.transform.SetParent(gameObject.transform, false);
 303384            newEntity.gameObject.SetActive(true);
 303385            newEntity.scene = this;
 386
 303387            newEntity.OnCleanupEvent += po.OnCleanup;
 388
 303389            if (Environment.i.world.sceneBoundsChecker.enabled)
 154390                newEntity.OnShapeUpdated += OnEntityShapeUpdated;
 391
 303392            entities.Add(id, newEntity);
 393
 303394            DataStore.i.sceneWorldObjects.sceneData[sceneData.sceneNumber].owners.Add(id);
 395
 303396            OnEntityAdded?.Invoke(newEntity);
 397
 303398            Environment.i.world.sceneBoundsChecker.AddEntityToBeChecked(newEntity, runPreliminaryEvaluation: true);
 399
 303400            return newEntity;
 401        }
 402
 403        void OnEntityShapeUpdated(IDCLEntity entity)
 404        {
 200405            Environment.i.world.sceneBoundsChecker.AddEntityToBeChecked(entity, runPreliminaryEvaluation: true);
 200406        }
 407
 408        public void RemoveEntity(long id, bool removeImmediatelyFromEntitiesList = true)
 409        {
 231410            if (entities.ContainsKey(id))
 411            {
 231412                IDCLEntity entity = entities[id];
 413
 231414                if (!entity.markedForCleanup)
 415                {
 416                    // This will also cleanup its children
 231417                    CleanUpEntityRecursively(entity, removeImmediatelyFromEntitiesList);
 418                }
 419
 231420                entities.Remove(id);
 421
 231422                var data = DataStore.i.sceneWorldObjects.sceneData;
 423
 289424                if (data.ContainsKey(sceneData.sceneNumber)) { data[sceneData.sceneNumber].owners.Remove(id); }
 425            }
 426#if UNITY_EDITOR || DEVELOPMENT_BUILD
 427            else
 428            {
 0429                Debug.LogWarning($"Couldn't remove entity with ID: {id} as it doesn't exist.");
 430            }
 431#endif
 173432        }
 433
 434        void CleanUpEntityRecursively(IDCLEntity entity, bool removeImmediatelyFromEntitiesList)
 435        {
 238436            using (var iterator = entity.children.GetEnumerator())
 437            {
 252438                while (iterator.MoveNext()) { CleanUpEntityRecursively(iterator.Current.Value, removeImmediatelyFromEnti
 238439            }
 440
 238441            OnEntityRemoved?.Invoke(entity);
 442
 238443            if (Environment.i.world.sceneBoundsChecker.enabled)
 444            {
 154445                entity.OnShapeUpdated -= OnEntityShapeUpdated;
 154446                Environment.i.world.sceneBoundsChecker.RemoveEntity(entity, removeIfPersistent: true, resetState: true);
 447            }
 448
 238449            if (removeImmediatelyFromEntitiesList)
 450            {
 451                // Every entity ends up being removed through here
 234452                entity.Cleanup();
 234453                entities.Remove(entity.entityId);
 454            }
 4455            else { Environment.i.platform.parcelScenesCleaner.MarkForCleanup(entity); }
 4456        }
 457
 458        void RemoveAllEntities(bool instant = false)
 459        {
 460            //NOTE(Brian): We need to remove only the rootEntities.
 461            //             If we don't, duplicated entities will get removed when destroying
 462            //             recursively, making this more complicated than it should.
 276463            List<IDCLEntity> rootEntities = new List<IDCLEntity>();
 464
 276465            using (var iterator = entities.GetEnumerator())
 466            {
 501467                while (iterator.MoveNext())
 468                {
 225469                    if (iterator.Current.Value.parent == null)
 470                    {
 219471                        if (instant)
 215472                            rootEntities.Add(iterator.Current.Value);
 473                        else
 4474                            Environment.i.platform.parcelScenesCleaner.MarkRootEntityForCleanup(this, iterator.Current.V
 475                    }
 476                }
 276477            }
 478
 276479            if (instant)
 480            {
 273481                int rootEntitiesCount = rootEntities.Count;
 482
 976483                for (int i = 0; i < rootEntitiesCount; i++)
 484                {
 215485                    IDCLEntity entity = rootEntities[i];
 215486                    RemoveEntity(entity.entityId, instant);
 487                }
 488
 273489                entities.Clear();
 490
 491                // TODO: Does it make sense that 'RemoveAllEntities()' destroys the whole scene GameObject?
 273492                if (gameObject != null)
 273493                    Destroy(gameObject);
 494            }
 276495        }
 496
 497        private void RemoveAllEntitiesImmediate()
 498        {
 273499            RemoveAllEntities(instant: true);
 273500        }
 501
 502        public void SetEntityParent(long entityId, long parentId)
 503        {
 15504            if (entityId == parentId) { return; }
 505
 15506            IDCLEntity me = GetEntityById(entityId);
 507
 15508            if (me == null)
 0509                return;
 510
 15511            Environment.i.platform.cullingController.MarkDirty();
 15512            Environment.i.platform.physicsSyncController.MarkDirty();
 513
 15514            DataStore_World worldData = DataStore.i.Get<DataStore_World>();
 15515            Transform avatarTransform = worldData.avatarTransform.Get();
 15516            Transform firstPersonCameraTransform = worldData.fpsTransform.Get();
 517
 518            // CONST_THIRD_PERSON_CAMERA_ENTITY_REFERENCE is for compatibility purposes
 15519            if (parentId == (long)SpecialEntityId.FIRST_PERSON_CAMERA_ENTITY_REFERENCE ||
 520                parentId == (long)SpecialEntityId.THIRD_PERSON_CAMERA_ENTITY_REFERENCE)
 521            {
 1522                if (firstPersonCameraTransform == null)
 523                {
 0524                    Debug.LogError("FPS transform is null when trying to set parent! " + sceneData.sceneNumber);
 0525                    return;
 526                }
 527
 528                // In this case, the entity will attached to the first person camera
 529                // On first person mode, the entity will rotate with the camera. On third person mode, the entity will r
 1530                me.SetParent(null);
 1531                me.gameObject.transform.SetParent(firstPersonCameraTransform, false);
 1532                Environment.i.world.sceneBoundsChecker.RemoveEntity(me, removeIfPersistent: true, resetState: true);
 1533                Environment.i.world.sceneBoundsChecker.AddEntityToBeChecked(me, isPersistent: true, runPreliminaryEvalua
 1534                return;
 535            }
 536
 14537            if (parentId == (long)SpecialEntityId.AVATAR_ENTITY_REFERENCE ||
 538                parentId == (long)SpecialEntityId
 539                   .AVATAR_POSITION_REFERENCE) // AvatarPositionEntityReference is for compatibility purposes
 540            {
 1541                if (avatarTransform == null)
 542                {
 0543                    Debug.LogError("Avatar transform is null when trying to set parent! " + sceneData.sceneNumber);
 0544                    return;
 545                }
 546
 547                // In this case, the entity will be attached to the avatar
 548                // It will simply rotate with the avatar, regardless of where the camera is pointing
 1549                me.SetParent(null);
 1550                me.gameObject.transform.SetParent(avatarTransform, false);
 1551                Environment.i.world.sceneBoundsChecker.RemoveEntity(me, removeIfPersistent: true, resetState: true);
 1552                Environment.i.world.sceneBoundsChecker.AddEntityToBeChecked(me, isPersistent: true, runPreliminaryEvalua
 1553                return;
 554            }
 555
 556            // Remove from persistent checks if it was formerly added as child of avatarTransform or fpsTransform
 13557            if (me.gameObject.transform.parent == avatarTransform ||
 558                me.gameObject.transform.parent == firstPersonCameraTransform)
 559            {
 2560                if (Environment.i.world.sceneBoundsChecker.WasAddedAsPersistent(me))
 2561                    Environment.i.world.sceneBoundsChecker.RemoveEntity(me, removeIfPersistent: true);
 562            }
 563
 13564            if (parentId == (long)SpecialEntityId.SCENE_ROOT_ENTITY)
 565            {
 566                // The entity will be child of the scene directly
 2567                me.SetParent(null);
 2568                me.gameObject.transform.SetParent(gameObject.transform, false);
 569            }
 570            else
 571            {
 11572                IDCLEntity myParent = GetEntityById(parentId);
 573
 22574                if (myParent != null) { me.SetParent(myParent); }
 575            }
 576
 577            // After reparenting the Entity may end up outside the scene boundaries
 13578            Environment.i.world.sceneBoundsChecker?.AddEntityToBeChecked(me, runPreliminaryEvaluation: true);
 13579        }
 580
 581        protected virtual void SendMetricsEvent()
 582        {
 13082583            if (Time.frameCount % 10 == 0)
 1317584                metricsCounter.SendEvent();
 13082585        }
 586
 587        public IDCLEntity GetEntityById(long entityId)
 588        {
 800589            if (!entities.TryGetValue(entityId, out IDCLEntity entity)) { return null; }
 590
 591            //NOTE(Brian): This is for removing stray null references? This should never happen.
 592            //             Maybe move to a different 'clean-up' method to make this method have a single responsibility?
 800593            if (entity == null || entity.gameObject == null)
 594            {
 0595                entities.Remove(entityId);
 0596                return null;
 597            }
 598
 800599            return entity;
 600        }
 601
 602        public string GetStateString()
 603        {
 820604            string baseState = isPersistent ? "global-scene" : "scene";
 605
 820606            switch (sceneLifecycleHandler.state)
 607            {
 608                case SceneLifecycleHandler.State.NOT_READY:
 0609                    return $"{baseState}:{prettyName} - not ready...";
 610                case SceneLifecycleHandler.State.WAITING_FOR_INIT_MESSAGES:
 426611                    return $"{baseState}:{prettyName} - waiting for init messages...";
 612                case SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS:
 1613                    return $"{baseState}:{prettyName} - {sceneLifecycleHandler.sceneResourcesLoadTracker.GetStateString(
 614                case SceneLifecycleHandler.State.READY:
 393615                    return $"{baseState}:{prettyName} - ready! ({(contentCategory != SceneContentCategory.TEEN ? content
 616            }
 617
 0618            return $"scene:{prettyName} - no state?";
 619        }
 620
 621        public void RefreshLoadingState()
 622        {
 623#if UNITY_STANDALONE || UNITY_EDITOR
 820624            if (DataStore.i.common.isApplicationQuitting.Get())
 0625                return;
 626#endif
 627
 820628            CalculateSceneLoadingState();
 629
 630#if UNITY_EDITOR
 820631            gameObject.name = GetStateString();
 632#endif
 820633        }
 634
 635        [ContextMenu("Get Waiting Components Debug Info")]
 636        public void GetWaitingComponentsDebugInfo()
 637        {
 0638            switch (sceneLifecycleHandler.state)
 639            {
 640                case SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS:
 0641                    sceneLifecycleHandler.sceneResourcesLoadTracker.PrintWaitingResourcesDebugInfo();
 0642                    break;
 643
 644                default:
 0645                    Debug.Log($"The scene {sceneData.sceneNumber} is not waiting for any components. Its current state i
 646                    break;
 647            }
 0648        }
 649
 650        [ContextMenu("Get Scene Info")]
 651        public void GetSceneDebugInfo()
 652        {
 0653            Debug.Log("-----------------");
 0654            Debug.Log("SCENE DEBUG INFO:");
 0655            Debug.Log($"Scene Id: {sceneData.id}");
 0656            Debug.Log($"Scene Number: {sceneData.sceneNumber}");
 0657            Debug.Log($"Scene Coords: {sceneData.basePosition.ToString()}");
 0658            Debug.Log($"Scene State: {sceneLifecycleHandler.state.ToString()}");
 0659            Debug.Log("-----------------");
 0660        }
 661
 662        /// <summary>
 663        /// Calculates the current loading progress of the scene and raise the event OnLoadingStateUpdated with the perc
 664        /// </summary>
 665        public void CalculateSceneLoadingState()
 666        {
 820667            loadingProgress = 0f;
 668
 820669            if (sceneLifecycleHandler.state == SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS ||
 394670                sceneLifecycleHandler.state == SceneLifecycleHandler.State.READY) { loadingProgress = sceneLifecycleHand
 671
 820672            OnLoadingStateUpdated?.Invoke(loadingProgress);
 0673        }
 674
 675        public bool IsInitMessageDone()
 676        {
 8677            return sceneLifecycleHandler.state == SceneLifecycleHandler.State.READY
 678                   || sceneLifecycleHandler.state == SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS;
 679        }
 680
 681        public void SetContentCategory(SceneContentCategory category) =>
 69682            contentCategory = category;
 683
 684        public void SetAssociatedPlace(string placeId) =>
 69685            associatedPlaceId = placeId;
 686    }
 687}

Methods/Properties

ParcelScene()
entities()
entities(System.Collections.Generic.Dictionary[Int64,IDCLEntity])
componentsManagerLegacy()
componentsManagerLegacy(DCL.IECSComponentsManagerLegacy)
sceneData()
sceneData(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
metricsCounter()
metricsCounter(DCL.ISceneMetricsCounter)
contentProvider()
contentProvider(DCL.ContentProvider)
isTestScene()
isTestScene(System.Boolean)
isPersistent()
isPersistent(System.Boolean)
isPortableExperience()
isPortableExperience(System.Boolean)
loadingProgress()
loadingProgress(System.Single)
contentCategory()
contentCategory(DCL.Controllers.SceneContentCategory)
associatedPlaceId()
associatedPlaceId(System.String)
isReleased()
isReleased(System.Boolean)
featureFlags()
Awake()
OnDestroy()
OnDisable()
Update()
prettyName()
SetData()
SetupPositionAndParcels()
OnWorldReposition(UnityEngine.Vector3, UnityEngine.Vector3)
SetUpdateData(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
InitializeDebugPlane()
RemoveDebugPlane()
Cleanup(System.Boolean)
ToString()
GetSceneName()
GetParcels()
IsInsideSceneBoundaries(UnityEngine.Bounds)
IsInsideSceneBoundaries(UnityEngine.Vector2Int, System.Single)
IsInsideSceneBoundaries(UnityEngine.Vector3, System.Single)
IsInsideSceneOuterBoundaries(UnityEngine.Bounds)
IsInsideSceneOuterBoundaries(UnityEngine.Vector3)
OnDrawGizmosSelected()
GetEntityById(System.String)
GetSceneTransform()
CreateEntity(System.Int64)
OnEntityShapeUpdated(DCL.Models.IDCLEntity)
RemoveEntity(System.Int64, System.Boolean)
CleanUpEntityRecursively(DCL.Models.IDCLEntity, System.Boolean)
RemoveAllEntities(System.Boolean)
RemoveAllEntitiesImmediate()
SetEntityParent(System.Int64, System.Int64)
SendMetricsEvent()
GetEntityById(System.Int64)
GetStateString()
RefreshLoadingState()
GetWaitingComponentsDebugInfo()
GetSceneDebugInfo()
CalculateSceneLoadingState()
IsInitMessageDone()
SetContentCategory(DCL.Controllers.SceneContentCategory)
SetAssociatedPlace(System.String)