< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:220
Uncovered lines:153
Coverable lines:373
Total lines:889
Line coverage:58.9% (220 of 373)
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%220100%
ActivateBuilderInWorldEditScene()0%110100%
DeactivateBuilderInWorldEditScene()0%110100%
SetPositionDirty(...)0%440100%
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
 71820        public bool enabled { get; set; } = true;
 21
 22        private Coroutine deferredDecodingCoroutine;
 23
 24        public void Initialize()
 25        {
 68226            sceneSortDirty = true;
 68227            positionDirty = true;
 68228            lastSortFrame = 0;
 68229            enabled = true;
 30
 68231            Environment.i.platform.debugController.OnDebugModeSet += OnDebugModeSet;
 32
 33            // We trigger the Decentraland logic once SceneController has been instanced and is ready to act.
 68234            WebInterface.StartDecentraland();
 35
 68236            if (deferredMessagesDecoding) // We should be able to delete this code
 037                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding()); //
 38
 68239            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 40
 68241            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 42
 43            //TODO(Brian): Move those subscriptions elsewhere.
 68244            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 68245            PoolManager.i.OnGet += Environment.i.platform.physicsSyncController.MarkDirty;
 46
 68247            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 68248            PoolManager.i.OnGet += Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 68249        }
 50
 2051        private void OnDebugModeSet() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackS
 52
 53        public void Start()
 54        {
 12355            if (prewarmSceneMessagesPool)
 56            {
 057                for (int i = 0; i < 100000; i++)
 58                {
 059                    sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 60                }
 61            }
 62
 12363            if (prewarmEntitiesPool)
 64            {
 065                EnsureEntityPool();
 66            }
 67
 68            // Warmup some shader variants
 12369            Resources.Load<ShaderVariantCollection>("ShaderVariantCollections/shaderVariants-selected").WarmUp();
 12370        }
 71
 72        public void Dispose()
 73        {
 70274            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 70275            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 70276            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 70277            Environment.i.platform.debugController.OnDebugModeSet -= OnDebugModeSet;
 78
 70279            UnloadAllScenes(includePersistent: true);
 80
 70281            if (deferredDecodingCoroutine != null)
 082                CoroutineStarter.Stop(deferredDecodingCoroutine);
 70283        }
 84
 85        public void Update()
 86        {
 1734387            if (!enabled)
 5288                return;
 89
 1729190            InputController_Legacy.i.Update();
 91
 1729192            Environment.i.world.pointerEventsController.Update();
 93
 1729194            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 95            {
 82796                lastSortFrame = Time.frameCount;
 82797                sceneSortDirty = false;
 82798                SortScenesByDistance();
 99            }
 17291100        }
 101
 102        public void LateUpdate()
 103        {
 17337104            if (!enabled)
 52105                return;
 106
 17285107            Environment.i.platform.physicsSyncController.Sync();
 17285108        }
 109
 110        public void EnsureEntityPool() // TODO: Move to PoolManagerFactory
 111        {
 542112            if (PoolManager.i.ContainsPool(EMPTY_GO_POOL_NAME))
 275113                return;
 114
 267115            GameObject go = new GameObject();
 267116            Pool pool = PoolManager.i.AddPool(EMPTY_GO_POOL_NAME, go, maxPrewarmCount: 2000, isPersistent: true);
 117
 267118            if (prewarmEntitiesPool)
 14119                pool.ForcePrewarm();
 267120        }
 121
 122        //======================================================================
 123
 124        #region MESSAGES_HANDLING
 125
 126        //======================================================================
 127
 128#if UNITY_EDITOR
 129        public delegate void ProcessDelegate(string sceneId, string method);
 130
 131        public event ProcessDelegate OnMessageProcessInfoStart;
 132        public event ProcessDelegate OnMessageProcessInfoEnds;
 133#endif
 657134        public bool deferredMessagesDecoding { get; set; } = false;
 135
 682136        Queue<string> payloadsToDecode = new Queue<string>();
 137        const float MAX_TIME_FOR_DECODE = 0.005f;
 138
 139        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 140        {
 0141            string sceneId = msgObject.sceneId;
 0142            string method = msgObject.method;
 143
 0144            yieldInstruction = null;
 145
 146            IParcelScene scene;
 0147            bool res = false;
 0148            IWorldState worldState = Environment.i.world.state;
 0149            DebugConfig debugConfig = DataStore.i.debugConfig;
 150
 0151            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 152            {
 153#if UNITY_EDITOR
 0154                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 155                {
 0156                    return false;
 157                }
 158#endif
 0159                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 160                {
 0161                    return true;
 162                }
 163
 164#if UNITY_EDITOR
 0165                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 166#endif
 0167                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 168
 0169                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 170
 0171                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 172
 173#if UNITY_EDITOR
 0174                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 175#endif
 176
 0177                res = true;
 0178            }
 179
 180            else
 181            {
 0182                res = false;
 183            }
 184
 0185            sceneMessagesPool.Enqueue(msgObject);
 186
 0187            return res;
 188        }
 189
 190        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 191            out CustomYieldInstruction yieldInstruction)
 192        {
 0193            yieldInstruction = null;
 0194            IDelayedComponent delayedComponent = null;
 195
 196            try
 197            {
 198                switch (method)
 199                {
 200                    case MessagingTypes.ENTITY_CREATE:
 201                        {
 0202                            if (msgPayload is Protocol.CreateEntity payload)
 0203                                scene.CreateEntity(payload.entityId);
 204
 0205                            break;
 206                        }
 207                    case MessagingTypes.ENTITY_REPARENT:
 208                        {
 0209                            if (msgPayload is Protocol.SetEntityParent payload)
 0210                                scene.SetEntityParent(payload.entityId, payload.parentId);
 211
 0212                            break;
 213                        }
 214
 215                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 216                        {
 0217                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 218                            {
 0219                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 220                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 221                            }
 222
 0223                            break;
 224                        }
 225
 226                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 227                        {
 0228                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0229                                scene.EntityComponentRemove(payload.entityId, payload.name);
 230
 0231                            break;
 232                        }
 233
 234                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 235                        {
 0236                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0237                                scene.SharedComponentAttach(payload.entityId, payload.id);
 238
 0239                            break;
 240                        }
 241
 242                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 243                        {
 0244                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0245                                scene.SharedComponentCreate(payload.id, payload.classId);
 246
 0247                            break;
 248                        }
 249
 250                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 251                        {
 0252                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0253                                scene.SharedComponentDispose(payload.id);
 0254                            break;
 255                        }
 256
 257                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 258                        {
 0259                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0260                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 261
 0262                            break;
 263                        }
 264
 265                    case MessagingTypes.ENTITY_DESTROY:
 266                        {
 0267                            if (msgPayload is Protocol.RemoveEntity payload)
 0268                                scene.RemoveEntity(payload.entityId);
 0269                            break;
 270                        }
 271
 272                    case MessagingTypes.INIT_DONE:
 273                        {
 0274                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0275                            break;
 276                        }
 277
 278                    case MessagingTypes.QUERY:
 279                        {
 0280                            if (msgPayload is QueryMessage queryMessage)
 0281                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0282                            break;
 283                        }
 284
 285                    case MessagingTypes.OPEN_EXTERNAL_URL:
 286                        {
 0287                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0288                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0289                            break;
 290                        }
 291
 292                    case MessagingTypes.OPEN_NFT_DIALOG:
 293                        {
 0294                            if (msgPayload is Protocol.OpenNftDialog payload)
 0295                                DataStore.i.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payload.token
 296                                    payload.comment), true);
 0297                            break;
 298                        }
 299
 300                    default:
 0301                        Debug.LogError($"Unknown method {method}");
 302                        break;
 303                }
 0304            }
 0305            catch (Exception e)
 306            {
 0307                throw new Exception(
 308                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 309            }
 310
 0311            if (delayedComponent != null)
 312            {
 0313                if (delayedComponent.isRoutineRunning)
 0314                    yieldInstruction = delayedComponent.yieldInstruction;
 315            }
 0316        }
 317
 318        public void ParseQuery(object payload, string sceneId)
 319        {
 0320            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 321
 0322            if (!(payload is RaycastQuery raycastQuery))
 0323                return;
 324
 0325            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 326
 0327            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0328            raycastQuery.sceneId = sceneId;
 0329            PhysicsCast.i.Query(raycastQuery);
 0330        }
 331
 0332        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 333
 334        private void SendSceneMessage(string payload, bool enqueue)
 335        {
 0336            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0337            int count = chunks.Length;
 338
 0339            for (int i = 0; i < count; i++)
 340            {
 0341                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 342                {
 0343                    payloadsToDecode.Enqueue(chunks[i]);
 0344                }
 345                else
 346                {
 0347                    DecodeAndEnqueue(chunks[i]);
 348                }
 349            }
 0350        }
 351
 352        private void DecodeAndEnqueue(string payload)
 353        {
 0354            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 355
 356            string sceneId;
 357            string message;
 358            string messageTag;
 359            PB_SendSceneMessage sendSceneMessage;
 360
 0361            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 362            {
 0363                return;
 364            }
 365
 366            QueuedSceneMessage_Scene queuedMessage;
 367
 0368            if (sceneMessagesPool.Count > 0)
 0369                queuedMessage = sceneMessagesPool.Dequeue();
 370            else
 0371                queuedMessage = new QueuedSceneMessage_Scene();
 372
 0373            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 374
 0375            EnqueueSceneMessage(queuedMessage);
 376
 0377            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0378        }
 379
 380        private IEnumerator DeferredDecoding()
 381        {
 0382            float start = Time.realtimeSinceStartup;
 383            float maxTimeForDecode;
 384
 0385            while (true)
 386            {
 0387                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 388
 0389                if (payloadsToDecode.Count > 0)
 390                {
 0391                    string payload = payloadsToDecode.Dequeue();
 392
 0393                    DecodeAndEnqueue(payload);
 394
 0395                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 396                        continue;
 397                }
 398
 0399                yield return null;
 0400                start = Time.unscaledTime;
 401            }
 402        }
 403
 404        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 405        {
 0406            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0407            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0408            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0409        }
 410
 411        //======================================================================
 412
 413        #endregion
 414
 415        //======================================================================
 416
 417        //======================================================================
 418
 419        #region SCENES_MANAGEMENT
 420
 421        //======================================================================
 422        public event Action<string> OnReadyScene;
 423
 424        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 425        {
 682426            if (data == null)
 427            {
 674428                data = new LoadParcelScenesMessage.UnityParcelScene();
 429            }
 430
 682431            if (data.parcels == null)
 432            {
 674433                data.parcels = new Vector2Int[] { data.basePosition };
 434            }
 435
 682436            if (string.IsNullOrEmpty(data.id))
 437            {
 674438                data.id = $"(test):{data.basePosition.x},{data.basePosition.y}";
 439            }
 440
 682441            if (Environment.i.world.state.loadedScenes.ContainsKey(data.id))
 442            {
 12443                Debug.LogWarning($"Scene {data.id} is already loaded.");
 12444                return Environment.i.world.state.loadedScenes[data.id];
 445            }
 446
 670447            var go = new GameObject();
 670448            var newScene = go.AddComponent<ParcelScene>();
 670449            newScene.ownerController = this;
 670450            newScene.isTestScene = true;
 670451            newScene.isPersistent = true;
 670452            newScene.SetData(data);
 453
 670454            if (DCLCharacterController.i != null)
 670455                newScene.InitializeDebugPlane();
 456
 670457            Environment.i.world.state.scenesSortedByDistance.Add(newScene);
 458
 670459            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 460
 670461            Environment.i.world.state.loadedScenes.Add(data.id, newScene);
 670462            OnNewSceneAdded?.Invoke(newScene);
 670463            return newScene;
 464        }
 465
 466        public void SendSceneReady(string sceneId)
 467        {
 678468            Environment.i.world.state.readyScenes.Add(sceneId);
 469
 678470            Environment.i.messaging.manager.SetSceneReady(sceneId);
 471
 678472            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 473
 678474            Environment.i.world.blockersController.SetupWorldBlockers();
 475
 678476            OnReadyScene?.Invoke(sceneId);
 7477        }
 478
 14479        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 480
 8481        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 482
 483        private void SetPositionDirty(DCLCharacterPosition character)
 484        {
 1751485            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 1751486            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 487
 1751488            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 489
 1751490            if (positionDirty)
 491            {
 357492                sceneSortDirty = true;
 357493                currentGridSceneCoordinate.x = currentX;
 357494                currentGridSceneCoordinate.y = currentY;
 495
 496                // Since the first position for the character is not sent from Kernel until just-before calling
 497                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 498                // to lock the rendering accordingly...
 357499                if (!CommonScriptableObjects.rendererState.Get())
 500                {
 1501                    SortScenesByDistance();
 502                }
 503            }
 1751504        }
 505
 506        public void SortScenesByDistance()
 507        {
 831508            if (DCLCharacterController.i == null)
 0509                return;
 510
 831511            IWorldState worldState = Environment.i.world.state;
 512
 831513            worldState.currentSceneId = null;
 831514            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 515
 831516            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 517            {
 518                IParcelScene scene;
 519                bool characterIsInsideScene;
 520
 1472521                while (iterator.MoveNext())
 522                {
 799523                    scene = iterator.Current;
 524
 799525                    if (scene == null)
 526                        continue;
 527
 799528                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 529
 799530                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 531                    {
 158532                        worldState.currentSceneId = scene.sceneData.id;
 158533                        break;
 534                    }
 535                }
 673536            }
 537
 831538            if (!DataStore.i.debugConfig.isDebugMode && string.IsNullOrEmpty(worldState.currentSceneId))
 539            {
 540                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 645541                CommonScriptableObjects.rendererState.AddLock(this);
 645542            }
 543            else
 544            {
 545                // 1. Set current scene id
 186546                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 547
 548                // 2. Attempt to remove SceneController's lock on rendering
 186549                CommonScriptableObjects.rendererState.RemoveLock(this);
 550            }
 551
 831552            OnSortScenes?.Invoke();
 815553        }
 554
 555        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 556        {
 60557            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 60558            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 559
 60560            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 60561            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 562
 60563            return dist1 - dist2;
 564        }
 565
 566        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 567        {
 7277568            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 569                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 570            {
 0571                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 572
 0573                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 574            }
 7277575        }
 576
 577        public void LoadParcelScenesExecute(string scenePayload)
 578        {
 579            LoadParcelScenesMessage.UnityParcelScene scene;
 580
 27581            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 27582            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 27583            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 584
 27585            if (scene == null || scene.id == null)
 0586                return;
 587
 27588            var sceneToLoad = scene;
 589
 590
 27591            DebugConfig debugConfig = DataStore.i.debugConfig;
 592#if UNITY_EDITOR
 27593            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 594            {
 0595                SendSceneReady(sceneToLoad.id);
 0596                return;
 597            }
 598#endif
 599
 27600            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 601
 27602            IWorldState worldState = Environment.i.world.state;
 603
 27604            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 605            {
 27606                var newGameObject = new GameObject("New Scene");
 607
 27608                var newScene = newGameObject.AddComponent<ParcelScene>();
 27609                newScene.SetData(sceneToLoad);
 610
 27611                if (debugConfig.isDebugMode)
 612                {
 27613                    newScene.InitializeDebugPlane();
 614                }
 615
 27616                newScene.ownerController = this;
 27617                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 27618                worldState.scenesSortedByDistance.Add(newScene);
 619
 27620                sceneSortDirty = true;
 621
 27622                OnNewSceneAdded?.Invoke(newScene);
 623
 27624                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 625
 27626                if (VERBOSE)
 0627                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 628            }
 629
 27630            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0631        }
 632
 633        public void UpdateParcelScenesExecute(string sceneId)
 634        {
 635            LoadParcelScenesMessage.UnityParcelScene sceneData;
 636
 0637            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0638            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0639            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 640
 0641            IWorldState worldState = Environment.i.world.state;
 642
 0643            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 644            {
 0645                ParcelScene scene = sceneInterface as ParcelScene;
 0646                scene.SetUpdateData(sceneData);
 0647            }
 648            else
 649            {
 0650                LoadParcelScenesExecute(sceneId);
 651            }
 0652        }
 653
 654        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 655        {
 16656            if (scene == null || scene.id == null)
 0657                return;
 658
 16659            var sceneToLoad = scene;
 660
 16661            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 662
 16663            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 664
 16665            if (parcelScene != null)
 16666                parcelScene.SetUpdateData(sceneToLoad);
 667
 16668            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0669        }
 670
 671        public void UnloadScene(string sceneKey)
 672        {
 1673            var queuedMessage = new QueuedSceneMessage()
 674                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 675
 1676            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 677
 1678            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 679
 1680            Environment.i.messaging.manager.RemoveController(sceneKey);
 681
 1682            IWorldState worldState = Environment.i.world.state;
 683
 1684            if (worldState.loadedScenes.ContainsKey(sceneKey))
 685            {
 1686                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1687                sceneToUnload.isPersistent = false;
 688
 1689                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0690                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 691            }
 1692        }
 693
 694        public void UnloadParcelSceneExecute(string sceneId)
 695        {
 719696            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 697
 719698            IWorldState worldState = Environment.i.world.state;
 699
 719700            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 701            {
 1702                return;
 703            }
 704
 718705            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 706
 718707            if (scene == null)
 0708                return;
 709
 718710            worldState.loadedScenes.Remove(sceneId);
 718711            worldState.globalSceneIds.Remove(sceneId);
 712
 713            // Remove the scene id from the msg. priorities list
 718714            worldState.scenesSortedByDistance.Remove(scene);
 715
 716            // Remove messaging controller for unloaded scene
 718717            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 718
 718719            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 720
 718721            if (VERBOSE)
 722            {
 0723                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 724            }
 725
 718726            Environment.i.world.blockersController.SetupWorldBlockers();
 727
 718728            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0729        }
 730
 731        public void UnloadAllScenes(bool includePersistent = false)
 732        {
 705733            var worldState = Environment.i.world.state;
 734
 705735            if (includePersistent)
 736            {
 1420737                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 738
 2790739                foreach (var kvp in persistentScenes)
 740                {
 691741                    if (kvp.Value is ParcelScene scene)
 742                    {
 691743                        scene.isPersistent = false;
 744                    }
 745                }
 746            }
 747
 705748            var list = worldState.loadedScenes.ToArray();
 749
 2846750            for (int i = 0; i < list.Length; i++)
 751            {
 718752                UnloadParcelSceneExecute(list[i].Key);
 753            }
 705754        }
 755
 756        public void LoadParcelScenes(string decentralandSceneJSON)
 757        {
 27758            var queuedMessage = new QueuedSceneMessage()
 759            {
 760                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 761                message = decentralandSceneJSON
 762            };
 763
 27764            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 765
 27766            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 767
 27768            if (VERBOSE)
 0769                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 27770        }
 771
 772        public void UpdateParcelScenes(string decentralandSceneJSON)
 773        {
 0774            var queuedMessage = new QueuedSceneMessage()
 775                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 776
 0777            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 778
 0779            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0780        }
 781
 782        public void UnloadAllScenesQueued()
 783        {
 0784            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 785
 0786            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 787
 0788            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0789        }
 790
 791        public void CreateGlobalScene(string json)
 792        {
 793#if UNITY_EDITOR
 21794            DebugConfig debugConfig = DataStore.i.debugConfig;
 795
 21796            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0797                return;
 798#endif
 21799            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 800
 21801            string newGlobalSceneId = globalScene.id;
 802
 21803            IWorldState worldState = Environment.i.world.state;
 804
 21805            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0806                return;
 807
 21808            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 809
 21810            var newScene = newGameObject.AddComponent<GlobalScene>();
 21811            newScene.ownerController = this;
 21812            newScene.unloadWithDistance = false;
 21813            newScene.isPersistent = true;
 21814            newScene.sceneName = globalScene.name;
 21815            newScene.isPortableExperience = globalScene.isPortableExperience;
 816
 21817            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 818            {
 819                id = newGlobalSceneId,
 820                basePosition = new Vector2Int(0, 0),
 821                baseUrl = globalScene.baseUrl,
 822                contents = globalScene.contents
 823            };
 824
 21825            newScene.SetData(data);
 826
 21827            if (!string.IsNullOrEmpty(globalScene.icon))
 0828                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 829
 21830            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 21831            OnNewSceneAdded?.Invoke(newScene);
 832
 21833            if (newScene.isPortableExperience)
 0834                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 835
 21836            worldState.globalSceneIds.Add(newGlobalSceneId);
 837
 21838            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 839
 21840            if (VERBOSE)
 841            {
 0842                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 843            }
 21844        }
 845
 846        public void IsolateScene(IParcelScene sceneToActive)
 847        {
 196848            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 849            {
 49850                if (scene != sceneToActive)
 0851                    scene.GetSceneTransform().gameObject.SetActive(false);
 852            }
 49853        }
 854
 855        public void ReIntegrateIsolatedScene()
 856        {
 28857            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 858            {
 7859                scene.GetSceneTransform().gameObject.SetActive(true);
 860            }
 7861        }
 862
 863        //======================================================================
 864
 865        #endregion
 866
 867        //======================================================================
 868
 682869        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 870
 1339871        public bool prewarmSceneMessagesPool { get; set; } = true;
 1339872        public bool prewarmEntitiesPool { get; set; } = true;
 873
 874        private bool sceneSortDirty = false;
 682875        private bool positionDirty = true;
 876        private int lastSortFrame = 0;
 877
 878        public event Action OnSortScenes;
 879        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 880        public event Action<IParcelScene> OnNewSceneAdded;
 881        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 882        public event Action<string> OnNewPortableExperienceSceneRemoved;
 883
 682884        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 682885        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 886
 887        public const string EMPTY_GO_POOL_NAME = "Empty";
 888    }
 889}

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)