< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:217
Uncovered lines:157
Coverable lines:374
Total lines:893
Line coverage:58% (217 of 374)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneController()0%110100%
Initialize()0%22093.33%
OnDebugModeSet()0%110100%
Start()0%6.744044.44%
Dispose()0%2.012087.5%
Update()0%440100%
LateUpdate()0%220100%
EnsureEntityPool()0%330100%
ProcessMessage(...)0%1101000%
ProcessMessage(...)0%22564700%
ParseQuery(...)0%6200%
SendSceneMessage(...)0%2100%
SendSceneMessage(...)0%12300%
DecodeAndEnqueue(...)0%30500%
DeferredDecoding()0%56700%
EnqueueSceneMessage(...)0%2100%
CreateTestScene(...)0%770100%
SendSceneReady(...)0%2.022083.33%
ActivateBuilderInWorldEditScene()0%2100%
DeactivateBuilderInWorldEditScene()0%2100%
SetPositionDirty(...)0%4.024090%
SortScenesByDistance()0%8.018095.24%
SortScenesByDistanceMethod(...)0%110100%
OnCurrentSceneIdChange(...)0%64050%
LoadParcelScenesExecute(...)0%13.9613082.14%
UpdateParcelScenesExecute(...)0%20400%
UpdateParcelScenesExecute(...)0%6.396077.78%
UnloadScene(...)0%6.036090.91%
UnloadParcelSceneExecute(...)0%7.277082.35%
UnloadAllScenes(...)0%770100%
LoadParcelScenes(...)0%3.043083.33%
UpdateParcelScenes(...)0%6200%
UnloadAllScenesQueued()0%6200%
CreateGlobalScene(...)0%9.469082.14%
IsolateScene(...)0%3.043083.33%
ReIntegrateIsolatedScene()0%220100%

