< 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:165
Coverable lines:356
Total lines:863
Line coverage:53.6% (191 of 356)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneController()0%110100%
Initialize()0%7.996061.9%
OnDebugModeSet(...)0%3.713057.14%
Dispose()0%22091.67%
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%12.0711079.31%
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        const int SCENE_MESSAGES_PREWARM_COUNT = 100000;
 20
 67521        public bool enabled { get; set; } = true;
 022        internal BaseVariable<Transform> isPortableExperiencesInitialized => DataStore.i.experiencesViewer.isInitialized
 23
 24        //TODO(Brian): Move to WorldRuntimePlugin later
 25        private LoadingFeedbackController loadingFeedbackController;
 26
 27        private Coroutine deferredDecodingCoroutine;
 28
 29        public void Initialize()
 30        {
 65231            sceneSortDirty = true;
 65232            positionDirty = true;
 65233            lastSortFrame = 0;
 65234            enabled = true;
 35
 65236            loadingFeedbackController = new LoadingFeedbackController();
 37
 65238            DataStore.i.debugConfig.isDebugMode.OnChange += OnDebugModeSet;
 39
 65240            if (deferredMessagesDecoding) // We should be able to delete this code
 041                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding());
 42
 65243            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 44
 65245            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 46
 47            // TODO(Brian): Move this later to Main.cs
 65248            if ( !EnvironmentSettings.RUNNING_TESTS )
 49            {
 050                if (prewarmSceneMessagesPool)
 51                {
 052                    for (int i = 0; i < SCENE_MESSAGES_PREWARM_COUNT; i++)
 53                    {
 054                        sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 55                    }
 56                }
 57
 058                if (prewarmEntitiesPool)
 59                {
 060                    PoolManagerFactory.EnsureEntityPool(prewarmEntitiesPool);
 61                }
 62            }
 63
 65264            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 65265            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.LateUpdate, LateUpda
 65266        }
 67
 68        private void OnDebugModeSet(bool current, bool previous)
 69        {
 970            if (current == previous)
 071                return;
 72
 973            if (current)
 74            {
 975                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedBox());
 976            }
 77            else
 78            {
 079                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_Simple());
 80            }
 081        }
 82
 83        public void Dispose()
 84        {
 65285            loadingFeedbackController.Dispose();
 86
 65287            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 65288            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.LateUpdate, LateU
 89
 65290            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 65291            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 92
 65293            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 65294            DataStore.i.debugConfig.isDebugMode.OnChange -= OnDebugModeSet;
 95
 65296            CommonScriptableObjects.sceneID.OnChange -= OnCurrentSceneIdChange;
 97
 65298            UnloadAllScenes(includePersistent: true);
 99
 652100            if (deferredDecodingCoroutine != null)
 0101                CoroutineStarter.Stop(deferredDecodingCoroutine);
 652102        }
 103
 104        public void Update()
 105        {
 6941106            if (!enabled)
 161107                return;
 108
 6780109            InputController_Legacy.i.Update();
 110
 6780111            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 112            {
 648113                lastSortFrame = Time.frameCount;
 648114                sceneSortDirty = false;
 648115                SortScenesByDistance();
 116            }
 6780117        }
 118
 119        public void LateUpdate()
 120        {
 6941121            if (!enabled)
 161122                return;
 123
 6780124            Environment.i.platform.physicsSyncController.Sync();
 6780125        }
 126
 127        //======================================================================
 128
 129        #region MESSAGES_HANDLING
 130
 131        //======================================================================
 132
 133#if UNITY_EDITOR
 134        public delegate void ProcessDelegate(string sceneId, string method);
 135
 136        public event ProcessDelegate OnMessageProcessInfoStart;
 137        public event ProcessDelegate OnMessageProcessInfoEnds;
 138#endif
 0139        public bool deferredMessagesDecoding { get; set; } = false;
 140
 652141        Queue<string> payloadsToDecode = new Queue<string>();
 142        const float MAX_TIME_FOR_DECODE = 0.005f;
 143
 144        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 145        {
 0146            string sceneId = msgObject.sceneId;
 0147            string method = msgObject.method;
 148
 0149            yieldInstruction = null;
 150
 151            IParcelScene scene;
 0152            bool res = false;
 0153            IWorldState worldState = Environment.i.world.state;
 0154            DebugConfig debugConfig = DataStore.i.debugConfig;
 155
 0156            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 157            {
 158#if UNITY_EDITOR
 0159                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 160                {
 0161                    return false;
 162                }
 163#endif
 0164                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 165                {
 0166                    return true;
 167                }
 168
 169#if UNITY_EDITOR
 0170                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 171#endif
 0172                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 173
 0174                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 175
 0176                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 177
 178#if UNITY_EDITOR
 0179                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 180#endif
 181
 0182                res = true;
 0183            }
 184
 185            else
 186            {
 0187                res = false;
 188            }
 189
 0190            sceneMessagesPool.Enqueue(msgObject);
 191
 0192            return res;
 193        }
 194
 195        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 196            out CustomYieldInstruction yieldInstruction)
 197        {
 0198            yieldInstruction = null;
 0199            IDelayedComponent delayedComponent = null;
 200
 201            try
 202            {
 203                switch (method)
 204                {
 205                    case MessagingTypes.ENTITY_CREATE:
 206                        {
 0207                            if (msgPayload is Protocol.CreateEntity payload)
 0208                                scene.CreateEntity(payload.entityId);
 209
 0210                            break;
 211                        }
 212                    case MessagingTypes.ENTITY_REPARENT:
 213                        {
 0214                            if (msgPayload is Protocol.SetEntityParent payload)
 0215                                scene.SetEntityParent(payload.entityId, payload.parentId);
 216
 0217                            break;
 218                        }
 219
 220                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 221                        {
 0222                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 223                            {
 0224                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 225                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 226                            }
 227
 0228                            break;
 229                        }
 230
 231                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 232                        {
 0233                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0234                                scene.EntityComponentRemove(payload.entityId, payload.name);
 235
 0236                            break;
 237                        }
 238
 239                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 240                        {
 0241                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0242                                scene.SharedComponentAttach(payload.entityId, payload.id);
 243
 0244                            break;
 245                        }
 246
 247                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 248                        {
 0249                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0250                                scene.SharedComponentCreate(payload.id, payload.classId);
 251
 0252                            break;
 253                        }
 254
 255                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 256                        {
 0257                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0258                                scene.SharedComponentDispose(payload.id);
 0259                            break;
 260                        }
 261
 262                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 263                        {
 0264                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0265                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 266
 0267                            break;
 268                        }
 269
 270                    case MessagingTypes.ENTITY_DESTROY:
 271                        {
 0272                            if (msgPayload is Protocol.RemoveEntity payload)
 0273                                scene.RemoveEntity(payload.entityId);
 0274                            break;
 275                        }
 276
 277                    case MessagingTypes.INIT_DONE:
 278                        {
 0279                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0280                            break;
 281                        }
 282
 283                    case MessagingTypes.QUERY:
 284                        {
 0285                            if (msgPayload is QueryMessage queryMessage)
 0286                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0287                            break;
 288                        }
 289
 290                    case MessagingTypes.OPEN_EXTERNAL_URL:
 291                        {
 0292                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0293                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0294                            break;
 295                        }
 296
 297                    case MessagingTypes.OPEN_NFT_DIALOG:
 298                        {
 0299                            if (msgPayload is Protocol.OpenNftDialog payload)
 0300                                DataStore.i.common.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payloa
 301                                    payload.comment), true);
 0302                            break;
 303                        }
 304
 305                    default:
 0306                        Debug.LogError($"Unknown method {method}");
 307                        break;
 308                }
 0309            }
 0310            catch (Exception e)
 311            {
 0312                throw new Exception(
 313                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 314            }
 315
 0316            if (delayedComponent != null)
 317            {
 0318                if (delayedComponent.isRoutineRunning)
 0319                    yieldInstruction = delayedComponent.yieldInstruction;
 320            }
 0321        }
 322
 323        public void ParseQuery(object payload, string sceneId)
 324        {
 0325            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 326
 0327            if (!(payload is RaycastQuery raycastQuery))
 0328                return;
 329
 0330            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 331
 0332            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0333            raycastQuery.sceneId = sceneId;
 0334            PhysicsCast.i.Query(raycastQuery);
 0335        }
 336
 0337        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 338
 339        private void SendSceneMessage(string payload, bool enqueue)
 340        {
 0341            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0342            int count = chunks.Length;
 343
 0344            for (int i = 0; i < count; i++)
 345            {
 0346                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 347                {
 0348                    payloadsToDecode.Enqueue(chunks[i]);
 0349                }
 350                else
 351                {
 0352                    DecodeAndEnqueue(chunks[i]);
 353                }
 354            }
 0355        }
 356
 357        private void DecodeAndEnqueue(string payload)
 358        {
 0359            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 360
 361            string sceneId;
 362            string message;
 363            string messageTag;
 364            PB_SendSceneMessage sendSceneMessage;
 365
 0366            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 367            {
 0368                return;
 369            }
 370
 371            QueuedSceneMessage_Scene queuedMessage;
 372
 0373            if (sceneMessagesPool.Count > 0)
 0374                queuedMessage = sceneMessagesPool.Dequeue();
 375            else
 0376                queuedMessage = new QueuedSceneMessage_Scene();
 377
 0378            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 379
 0380            EnqueueSceneMessage(queuedMessage);
 381
 0382            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0383        }
 384
 385        private IEnumerator DeferredDecoding()
 386        {
 0387            float start = Time.realtimeSinceStartup;
 388            float maxTimeForDecode;
 389
 0390            while (true)
 391            {
 0392                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 393
 0394                if (payloadsToDecode.Count > 0)
 395                {
 0396                    string payload = payloadsToDecode.Dequeue();
 397
 0398                    DecodeAndEnqueue(payload);
 399
 0400                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 401                        continue;
 402                }
 403
 0404                yield return null;
 0405                start = Time.unscaledTime;
 406            }
 407        }
 408
 409        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 410        {
 0411            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0412            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0413            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0414        }
 415
 416        //======================================================================
 417
 418        #endregion
 419
 420        //======================================================================
 421
 422        //======================================================================
 423
 424        #region SCENES_MANAGEMENT
 425
 426        //======================================================================
 427        public event Action<string> OnReadyScene;
 428
 429        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 430        {
 0431            IParcelScene result = WorldStateUtils.CreateTestScene(data);
 0432            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 0433            OnNewSceneAdded?.Invoke(result);
 0434            return result;
 435        }
 436
 437        public void SendSceneReady(string sceneId)
 438        {
 389439            Environment.i.world.state.readyScenes.Add(sceneId);
 440
 389441            Environment.i.messaging.manager.SetSceneReady(sceneId);
 442
 389443            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 389444            WebInterface.ReportCameraChanged(CommonScriptableObjects.cameraMode.Get(), sceneId);
 445
 389446            Environment.i.world.blockersController.SetupWorldBlockers();
 447
 389448            OnReadyScene?.Invoke(sceneId);
 2449        }
 450
 10451        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 452
 2453        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 454
 455        private void SetPositionDirty(DCLCharacterPosition character)
 456        {
 4972457            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 4972458            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 459
 4972460            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 461
 4972462            if (positionDirty)
 463            {
 578464                sceneSortDirty = true;
 578465                currentGridSceneCoordinate.x = currentX;
 578466                currentGridSceneCoordinate.y = currentY;
 467
 468                // Since the first position for the character is not sent from Kernel until just-before calling
 469                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 470                // to lock the rendering accordingly...
 578471                if (!CommonScriptableObjects.rendererState.Get())
 472                {
 0473                    SortScenesByDistance();
 474                }
 475            }
 4972476        }
 477
 478        public void SortScenesByDistance()
 479        {
 648480            if (DCLCharacterController.i == null)
 63481                return;
 482
 585483            IWorldState worldState = Environment.i.world.state;
 484
 585485            worldState.currentSceneId = null;
 585486            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 487
 585488            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 489            {
 490                IParcelScene scene;
 491                bool characterIsInsideScene;
 492
 604493                while (iterator.MoveNext())
 494                {
 24495                    scene = iterator.Current;
 496
 24497                    if (scene == null)
 498                        continue;
 499
 24500                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 501
 24502                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 503                    {
 5504                        worldState.currentSceneId = scene.sceneData.id;
 5505                        break;
 506                    }
 507                }
 580508            }
 509
 585510            if (!DataStore.i.debugConfig.isDebugMode.Get() && string.IsNullOrEmpty(worldState.currentSceneId))
 511            {
 512                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 577513                CommonScriptableObjects.rendererState.AddLock(this);
 577514            }
 515            else
 516            {
 517                // 1. Set current scene id
 8518                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 519
 520                // 2. Attempt to remove SceneController's lock on rendering
 8521                CommonScriptableObjects.rendererState.RemoveLock(this);
 522            }
 523
 585524            OnSortScenes?.Invoke();
 585525        }
 526
 527        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 528        {
 22529            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 22530            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 531
 22532            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 22533            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 534
 22535            return dist1 - dist2;
 536        }
 537
 538        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 539        {
 15540            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 541                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 542            {
 0543                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 544
 0545                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 546            }
 15547        }
 548
 549        public void LoadParcelScenesExecute(string scenePayload)
 550        {
 551            LoadParcelScenesMessage.UnityParcelScene scene;
 552
 26553            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 26554            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 26555            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 556
 26557            if (scene == null || scene.id == null)
 0558                return;
 559
 26560            var sceneToLoad = scene;
 561
 562
 26563            DebugConfig debugConfig = DataStore.i.debugConfig;
 564#if UNITY_EDITOR
 26565            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 566            {
 0567                SendSceneReady(sceneToLoad.id);
 0568                return;
 569            }
 570#endif
 571
 26572            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 573
 26574            IWorldState worldState = Environment.i.world.state;
 575
 26576            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 577            {
 26578                var newGameObject = new GameObject("New Scene");
 579
 26580                var newScene = newGameObject.AddComponent<ParcelScene>();
 26581                newScene.SetData(sceneToLoad);
 582
 26583                if (debugConfig.isDebugMode.Get())
 584                {
 26585                    newScene.InitializeDebugPlane();
 586                }
 587
 26588                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 26589                worldState.scenesSortedByDistance.Add(newScene);
 590
 26591                sceneSortDirty = true;
 592
 26593                OnNewSceneAdded?.Invoke(newScene);
 594
 26595                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 596
 26597                if (VERBOSE)
 0598                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 599            }
 600
 26601            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0602        }
 603
 604        public void UpdateParcelScenesExecute(string sceneId)
 605        {
 606            LoadParcelScenesMessage.UnityParcelScene sceneData;
 607
 0608            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0609            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0610            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 611
 0612            IWorldState worldState = Environment.i.world.state;
 613
 0614            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 615            {
 0616                ParcelScene scene = sceneInterface as ParcelScene;
 0617                scene.SetUpdateData(sceneData);
 0618            }
 619            else
 620            {
 0621                LoadParcelScenesExecute(sceneId);
 622            }
 0623        }
 624
 625        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 626        {
 15627            if (scene == null || scene.id == null)
 0628                return;
 629
 15630            var sceneToLoad = scene;
 631
 15632            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 633
 15634            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 635
 15636            if (parcelScene != null)
 15637                parcelScene.SetUpdateData(sceneToLoad);
 638
 15639            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0640        }
 641
 642        public void UnloadScene(string sceneKey)
 643        {
 1644            var queuedMessage = new QueuedSceneMessage()
 645                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 646
 1647            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 648
 1649            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 650
 1651            Environment.i.messaging.manager.RemoveController(sceneKey);
 652
 1653            IWorldState worldState = Environment.i.world.state;
 654
 1655            if (worldState.loadedScenes.ContainsKey(sceneKey))
 656            {
 1657                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1658                sceneToUnload.isPersistent = false;
 659
 1660                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0661                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 662            }
 1663        }
 664
 665        public void UnloadParcelSceneExecute(string sceneId)
 666        {
 413667            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 668
 413669            IWorldState worldState = Environment.i.world.state;
 670
 413671            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 672            {
 0673                return;
 674            }
 675
 413676            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 677
 413678            if (scene == null)
 9679                return;
 680
 404681            worldState.loadedScenes.Remove(sceneId);
 404682            worldState.globalSceneIds.Remove(sceneId);
 683
 684            // Remove the scene id from the msg. priorities list
 404685            worldState.scenesSortedByDistance.Remove(scene);
 686
 687            // Remove messaging controller for unloaded scene
 404688            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 689
 404690            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 691
 692
 404693            if (VERBOSE)
 694            {
 0695                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 696            }
 697
 404698            Environment.i.world.blockersController.SetupWorldBlockers();
 699
 404700            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0701        }
 702
 703        public void UnloadAllScenes(bool includePersistent = false)
 704        {
 654705            var worldState = Environment.i.world.state;
 706
 654707            if (includePersistent)
 708            {
 1066709                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 710
 2082711                foreach (var kvp in persistentScenes)
 712                {
 387713                    if (kvp.Value is ParcelScene scene)
 714                    {
 387715                        scene.isPersistent = false;
 716                    }
 717                }
 718            }
 719
 654720            var list = worldState.loadedScenes.ToArray();
 721
 2132722            for (int i = 0; i < list.Length; i++)
 723            {
 412724                UnloadParcelSceneExecute(list[i].Key);
 725            }
 654726        }
 727
 728        public void LoadParcelScenes(string decentralandSceneJSON)
 729        {
 26730            var queuedMessage = new QueuedSceneMessage()
 731            {
 732                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 733                message = decentralandSceneJSON
 734            };
 735
 26736            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 737
 26738            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 739
 26740            if (VERBOSE)
 0741                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 26742        }
 743
 744        public void UpdateParcelScenes(string decentralandSceneJSON)
 745        {
 0746            var queuedMessage = new QueuedSceneMessage()
 747                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 748
 0749            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 750
 0751            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0752        }
 753
 754        public void UnloadAllScenesQueued()
 755        {
 0756            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 757
 0758            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 759
 0760            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0761        }
 762
 763        public void CreateGlobalScene(string json)
 764        {
 765#if UNITY_EDITOR
 1766            DebugConfig debugConfig = DataStore.i.debugConfig;
 767
 1768            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0769                return;
 770#endif
 1771            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 772
 1773            if (globalScene.isPortableExperience && !isPortableExperiencesInitialized.Get())
 0774                return;
 775
 1776            string newGlobalSceneId = globalScene.id;
 777
 1778            IWorldState worldState = Environment.i.world.state;
 779
 1780            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0781                return;
 782
 1783            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 784
 1785            var newScene = newGameObject.AddComponent<GlobalScene>();
 1786            newScene.unloadWithDistance = false;
 1787            newScene.isPersistent = true;
 1788            newScene.sceneName = globalScene.name;
 1789            newScene.isPortableExperience = globalScene.isPortableExperience;
 790
 1791            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 792            {
 793                id = newGlobalSceneId,
 794                basePosition = new Vector2Int(0, 0),
 795                baseUrl = globalScene.baseUrl,
 796                contents = globalScene.contents
 797            };
 798
 1799            newScene.SetData(data);
 800
 1801            if (!string.IsNullOrEmpty(globalScene.icon))
 802            {
 0803                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 804            }
 805
 1806            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 1807            OnNewSceneAdded?.Invoke(newScene);
 808
 1809            if (newScene.isPortableExperience)
 0810                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 811
 1812            worldState.globalSceneIds.Add(newGlobalSceneId);
 813
 1814            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 815
 1816            if (VERBOSE)
 817            {
 0818                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 819            }
 1820        }
 821
 822        public void IsolateScene(IParcelScene sceneToActive)
 823        {
 152824            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 825            {
 38826                if (scene != sceneToActive)
 0827                    scene.GetSceneTransform().gameObject.SetActive(false);
 828            }
 38829        }
 830
 831        public void ReIntegrateIsolatedScene()
 832        {
 20833            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 834            {
 5835                scene.GetSceneTransform().gameObject.SetActive(true);
 836            }
 5837        }
 838
 839        //======================================================================
 840
 841        #endregion
 842
 843        //======================================================================
 844
 652845        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 846
 652847        public bool prewarmSceneMessagesPool { get; set; } = true;
 652848        public bool prewarmEntitiesPool { get; set; } = true;
 849
 850        private bool sceneSortDirty = false;
 652851        private bool positionDirty = true;
 852        private int lastSortFrame = 0;
 853
 854        public event Action OnSortScenes;
 855        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 856        public event Action<IParcelScene> OnNewSceneAdded;
 857        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 858        public event Action<string> OnNewPortableExperienceSceneRemoved;
 859
 652860        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 652861        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 862    }
 863}

Methods/Properties

enabled()
enabled(System.Boolean)
SceneController()
isPortableExperiencesInitialized()
Initialize()
OnDebugModeSet(System.Boolean, System.Boolean)
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)