< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:191
Uncovered lines:166
Coverable lines:357
Total lines:860
Line coverage:53.5% (191 of 357)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneController()0%110100%
Initialize()0%22093.75%
OnDebugModeSet(...)0%3.713057.14%
Start()0%20400%
Dispose()0%22090%
Update()0%440100%
LateUpdate()0%220100%
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%6200%
SendSceneReady(...)0%220100%
ActivateBuilderInWorldEditScene()0%110100%
DeactivateBuilderInWorldEditScene()0%110100%
SetPositionDirty(...)0%4.024090%
SortScenesByDistance()0%880100%
SortScenesByDistanceMethod(...)0%110100%
OnCurrentSceneIdChange(...)0%64050%
LoadParcelScenesExecute(...)0%14.0713081.48%
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%13.311073.33%
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
 69520        public bool enabled { get; set; } = true;
 21
 22        private Coroutine deferredDecodingCoroutine;
 23
 24        public void Initialize()
 25        {
 67226            sceneSortDirty = true;
 67227            positionDirty = true;
 67228            lastSortFrame = 0;
 67229            enabled = true;
 30
 67231            DataStore.i.debugConfig.isDebugMode.OnChange += OnDebugModeSet;
 32
 67233            if (deferredMessagesDecoding) // We should be able to delete this code
 034                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding()); //
 35
 67236            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 37
 67238            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 39
 40            //TODO(Brian): Move those subscriptions elsewhere.
 67241            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 67242            PoolManager.i.OnGet += Environment.i.platform.physicsSyncController.MarkDirty;
 43
 67244            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 67245            PoolManager.i.OnGet += Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 46
 67247            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 67248            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.LateUpdate, LateUpda
 67249        }
 50
 51        private void OnDebugModeSet(bool current, bool previous)
 52        {
 953            if (current == previous)
 054                return;
 55
 956            if (current)
 57            {
 958                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedFlicker());
 959            }
 60            else
 61            {
 062                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_Simple());
 63            }
 064        }
 65
 66        public void Start()
 67        {
 068            if (prewarmSceneMessagesPool)
 69            {
 070                for (int i = 0; i < 100000; i++)
 71                {
 072                    sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 73                }
 74            }
 75
 076            if (prewarmEntitiesPool)
 77            {
 078                PoolManagerFactory.EnsureEntityPool(prewarmEntitiesPool);
 79            }
 080        }
 81
 82        public void Dispose()
 83        {
 67784            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 67785            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 67786            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 67787            DataStore.i.debugConfig.isDebugMode.OnChange -= OnDebugModeSet;
 88
 67789            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 67790            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.LateUpdate, LateU
 91
 67792            UnloadAllScenes(includePersistent: true);
 93
 67794            if (deferredDecodingCoroutine != null)
 095                CoroutineStarter.Stop(deferredDecodingCoroutine);
 67796        }
 97
 98        public void Update()
 99        {
 11458100            if (!enabled)
 295101                return;
 102
 11163103            InputController_Legacy.i.Update();
 104
 11163105            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 106            {
 667107                lastSortFrame = Time.frameCount;
 667108                sceneSortDirty = false;
 667109                SortScenesByDistance();
 110            }
 11163111        }
 112
 113        public void LateUpdate()
 114        {
 11458115            if (!enabled)
 295116                return;
 117
 11163118            Environment.i.platform.physicsSyncController.Sync();
 11163119        }
 120
 121        //======================================================================
 122
 123        #region MESSAGES_HANDLING
 124
 125        //======================================================================
 126
 127#if UNITY_EDITOR
 128        public delegate void ProcessDelegate(string sceneId, string method);
 129
 130        public event ProcessDelegate OnMessageProcessInfoStart;
 131        public event ProcessDelegate OnMessageProcessInfoEnds;
 132#endif
 597133        public bool deferredMessagesDecoding { get; set; } = false;
 134
 672135        Queue<string> payloadsToDecode = new Queue<string>();
 136        const float MAX_TIME_FOR_DECODE = 0.005f;
 137
 138        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 139        {
 0140            string sceneId = msgObject.sceneId;
 0141            string method = msgObject.method;
 142
 0143            yieldInstruction = null;
 144
 145            IParcelScene scene;
 0146            bool res = false;
 0147            IWorldState worldState = Environment.i.world.state;
 0148            DebugConfig debugConfig = DataStore.i.debugConfig;
 149
 0150            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 151            {
 152#if UNITY_EDITOR
 0153                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 154                {
 0155                    return false;
 156                }
 157#endif
 0158                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 159                {
 0160                    return true;
 161                }
 162
 163#if UNITY_EDITOR
 0164                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 165#endif
 0166                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 167
 0168                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 169
 0170                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 171
 172#if UNITY_EDITOR
 0173                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 174#endif
 175
 0176                res = true;
 0177            }
 178
 179            else
 180            {
 0181                res = false;
 182            }
 183
 0184            sceneMessagesPool.Enqueue(msgObject);
 185
 0186            return res;
 187        }
 188
 189        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 190            out CustomYieldInstruction yieldInstruction)
 191        {
 0192            yieldInstruction = null;
 0193            IDelayedComponent delayedComponent = null;
 194
 195            try
 196            {
 197                switch (method)
 198                {
 199                    case MessagingTypes.ENTITY_CREATE:
 200                        {
 0201                            if (msgPayload is Protocol.CreateEntity payload)
 0202                                scene.CreateEntity(payload.entityId);
 203
 0204                            break;
 205                        }
 206                    case MessagingTypes.ENTITY_REPARENT:
 207                        {
 0208                            if (msgPayload is Protocol.SetEntityParent payload)
 0209                                scene.SetEntityParent(payload.entityId, payload.parentId);
 210
 0211                            break;
 212                        }
 213
 214                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 215                        {
 0216                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 217                            {
 0218                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 219                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 220                            }
 221
 0222                            break;
 223                        }
 224
 225                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 226                        {
 0227                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0228                                scene.EntityComponentRemove(payload.entityId, payload.name);
 229
 0230                            break;
 231                        }
 232
 233                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 234                        {
 0235                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0236                                scene.SharedComponentAttach(payload.entityId, payload.id);
 237
 0238                            break;
 239                        }
 240
 241                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 242                        {
 0243                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0244                                scene.SharedComponentCreate(payload.id, payload.classId);
 245
 0246                            break;
 247                        }
 248
 249                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 250                        {
 0251                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0252                                scene.SharedComponentDispose(payload.id);
 0253                            break;
 254                        }
 255
 256                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 257                        {
 0258                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0259                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 260
 0261                            break;
 262                        }
 263
 264                    case MessagingTypes.ENTITY_DESTROY:
 265                        {
 0266                            if (msgPayload is Protocol.RemoveEntity payload)
 0267                                scene.RemoveEntity(payload.entityId);
 0268                            break;
 269                        }
 270
 271                    case MessagingTypes.INIT_DONE:
 272                        {
 0273                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0274                            break;
 275                        }
 276
 277                    case MessagingTypes.QUERY:
 278                        {
 0279                            if (msgPayload is QueryMessage queryMessage)
 0280                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0281                            break;
 282                        }
 283
 284                    case MessagingTypes.OPEN_EXTERNAL_URL:
 285                        {
 0286                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0287                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0288                            break;
 289                        }
 290
 291                    case MessagingTypes.OPEN_NFT_DIALOG:
 292                        {
 0293                            if (msgPayload is Protocol.OpenNftDialog payload)
 0294                                DataStore.i.common.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payloa
 295                                    payload.comment), true);
 0296                            break;
 297                        }
 298
 299                    default:
 0300                        Debug.LogError($"Unknown method {method}");
 301                        break;
 302                }
 0303            }
 0304            catch (Exception e)
 305            {
 0306                throw new Exception(
 307                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 308            }
 309
 0310            if (delayedComponent != null)
 311            {
 0312                if (delayedComponent.isRoutineRunning)
 0313                    yieldInstruction = delayedComponent.yieldInstruction;
 314            }
 0315        }
 316
 317        public void ParseQuery(object payload, string sceneId)
 318        {
 0319            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 320
 0321            if (!(payload is RaycastQuery raycastQuery))
 0322                return;
 323
 0324            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 325
 0326            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0327            raycastQuery.sceneId = sceneId;
 0328            PhysicsCast.i.Query(raycastQuery);
 0329        }
 330
 0331        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 332
 333        private void SendSceneMessage(string payload, bool enqueue)
 334        {
 0335            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0336            int count = chunks.Length;
 337
 0338            for (int i = 0; i < count; i++)
 339            {
 0340                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 341                {
 0342                    payloadsToDecode.Enqueue(chunks[i]);
 0343                }
 344                else
 345                {
 0346                    DecodeAndEnqueue(chunks[i]);
 347                }
 348            }
 0349        }
 350
 351        private void DecodeAndEnqueue(string payload)
 352        {
 0353            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 354
 355            string sceneId;
 356            string message;
 357            string messageTag;
 358            PB_SendSceneMessage sendSceneMessage;
 359
 0360            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 361            {
 0362                return;
 363            }
 364
 365            QueuedSceneMessage_Scene queuedMessage;
 366
 0367            if (sceneMessagesPool.Count > 0)
 0368                queuedMessage = sceneMessagesPool.Dequeue();
 369            else
 0370                queuedMessage = new QueuedSceneMessage_Scene();
 371
 0372            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 373
 0374            EnqueueSceneMessage(queuedMessage);
 375
 0376            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0377        }
 378
 379        private IEnumerator DeferredDecoding()
 380        {
 0381            float start = Time.realtimeSinceStartup;
 382            float maxTimeForDecode;
 383
 0384            while (true)
 385            {
 0386                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 387
 0388                if (payloadsToDecode.Count > 0)
 389                {
 0390                    string payload = payloadsToDecode.Dequeue();
 391
 0392                    DecodeAndEnqueue(payload);
 393
 0394                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 395                        continue;
 396                }
 397
 0398                yield return null;
 0399                start = Time.unscaledTime;
 400            }
 401        }
 402
 403        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 404        {
 0405            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0406            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0407            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0408        }
 409
 410        //======================================================================
 411
 412        #endregion
 413
 414        //======================================================================
 415
 416        //======================================================================
 417
 418        #region SCENES_MANAGEMENT
 419
 420        //======================================================================
 421        public event Action<string> OnReadyScene;
 422
 423        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 424        {
 0425            IParcelScene result = WorldStateUtils.CreateTestScene(data);
 0426            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 0427            OnNewSceneAdded?.Invoke(result);
 0428            return result;
 429        }
 430
 431        public void SendSceneReady(string sceneId)
 432        {
 398433            Environment.i.world.state.readyScenes.Add(sceneId);
 434
 398435            Environment.i.messaging.manager.SetSceneReady(sceneId);
 436
 398437            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 398438            WebInterface.ReportCameraChanged(CommonScriptableObjects.cameraMode.Get(), sceneId);
 439
 398440            Environment.i.world.blockersController.SetupWorldBlockers();
 441
 398442            OnReadyScene?.Invoke(sceneId);
 2443        }
 444
 10445        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 446
 2447        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 448
 449        private void SetPositionDirty(DCLCharacterPosition character)
 450        {
 8244451            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 8244452            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 453
 8244454            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 455
 8244456            if (positionDirty)
 457            {
 596458                sceneSortDirty = true;
 596459                currentGridSceneCoordinate.x = currentX;
 596460                currentGridSceneCoordinate.y = currentY;
 461
 462                // Since the first position for the character is not sent from Kernel until just-before calling
 463                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 464                // to lock the rendering accordingly...
 596465                if (!CommonScriptableObjects.rendererState.Get())
 466                {
 0467                    SortScenesByDistance();
 468                }
 469            }
 8244470        }
 471
 472        public void SortScenesByDistance()
 473        {
 667474            if (DCLCharacterController.i == null)
 64475                return;
 476
 603477            IWorldState worldState = Environment.i.world.state;
 478
 603479            worldState.currentSceneId = null;
 603480            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 481
 603482            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 483            {
 484                IParcelScene scene;
 485                bool characterIsInsideScene;
 486
 624487                while (iterator.MoveNext())
 488                {
 26489                    scene = iterator.Current;
 490
 26491                    if (scene == null)
 492                        continue;
 493
 26494                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 495
 26496                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 497                    {
 5498                        worldState.currentSceneId = scene.sceneData.id;
 5499                        break;
 500                    }
 501                }
 598502            }
 503
 603504            if (!DataStore.i.debugConfig.isDebugMode.Get() && string.IsNullOrEmpty(worldState.currentSceneId))
 505            {
 506                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 595507                CommonScriptableObjects.rendererState.AddLock(this);
 595508            }
 509            else
 510            {
 511                // 1. Set current scene id
 8512                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 513
 514                // 2. Attempt to remove SceneController's lock on rendering
 8515                CommonScriptableObjects.rendererState.RemoveLock(this);
 516            }
 517
 603518            OnSortScenes?.Invoke();
 603519        }
 520
 521        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 522        {
 22523            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 22524            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 525
 22526            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 22527            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 528
 22529            return dist1 - dist2;
 530        }
 531
 532        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 533        {
 6031534            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 535                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 536            {
 0537                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 538
 0539                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 540            }
 6031541        }
 542
 543        public void LoadParcelScenesExecute(string scenePayload)
 544        {
 545            LoadParcelScenesMessage.UnityParcelScene scene;
 546
 26547            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 26548            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 26549            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 550
 26551            if (scene == null || scene.id == null)
 0552                return;
 553
 26554            var sceneToLoad = scene;
 555
 556
 26557            DebugConfig debugConfig = DataStore.i.debugConfig;
 558#if UNITY_EDITOR
 26559            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 560            {
 0561                SendSceneReady(sceneToLoad.id);
 0562                return;
 563            }
 564#endif
 565
 26566            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 567
 26568            IWorldState worldState = Environment.i.world.state;
 569
 26570            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 571            {
 26572                var newGameObject = new GameObject("New Scene");
 573
 26574                var newScene = newGameObject.AddComponent<ParcelScene>();
 26575                newScene.SetData(sceneToLoad);
 576
 26577                if (debugConfig.isDebugMode.Get())
 578                {
 26579                    newScene.InitializeDebugPlane();
 580                }
 581
 26582                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 26583                worldState.scenesSortedByDistance.Add(newScene);
 584
 26585                sceneSortDirty = true;
 586
 26587                OnNewSceneAdded?.Invoke(newScene);
 588
 26589                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 590
 26591                if (VERBOSE)
 0592                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 593            }
 594
 26595            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0596        }
 597
 598        public void UpdateParcelScenesExecute(string sceneId)
 599        {
 600            LoadParcelScenesMessage.UnityParcelScene sceneData;
 601
 0602            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0603            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0604            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 605
 0606            IWorldState worldState = Environment.i.world.state;
 607
 0608            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 609            {
 0610                ParcelScene scene = sceneInterface as ParcelScene;
 0611                scene.SetUpdateData(sceneData);
 0612            }
 613            else
 614            {
 0615                LoadParcelScenesExecute(sceneId);
 616            }
 0617        }
 618
 619        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 620        {
 15621            if (scene == null || scene.id == null)
 0622                return;
 623
 15624            var sceneToLoad = scene;
 625
 15626            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 627
 15628            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 629
 15630            if (parcelScene != null)
 15631                parcelScene.SetUpdateData(sceneToLoad);
 632
 15633            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0634        }
 635
 636        public void UnloadScene(string sceneKey)
 637        {
 1638            var queuedMessage = new QueuedSceneMessage()
 639                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 640
 1641            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 642
 1643            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 644
 1645            Environment.i.messaging.manager.RemoveController(sceneKey);
 646
 1647            IWorldState worldState = Environment.i.world.state;
 648
 1649            if (worldState.loadedScenes.ContainsKey(sceneKey))
 650            {
 1651                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1652                sceneToUnload.isPersistent = false;
 653
 1654                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0655                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 656            }
 1657        }
 658
 659        public void UnloadParcelSceneExecute(string sceneId)
 660        {
 423661            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 662
 423663            IWorldState worldState = Environment.i.world.state;
 664
 423665            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 666            {
 1667                return;
 668            }
 669
 422670            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 671
 422672            if (scene == null)
 0673                return;
 674
 422675            worldState.loadedScenes.Remove(sceneId);
 422676            worldState.globalSceneIds.Remove(sceneId);
 677
 678            // Remove the scene id from the msg. priorities list
 422679            worldState.scenesSortedByDistance.Remove(scene);
 680
 681            // Remove messaging controller for unloaded scene
 422682            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 683
 422684            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 685
 422686            if (VERBOSE)
 687            {
 0688                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 689            }
 690
 422691            Environment.i.world.blockersController.SetupWorldBlockers();
 692
 422693            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0694        }
 695
 696        public void UnloadAllScenes(bool includePersistent = false)
 697        {
 680698            var worldState = Environment.i.world.state;
 699
 680700            if (includePersistent)
 701            {
 1100702                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 703
 2150704                foreach (var kvp in persistentScenes)
 705                {
 396706                    if (kvp.Value is ParcelScene scene)
 707                    {
 396708                        scene.isPersistent = false;
 709                    }
 710                }
 711            }
 712
 680713            var list = worldState.loadedScenes.ToArray();
 714
 2204715            for (int i = 0; i < list.Length; i++)
 716            {
 422717                UnloadParcelSceneExecute(list[i].Key);
 718            }
 680719        }
 720
 721        public void LoadParcelScenes(string decentralandSceneJSON)
 722        {
 26723            var queuedMessage = new QueuedSceneMessage()
 724            {
 725                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 726                message = decentralandSceneJSON
 727            };
 728
 26729            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 730
 26731            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 732
 26733            if (VERBOSE)
 0734                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 26735        }
 736
 737        public void UpdateParcelScenes(string decentralandSceneJSON)
 738        {
 0739            var queuedMessage = new QueuedSceneMessage()
 740                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 741
 0742            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 743
 0744            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0745        }
 746
 747        public void UnloadAllScenesQueued()
 748        {
 0749            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 750
 0751            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 752
 0753            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0754        }
 755
 756        public void CreateGlobalScene(string json)
 757        {
 758#if UNITY_EDITOR
 1759            DebugConfig debugConfig = DataStore.i.debugConfig;
 760
 1761            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0762                return;
 763#endif
 1764            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 765
 1766            string newGlobalSceneId = globalScene.id;
 767
 1768            IWorldState worldState = Environment.i.world.state;
 769
 1770            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0771                return;
 772
 1773            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 774
 1775            var newScene = newGameObject.AddComponent<GlobalScene>();
 1776            newScene.unloadWithDistance = false;
 1777            newScene.isPersistent = true;
 1778            newScene.sceneName = globalScene.name;
 1779            newScene.isPortableExperience = globalScene.isPortableExperience;
 780
 1781            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 782            {
 783                id = newGlobalSceneId,
 784                basePosition = new Vector2Int(0, 0),
 785                baseUrl = globalScene.baseUrl,
 786                contents = globalScene.contents
 787            };
 788
 1789            newScene.SetData(data);
 790
 1791            if (!string.IsNullOrEmpty(globalScene.icon))
 792            {
 0793                if (globalScene.icon.StartsWith("http://") || globalScene.icon.StartsWith("https://"))
 794                {
 0795                    newScene.iconUrl = globalScene.icon;
 0796                }
 797                else
 798                {
 0799                    newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 800                }
 801            }
 802
 1803            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 1804            OnNewSceneAdded?.Invoke(newScene);
 805
 1806            if (newScene.isPortableExperience)
 0807                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 808
 1809            worldState.globalSceneIds.Add(newGlobalSceneId);
 810
 1811            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 812
 1813            if (VERBOSE)
 814            {
 0815                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 816            }
 1817        }
 818
 819        public void IsolateScene(IParcelScene sceneToActive)
 820        {
 152821            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 822            {
 38823                if (scene != sceneToActive)
 0824                    scene.GetSceneTransform().gameObject.SetActive(false);
 825            }
 38826        }
 827
 828        public void ReIntegrateIsolatedScene()
 829        {
 20830            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 831            {
 5832                scene.GetSceneTransform().gameObject.SetActive(true);
 833            }
 5834        }
 835
 836        //======================================================================
 837
 838        #endregion
 839
 840        //======================================================================
 841
 672842        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 843
 1269844        public bool prewarmSceneMessagesPool { get; set; } = true;
 1269845        public bool prewarmEntitiesPool { get; set; } = true;
 846
 847        private bool sceneSortDirty = false;
 672848        private bool positionDirty = true;
 849        private int lastSortFrame = 0;
 850
 851        public event Action OnSortScenes;
 852        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 853        public event Action<IParcelScene> OnNewSceneAdded;
 854        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 855        public event Action<string> OnNewPortableExperienceSceneRemoved;
 856
 672857        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 672858        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 859    }
 860}

Methods/Properties

enabled()
enabled(System.Boolean)
SceneController()
Initialize()
OnDebugModeSet(System.Boolean, System.Boolean)
Start()
Dispose()
Update()
LateUpdate()
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)