File(s)

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

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using DCL.Models;
 5using DCL.Configuration;
 6using System;
 7using System.Collections;
 8using System.Collections.Generic;
 9using System.Linq;
 10using DCL.Components;
 11using Newtonsoft.Json;
 12using UnityEngine;
 13
 14namespace DCL
 15{
 16    public class SceneController : ISceneController
 17    {
 18        public static bool VERBOSE = false;
 19
 58120        public bool enabled { get; set; } = true;
 21
 22        private Coroutine deferredDecodingCoroutine;
 23
 24        public void Initialize()
 25        {
 54726            sceneSortDirty = true;
 54727            positionDirty = true;
 54728            lastSortFrame = 0;
 54729            enabled = true;
 30
 54731            Environment.i.platform.debugController.OnDebugModeSet += OnDebugModeSet;
 32
 33            // We trigger the Decentraland logic once SceneController has been instanced and is ready to act.
 54734            WebInterface.StartDecentraland();
 35
 54736            if (deferredMessagesDecoding) // We should be able to delete this code
 037                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding()); //
 38
 54739            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 40
 54741            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 42
 43            //TODO(Brian): Move those subscriptions elsewhere.
 54744            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 54745            PoolManager.i.OnGet += Environment.i.platform.physicsSyncController.MarkDirty;
 46
 54747            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 54748            PoolManager.i.OnGet += Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 54749        }
 50
 51        private void OnDebugModeSet()
 52        {
 1053            Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedFlicker());
 1054        }
 55
 56        public void Start()
 57        {
 10558            if (prewarmSceneMessagesPool)
 59            {
 060                for (int i = 0; i < 100000; i++)
 61                {
 062                    sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 63                }
 64            }
 65
 10566            if (prewarmEntitiesPool)
 67            {
 068                EnsureEntityPool();
 69            }
 70
 71            // Warmup some shader variants
 10572            Resources.Load<ShaderVariantCollection>("ShaderVariantCollections/shaderVariants-selected").WarmUp();
 10573        }
 74
 75        public void Dispose()
 76        {
 55377            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 55378            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 55379            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 55380            Environment.i.platform.debugController.OnDebugModeSet -= OnDebugModeSet;
 81
 55382            UnloadAllScenes(includePersistent: true);
 83
 55384            if (deferredDecodingCoroutine != null)
 085                CoroutineStarter.Stop(deferredDecodingCoroutine);
 55386        }
 87
 88        public void Update()
 89        {
 1393490            if (!enabled)
 5191                return;
 92
 1388393            InputController_Legacy.i.Update();
 94
 1388395            Environment.i.world.pointerEventsController.Update();
 96
 1388397            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 98            {
 71899                lastSortFrame = Time.frameCount;
 718100                sceneSortDirty = false;
 718101                SortScenesByDistance();
 102            }
 13883103        }
 104
 105        public void LateUpdate()
 106        {
 13932107            if (!enabled)
 51108                return;
 109
 13881110            Environment.i.platform.physicsSyncController.Sync();
 13881111        }
 112
 113        public void EnsureEntityPool() // TODO: Move to PoolManagerFactory
 114        {
 470115            if (PoolManager.i.ContainsPool(EMPTY_GO_POOL_NAME))
 262116                return;
 117
 208118            GameObject go = new GameObject();
 208119            Pool pool = PoolManager.i.AddPool(EMPTY_GO_POOL_NAME, go, maxPrewarmCount: 2000, isPersistent: true);
 120
 208121            if (prewarmEntitiesPool)
 14122                pool.ForcePrewarm();
 208123        }
 124
 125        //======================================================================
 126
 127        #region MESSAGES_HANDLING
 128
 129        //======================================================================
 130
 131#if UNITY_EDITOR
 132        public delegate void ProcessDelegate(string sceneId, string method);
 133
 134        public event ProcessDelegate OnMessageProcessInfoStart;
 135        public event ProcessDelegate OnMessageProcessInfoEnds;
 136#endif
 508137        public bool deferredMessagesDecoding { get; set; } = false;
 138
 547139        Queue<string> payloadsToDecode = new Queue<string>();
 140        const float MAX_TIME_FOR_DECODE = 0.005f;
 141
 142        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 143        {
 0144            string sceneId = msgObject.sceneId;
 0145            string method = msgObject.method;
 146
 0147            yieldInstruction = null;
 148
 149            IParcelScene scene;
 0150            bool res = false;
 0151            IWorldState worldState = Environment.i.world.state;
 0152            DebugConfig debugConfig = DataStore.i.debugConfig;
 153
 0154            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 155            {
 156#if UNITY_EDITOR
 0157                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 158                {
 0159                    return false;
 160                }
 161#endif
 0162                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 163                {
 0164                    return true;
 165                }
 166
 167#if UNITY_EDITOR
 0168                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 169#endif
 0170                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 171
 0172                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 173
 0174                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 175
 176#if UNITY_EDITOR
 0177                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 178#endif
 179
 0180                res = true;
 0181            }
 182
 183            else
 184            {
 0185                res = false;
 186            }
 187
 0188            sceneMessagesPool.Enqueue(msgObject);
 189
 0190            return res;
 191        }
 192
 193        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 194            out CustomYieldInstruction yieldInstruction)
 195        {
 0196            yieldInstruction = null;
 0197            IDelayedComponent delayedComponent = null;
 198
 199            try
 200            {
 201                switch (method)
 202                {
 203                    case MessagingTypes.ENTITY_CREATE:
 204                        {
 0205                            if (msgPayload is Protocol.CreateEntity payload)
 0206                                scene.CreateEntity(payload.entityId);
 207
 0208                            break;
 209                        }
 210                    case MessagingTypes.ENTITY_REPARENT:
 211                        {
 0212                            if (msgPayload is Protocol.SetEntityParent payload)
 0213                                scene.SetEntityParent(payload.entityId, payload.parentId);
 214
 0215                            break;
 216                        }
 217
 218                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 219                        {
 0220                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 221                            {
 0222                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 223                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 224                            }
 225
 0226                            break;
 227                        }
 228
 229                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 230                        {
 0231                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0232                                scene.EntityComponentRemove(payload.entityId, payload.name);
 233
 0234                            break;
 235                        }
 236
 237                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 238                        {
 0239                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0240                                scene.SharedComponentAttach(payload.entityId, payload.id);
 241
 0242                            break;
 243                        }
 244
 245                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 246                        {
 0247                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0248                                scene.SharedComponentCreate(payload.id, payload.classId);
 249
 0250                            break;
 251                        }
 252
 253                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 254                        {
 0255                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0256                                scene.SharedComponentDispose(payload.id);
 0257                            break;
 258                        }
 259
 260                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 261                        {
 0262                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0263                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 264
 0265                            break;
 266                        }
 267
 268                    case MessagingTypes.ENTITY_DESTROY:
 269                        {
 0270                            if (msgPayload is Protocol.RemoveEntity payload)
 0271                                scene.RemoveEntity(payload.entityId);
 0272                            break;
 273                        }
 274
 275                    case MessagingTypes.INIT_DONE:
 276                        {
 0277                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0278                            break;
 279                        }
 280
 281                    case MessagingTypes.QUERY:
 282                        {
 0283                            if (msgPayload is QueryMessage queryMessage)
 0284                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0285                            break;
 286                        }
 287
 288                    case MessagingTypes.OPEN_EXTERNAL_URL:
 289                        {
 0290                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0291                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0292                            break;
 293                        }
 294
 295                    case MessagingTypes.OPEN_NFT_DIALOG:
 296                        {
 0297                            if (msgPayload is Protocol.OpenNftDialog payload)
 0298                                DataStore.i.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payload.token
 299                                    payload.comment), true);
 0300                            break;
 301                        }
 302
 303                    default:
 0304                        Debug.LogError($"Unknown method {method}");
 305                        break;
 306                }
 0307            }
 0308            catch (Exception e)
 309            {
 0310                throw new Exception(
 311                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 312            }
 313
 0314            if (delayedComponent != null)
 315            {
 0316                if (delayedComponent.isRoutineRunning)
 0317                    yieldInstruction = delayedComponent.yieldInstruction;
 318            }
 0319        }
 320
 321        public void ParseQuery(object payload, string sceneId)
 322        {
 0323            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 324
 0325            if (!(payload is RaycastQuery raycastQuery))
 0326                return;
 327
 0328            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 329
 0330            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0331            raycastQuery.sceneId = sceneId;
 0332            PhysicsCast.i.Query(raycastQuery);
 0333        }
 334
 0335        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 336
 337        private void SendSceneMessage(string payload, bool enqueue)
 338        {
 0339            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0340            int count = chunks.Length;
 341
 0342            for (int i = 0; i < count; i++)
 343            {
 0344                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 345                {
 0346                    payloadsToDecode.Enqueue(chunks[i]);
 0347                }
 348                else
 349                {
 0350                    DecodeAndEnqueue(chunks[i]);
 351                }
 352            }
 0353        }
 354
 355        private void DecodeAndEnqueue(string payload)
 356        {
 0357            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 358
 359            string sceneId;
 360            string message;
 361            string messageTag;
 362            PB_SendSceneMessage sendSceneMessage;
 363
 0364            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 365            {
 0366                return;
 367            }
 368
 369            QueuedSceneMessage_Scene queuedMessage;
 370
 0371            if (sceneMessagesPool.Count > 0)
 0372                queuedMessage = sceneMessagesPool.Dequeue();
 373            else
 0374                queuedMessage = new QueuedSceneMessage_Scene();
 375
 0376            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 377
 0378            EnqueueSceneMessage(queuedMessage);
 379
 0380            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0381        }
 382
 383        private IEnumerator DeferredDecoding()
 384        {
 0385            float start = Time.realtimeSinceStartup;
 386            float maxTimeForDecode;
 387
 0388            while (true)
 389            {
 0390                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 391
 0392                if (payloadsToDecode.Count > 0)
 393                {
 0394                    string payload = payloadsToDecode.Dequeue();
 395
 0396                    DecodeAndEnqueue(payload);
 397
 0398                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 399                        continue;
 400                }
 401
 0402                yield return null;
 0403                start = Time.unscaledTime;
 404            }
 405        }
 406
 407        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 408        {
 0409            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0410            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0411            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0412        }
 413
 414        //======================================================================
 415
 416        #endregion
 417
 418        //======================================================================
 419
 420        //======================================================================
 421
 422        #region SCENES_MANAGEMENT
 423
 424        //======================================================================
 425        public event Action<string> OnReadyScene;
 426
 427        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 428        {
 526429            if (data == null)
 430            {
 526431                data = new LoadParcelScenesMessage.UnityParcelScene();
 432            }
 433
 526434            if (data.parcels == null)
 435            {
 526436                data.parcels = new Vector2Int[] { data.basePosition };
 437            }
 438
 526439            if (string.IsNullOrEmpty(data.id))
 440            {
 526441                data.id = $"(test):{data.basePosition.x},{data.basePosition.y}";
 442            }
 443
 526444            if (Environment.i.world.state.loadedScenes.ContainsKey(data.id))
 445            {
 4446                Debug.LogWarning($"Scene {data.id} is already loaded.");
 4447                return Environment.i.world.state.loadedScenes[data.id];
 448            }
 449
 522450            var go = new GameObject();
 522451            var newScene = go.AddComponent<ParcelScene>();
 522452            newScene.ownerController = this;
 522453            newScene.isTestScene = true;
 522454            newScene.isPersistent = true;
 522455            newScene.SetData(data);
 456
 522457            if (DCLCharacterController.i != null)
 522458                newScene.InitializeDebugPlane();
 459
 522460            Environment.i.world.state.scenesSortedByDistance.Add(newScene);
 461
 522462            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 463
 522464            Environment.i.world.state.loadedScenes.Add(data.id, newScene);
 522465            OnNewSceneAdded?.Invoke(newScene);
 466
 522467            return newScene;
 468        }
 469
 470        public void SendSceneReady(string sceneId)
 471        {
 522472            Environment.i.world.state.readyScenes.Add(sceneId);
 473
 522474            Environment.i.messaging.manager.SetSceneReady(sceneId);
 475
 522476            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 477
 522478            Environment.i.world.blockersController.SetupWorldBlockers();
 479
 522480            OnReadyScene?.Invoke(sceneId);
 0481        }
 482
 0483        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 484
 0485        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 486
 487        private void SetPositionDirty(DCLCharacterPosition character)
 488        {
 1715489            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 1715490            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 491
 1715492            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 493
 1715494            if (positionDirty)
 495            {
 319496                sceneSortDirty = true;
 319497                currentGridSceneCoordinate.x = currentX;
 319498                currentGridSceneCoordinate.y = currentY;
 499
 500                // Since the first position for the character is not sent from Kernel until just-before calling
 501                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 502                // to lock the rendering accordingly...
 319503                if (!CommonScriptableObjects.rendererState.Get())
 504                {
 0505                    SortScenesByDistance();
 506                }
 507            }
 1715508        }
 509
 510        public void SortScenesByDistance()
 511        {
 722512            if (DCLCharacterController.i == null)
 0513                return;
 514
 722515            IWorldState worldState = Environment.i.world.state;
 516
 722517            worldState.currentSceneId = null;
 722518            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 519
 722520            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 521            {
 522                IParcelScene scene;
 523                bool characterIsInsideScene;
 524
 1258525                while (iterator.MoveNext())
 526                {
 690527                    scene = iterator.Current;
 528
 690529                    if (scene == null)
 530                        continue;
 531
 690532                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 533
 690534                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 535                    {
 154536                        worldState.currentSceneId = scene.sceneData.id;
 154537                        break;
 538                    }
 539                }
 568540            }
 541
 722542            if (!DataStore.i.debugConfig.isDebugMode && string.IsNullOrEmpty(worldState.currentSceneId))
 543            {
 544                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 537545                CommonScriptableObjects.rendererState.AddLock(this);
 537546            }
 547            else
 548            {
 549                // 1. Set current scene id
 185550                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 551
 552                // 2. Attempt to remove SceneController's lock on rendering
 185553                CommonScriptableObjects.rendererState.RemoveLock(this);
 554            }
 555
 722556            OnSortScenes?.Invoke();
 706557        }
 558
 559        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 560        {
 60561            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 60562            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 563
 60564            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 60565            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 566
 60567            return dist1 - dist2;
 568        }
 569
 570        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 571        {
 5689572            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 573                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 574            {
 0575                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 576
 0577                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 578            }
 5689579        }
 580
 581        public void LoadParcelScenesExecute(string scenePayload)
 582        {
 583            LoadParcelScenesMessage.UnityParcelScene scene;
 584
 27585            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 27586            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 27587            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 588
 27589            if (scene == null || scene.id == null)
 0590                return;
 591
 27592            var sceneToLoad = scene;
 593
 594
 27595            DebugConfig debugConfig = DataStore.i.debugConfig;
 596#if UNITY_EDITOR
 27597            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 598            {
 0599                SendSceneReady(sceneToLoad.id);
 0600                return;
 601            }
 602#endif
 603
 27604            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 605
 27606            IWorldState worldState = Environment.i.world.state;
 607
 27608            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 609            {
 27610                var newGameObject = new GameObject("New Scene");
 611
 27612                var newScene = newGameObject.AddComponent<ParcelScene>();
 27613                newScene.SetData(sceneToLoad);
 614
 27615                if (debugConfig.isDebugMode)
 616                {
 27617                    newScene.InitializeDebugPlane();
 618                }
 619
 27620                newScene.ownerController = this;
 27621                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 27622                worldState.scenesSortedByDistance.Add(newScene);
 623
 27624                sceneSortDirty = true;
 625
 27626                OnNewSceneAdded?.Invoke(newScene);
 627
 27628                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 629
 27630                if (VERBOSE)
 0631                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 632            }
 633
 27634            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0635        }
 636
 637        public void UpdateParcelScenesExecute(string sceneId)
 638        {
 639            LoadParcelScenesMessage.UnityParcelScene sceneData;
 640
 0641            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0642            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0643            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 644
 0645            IWorldState worldState = Environment.i.world.state;
 646
 0647            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 648            {
 0649                ParcelScene scene = sceneInterface as ParcelScene;
 0650                scene.SetUpdateData(sceneData);
 0651            }
 652            else
 653            {
 0654                LoadParcelScenesExecute(sceneId);
 655            }
 0656        }
 657
 658        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 659        {
 15660            if (scene == null || scene.id == null)
 0661                return;
 662
 15663            var sceneToLoad = scene;
 664
 15665            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 666
 15667            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 668
 15669            if (parcelScene != null)
 15670                parcelScene.SetUpdateData(sceneToLoad);
 671
 15672            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0673        }
 674
 675        public void UnloadScene(string sceneKey)
 676        {
 1677            var queuedMessage = new QueuedSceneMessage()
 678                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 679
 1680            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 681
 1682            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 683
 1684            Environment.i.messaging.manager.RemoveController(sceneKey);
 685
 1686            IWorldState worldState = Environment.i.world.state;
 687
 1688            if (worldState.loadedScenes.ContainsKey(sceneKey))
 689            {
 1690                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1691                sceneToUnload.isPersistent = false;
 692
 1693                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0694                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 695            }
 1696        }
 697
 698        public void UnloadParcelSceneExecute(string sceneId)
 699        {
 556700            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 701
 556702            IWorldState worldState = Environment.i.world.state;
 703
 556704            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 705            {
 1706                return;
 707            }
 708
 555709            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 710
 555711            if (scene == null)
 0712                return;
 713
 555714            worldState.loadedScenes.Remove(sceneId);
 555715            worldState.globalSceneIds.Remove(sceneId);
 716
 717            // Remove the scene id from the msg. priorities list
 555718            worldState.scenesSortedByDistance.Remove(scene);
 719
 720            // Remove messaging controller for unloaded scene
 555721            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 722
 555723            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 724
 555725            if (VERBOSE)
 726            {
 0727                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 728            }
 729
 555730            Environment.i.world.blockersController.SetupWorldBlockers();
 731
 555732            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0733        }
 734
 735        public void UnloadAllScenes(bool includePersistent = false)
 736        {
 556737            var worldState = Environment.i.world.state;
 738
 556739            if (includePersistent)
 740            {
 1108741                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 742
 2166743                foreach (var kvp in persistentScenes)
 744                {
 528745                    if (kvp.Value is ParcelScene scene)
 746                    {
 528747                        scene.isPersistent = false;
 748                    }
 749                }
 750            }
 751
 556752            var list = worldState.loadedScenes.ToArray();
 753
 2222754            for (int i = 0; i < list.Length; i++)
 755            {
 555756                UnloadParcelSceneExecute(list[i].Key);
 757            }
 556758        }
 759
 760        public void LoadParcelScenes(string decentralandSceneJSON)
 761        {
 27762            var queuedMessage = new QueuedSceneMessage()
 763            {
 764                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 765                message = decentralandSceneJSON
 766            };
 767
 27768            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 769
 27770            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 771
 27772            if (VERBOSE)
 0773                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 27774        }
 775
 776        public void UpdateParcelScenes(string decentralandSceneJSON)
 777        {
 0778            var queuedMessage = new QueuedSceneMessage()
 779                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 780
 0781            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 782
 0783            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0784        }
 785
 786        public void UnloadAllScenesQueued()
 787        {
 0788            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 789
 0790            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 791
 0792            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0793        }
 794
 795        public void CreateGlobalScene(string json)
 796        {
 797#if UNITY_EDITOR
 7798            DebugConfig debugConfig = DataStore.i.debugConfig;
 799
 7800            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0801                return;
 802#endif
 7803            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 804
 7805            string newGlobalSceneId = globalScene.id;
 806
 7807            IWorldState worldState = Environment.i.world.state;
 808
 7809            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0810                return;
 811
 7812            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 813
 7814            var newScene = newGameObject.AddComponent<GlobalScene>();
 7815            newScene.ownerController = this;
 7816            newScene.unloadWithDistance = false;
 7817            newScene.isPersistent = true;
 7818            newScene.sceneName = globalScene.name;
 7819            newScene.isPortableExperience = globalScene.isPortableExperience;
 820
 7821            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 822            {
 823                id = newGlobalSceneId,
 824                basePosition = new Vector2Int(0, 0),
 825                baseUrl = globalScene.baseUrl,
 826                contents = globalScene.contents
 827            };
 828
 7829            newScene.SetData(data);
 830
 7831            if (!string.IsNullOrEmpty(globalScene.icon))
 0832                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 833
 7834            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 7835            OnNewSceneAdded?.Invoke(newScene);
 836
 7837            if (newScene.isPortableExperience)
 0838                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 839
 7840            worldState.globalSceneIds.Add(newGlobalSceneId);
 841
 7842            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 843
 7844            if (VERBOSE)
 845            {
 0846                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 847            }
 7848        }
 849
 850        public void IsolateScene(IParcelScene sceneToActive)
 851        {
 16852            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 853            {
 4854                if (scene != sceneToActive)
 0855                    scene.GetSceneTransform().gameObject.SetActive(false);
 856            }
 4857        }
 858
 859        public void ReIntegrateIsolatedScene()
 860        {
 12861            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 862            {
 3863                scene.GetSceneTransform().gameObject.SetActive(true);
 864            }
 3865        }
 866
 867        //======================================================================
 868
 869        #endregion
 870
 871        //======================================================================
 872
 547873        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 874
 1055875        public bool prewarmSceneMessagesPool { get; set; } = true;
 1055876        public bool prewarmEntitiesPool { get; set; } = true;
 877
 878        private bool sceneSortDirty = false;
 547879        private bool positionDirty = true;
 880        private int lastSortFrame = 0;
 881
 882        public event Action OnSortScenes;
 883        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 884        public event Action<IParcelScene> OnNewSceneAdded;
 885        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 886        public event Action<string> OnNewPortableExperienceSceneRemoved;
 887
 547888        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 547889        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 890
 891        public const string EMPTY_GO_POOL_NAME = "Empty";
 892    }
 893}

Methods/Properties

enabled()
enabled(System.Boolean)
SceneController()
Initialize()
OnDebugModeSet()
Start()
Dispose()
Update()
LateUpdate()
EnsureEntityPool()
deferredMessagesDecoding()
deferredMessagesDecoding(System.Boolean)
ProcessMessage(DCL.QueuedSceneMessage_Scene, UnityEngine.CustomYieldInstruction&)
ProcessMessage(DCL.Controllers.ParcelScene, System.String, System.Object, UnityEngine.CustomYieldInstruction&)
ParseQuery(System.Object, System.String)
SendSceneMessage(System.String)
SendSceneMessage(System.String, System.Boolean)
DecodeAndEnqueue(System.String)
DeferredDecoding()
EnqueueSceneMessage(DCL.QueuedSceneMessage_Scene)
CreateTestScene(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
SendSceneReady(System.String)
ActivateBuilderInWorldEditScene()
DeactivateBuilderInWorldEditScene()
SetPositionDirty(DCLCharacterPosition)
SortScenesByDistance()
SortScenesByDistanceMethod(DCL.Controllers.IParcelScene, DCL.Controllers.IParcelScene)
OnCurrentSceneIdChange(System.String, System.String)
LoadParcelScenesExecute(System.String)
UpdateParcelScenesExecute(System.String)
UpdateParcelScenesExecute(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
UnloadScene(System.String)
UnloadParcelSceneExecute(System.String)
UnloadAllScenes(System.Boolean)
LoadParcelScenes(System.String)
UpdateParcelScenes(System.String)
UnloadAllScenesQueued()
CreateGlobalScene(System.String)
IsolateScene(DCL.Controllers.IParcelScene)
ReIntegrateIsolatedScene()
sceneMessagesPool()
prewarmSceneMessagesPool()
prewarmSceneMessagesPool(System.Boolean)
prewarmEntitiesPool()
prewarmEntitiesPool(System.Boolean)