< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:190
Uncovered lines:163
Coverable lines:353
Total lines:859
Line coverage:53.8% (190 of 353)
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%9.519081.48%
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
 67621        public bool enabled { get; set; } = true;
 22
 23        //TODO(Brian): Move to WorldRuntimePlugin later
 24        private LoadingFeedbackController loadingFeedbackController;
 25
 26        private Coroutine deferredDecodingCoroutine;
 27
 28        public void Initialize()
 29        {
 65330            sceneSortDirty = true;
 65331            positionDirty = true;
 65332            lastSortFrame = 0;
 65333            enabled = true;
 34
 65335            loadingFeedbackController = new LoadingFeedbackController();
 36
 65337            DataStore.i.debugConfig.isDebugMode.OnChange += OnDebugModeSet;
 38
 65339            if (deferredMessagesDecoding) // We should be able to delete this code
 040                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding());
 41
 65342            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 43
 65344            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 45
 46            // TODO(Brian): Move this later to Main.cs
 65347            if ( !EnvironmentSettings.RUNNING_TESTS )
 48            {
 049                if (prewarmSceneMessagesPool)
 50                {
 051                    for (int i = 0; i < SCENE_MESSAGES_PREWARM_COUNT; i++)
 52                    {
 053                        sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 54                    }
 55                }
 56
 057                if (prewarmEntitiesPool)
 58                {
 059                    PoolManagerFactory.EnsureEntityPool(prewarmEntitiesPool);
 60                }
 61            }
 62
 65363            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 65364            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.LateUpdate, LateUpda
 65365        }
 66
 67        private void OnDebugModeSet(bool current, bool previous)
 68        {
 969            if (current == previous)
 070                return;
 71
 972            if (current)
 73            {
 974                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedBox());
 975            }
 76            else
 77            {
 078                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_Simple());
 79            }
 080        }
 81
 82        public void Dispose()
 83        {
 65384            loadingFeedbackController.Dispose();
 85
 65386            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 65387            DCL.Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.LateUpdate, LateU
 88
 65389            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 65390            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 91
 65392            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 65393            DataStore.i.debugConfig.isDebugMode.OnChange -= OnDebugModeSet;
 94
 65395            CommonScriptableObjects.sceneID.OnChange -= OnCurrentSceneIdChange;
 96
 65397            UnloadAllScenes(includePersistent: true);
 98
 65399            if (deferredDecodingCoroutine != null)
 0100                CoroutineStarter.Stop(deferredDecodingCoroutine);
 653101        }
 102
 103        public void Update()
 104        {
 8545105            if (!enabled)
 318106                return;
 107
 8227108            InputController_Legacy.i.Update();
 109
 8227110            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 111            {
 651112                lastSortFrame = Time.frameCount;
 651113                sceneSortDirty = false;
 651114                SortScenesByDistance();
 115            }
 8227116        }
 117
 118        public void LateUpdate()
 119        {
 8545120            if (!enabled)
 318121                return;
 122
 8227123            Environment.i.platform.physicsSyncController.Sync();
 8227124        }
 125
 126        //======================================================================
 127
 128        #region MESSAGES_HANDLING
 129
 130        //======================================================================
 131
 132#if UNITY_EDITOR
 133        public delegate void ProcessDelegate(string sceneId, string method);
 134
 135        public event ProcessDelegate OnMessageProcessInfoStart;
 136        public event ProcessDelegate OnMessageProcessInfoEnds;
 137#endif
 0138        public bool deferredMessagesDecoding { get; set; } = false;
 139
 653140        Queue<string> payloadsToDecode = new Queue<string>();
 141        const float MAX_TIME_FOR_DECODE = 0.005f;
 142
 143        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 144        {
 0145            string sceneId = msgObject.sceneId;
 0146            string method = msgObject.method;
 147
 0148            yieldInstruction = null;
 149
 150            IParcelScene scene;
 0151            bool res = false;
 0152            IWorldState worldState = Environment.i.world.state;
 0153            DebugConfig debugConfig = DataStore.i.debugConfig;
 154
 0155            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 156            {
 157#if UNITY_EDITOR
 0158                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 159                {
 0160                    return false;
 161                }
 162#endif
 0163                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 164                {
 0165                    return true;
 166                }
 167
 168#if UNITY_EDITOR
 0169                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 170#endif
 0171                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 172
 0173                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 174
 0175                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 176
 177#if UNITY_EDITOR
 0178                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 179#endif
 180
 0181                res = true;
 0182            }
 183
 184            else
 185            {
 0186                res = false;
 187            }
 188
 0189            sceneMessagesPool.Enqueue(msgObject);
 190
 0191            return res;
 192        }
 193
 194        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 195            out CustomYieldInstruction yieldInstruction)
 196        {
 0197            yieldInstruction = null;
 0198            IDelayedComponent delayedComponent = null;
 199
 200            try
 201            {
 202                switch (method)
 203                {
 204                    case MessagingTypes.ENTITY_CREATE:
 205                        {
 0206                            if (msgPayload is Protocol.CreateEntity payload)
 0207                                scene.CreateEntity(payload.entityId);
 208
 0209                            break;
 210                        }
 211                    case MessagingTypes.ENTITY_REPARENT:
 212                        {
 0213                            if (msgPayload is Protocol.SetEntityParent payload)
 0214                                scene.SetEntityParent(payload.entityId, payload.parentId);
 215
 0216                            break;
 217                        }
 218
 219                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 220                        {
 0221                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 222                            {
 0223                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 224                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 225                            }
 226
 0227                            break;
 228                        }
 229
 230                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 231                        {
 0232                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0233                                scene.EntityComponentRemove(payload.entityId, payload.name);
 234
 0235                            break;
 236                        }
 237
 238                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 239                        {
 0240                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0241                                scene.SharedComponentAttach(payload.entityId, payload.id);
 242
 0243                            break;
 244                        }
 245
 246                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 247                        {
 0248                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0249                                scene.SharedComponentCreate(payload.id, payload.classId);
 250
 0251                            break;
 252                        }
 253
 254                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 255                        {
 0256                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0257                                scene.SharedComponentDispose(payload.id);
 0258                            break;
 259                        }
 260
 261                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 262                        {
 0263                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0264                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 265
 0266                            break;
 267                        }
 268
 269                    case MessagingTypes.ENTITY_DESTROY:
 270                        {
 0271                            if (msgPayload is Protocol.RemoveEntity payload)
 0272                                scene.RemoveEntity(payload.entityId);
 0273                            break;
 274                        }
 275
 276                    case MessagingTypes.INIT_DONE:
 277                        {
 0278                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0279                            break;
 280                        }
 281
 282                    case MessagingTypes.QUERY:
 283                        {
 0284                            if (msgPayload is QueryMessage queryMessage)
 0285                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0286                            break;
 287                        }
 288
 289                    case MessagingTypes.OPEN_EXTERNAL_URL:
 290                        {
 0291                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0292                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0293                            break;
 294                        }
 295
 296                    case MessagingTypes.OPEN_NFT_DIALOG:
 297                        {
 0298                            if (msgPayload is Protocol.OpenNftDialog payload)
 0299                                DataStore.i.common.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payloa
 300                                    payload.comment), true);
 0301                            break;
 302                        }
 303
 304                    default:
 0305                        Debug.LogError($"Unknown method {method}");
 306                        break;
 307                }
 0308            }
 0309            catch (Exception e)
 310            {
 0311                throw new Exception(
 312                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 313            }
 314
 0315            if (delayedComponent != null)
 316            {
 0317                if (delayedComponent.isRoutineRunning)
 0318                    yieldInstruction = delayedComponent.yieldInstruction;
 319            }
 0320        }
 321
 322        public void ParseQuery(object payload, string sceneId)
 323        {
 0324            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 325
 0326            if (!(payload is RaycastQuery raycastQuery))
 0327                return;
 328
 0329            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 330
 0331            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0332            raycastQuery.sceneId = sceneId;
 0333            PhysicsCast.i.Query(raycastQuery);
 0334        }
 335
 0336        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 337
 338        private void SendSceneMessage(string payload, bool enqueue)
 339        {
 0340            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0341            int count = chunks.Length;
 342
 0343            for (int i = 0; i < count; i++)
 344            {
 0345                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 346                {
 0347                    payloadsToDecode.Enqueue(chunks[i]);
 0348                }
 349                else
 350                {
 0351                    DecodeAndEnqueue(chunks[i]);
 352                }
 353            }
 0354        }
 355
 356        private void DecodeAndEnqueue(string payload)
 357        {
 0358            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 359
 360            string sceneId;
 361            string message;
 362            string messageTag;
 363            PB_SendSceneMessage sendSceneMessage;
 364
 0365            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 366            {
 0367                return;
 368            }
 369
 370            QueuedSceneMessage_Scene queuedMessage;
 371
 0372            if (sceneMessagesPool.Count > 0)
 0373                queuedMessage = sceneMessagesPool.Dequeue();
 374            else
 0375                queuedMessage = new QueuedSceneMessage_Scene();
 376
 0377            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 378
 0379            EnqueueSceneMessage(queuedMessage);
 380
 0381            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0382        }
 383
 384        private IEnumerator DeferredDecoding()
 385        {
 0386            float start = Time.realtimeSinceStartup;
 387            float maxTimeForDecode;
 388
 0389            while (true)
 390            {
 0391                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 392
 0393                if (payloadsToDecode.Count > 0)
 394                {
 0395                    string payload = payloadsToDecode.Dequeue();
 396
 0397                    DecodeAndEnqueue(payload);
 398
 0399                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 400                        continue;
 401                }
 402
 0403                yield return null;
 0404                start = Time.unscaledTime;
 405            }
 406        }
 407
 408        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 409        {
 0410            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0411            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0412            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0413        }
 414
 415        //======================================================================
 416
 417        #endregion
 418
 419        //======================================================================
 420
 421        //======================================================================
 422
 423        #region SCENES_MANAGEMENT
 424
 425        //======================================================================
 426        public event Action<string> OnReadyScene;
 427
 428        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 429        {
 0430            IParcelScene result = WorldStateUtils.CreateTestScene(data);
 0431            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 0432            OnNewSceneAdded?.Invoke(result);
 0433            return result;
 434        }
 435
 436        public void SendSceneReady(string sceneId)
 437        {
 388438            Environment.i.world.state.readyScenes.Add(sceneId);
 439
 388440            Environment.i.messaging.manager.SetSceneReady(sceneId);
 441
 388442            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 388443            WebInterface.ReportCameraChanged(CommonScriptableObjects.cameraMode.Get(), sceneId);
 444
 388445            Environment.i.world.blockersController.SetupWorldBlockers();
 446
 388447            OnReadyScene?.Invoke(sceneId);
 2448        }
 449
 10450        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 451
 2452        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 453
 454        private void SetPositionDirty(DCLCharacterPosition character)
 455        {
 6098456            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 6098457            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 458
 6098459            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 460
 6098461            if (positionDirty)
 462            {
 579463                sceneSortDirty = true;
 579464                currentGridSceneCoordinate.x = currentX;
 579465                currentGridSceneCoordinate.y = currentY;
 466
 467                // Since the first position for the character is not sent from Kernel until just-before calling
 468                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 469                // to lock the rendering accordingly...
 579470                if (!CommonScriptableObjects.rendererState.Get())
 471                {
 0472                    SortScenesByDistance();
 473                }
 474            }
 6098475        }
 476
 477        public void SortScenesByDistance()
 478        {
 651479            if (DCLCharacterController.i == null)
 65480                return;
 481
 586482            IWorldState worldState = Environment.i.world.state;
 483
 586484            worldState.currentSceneId = null;
 586485            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 486
 586487            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 488            {
 489                IParcelScene scene;
 490                bool characterIsInsideScene;
 491
 609492                while (iterator.MoveNext())
 493                {
 28494                    scene = iterator.Current;
 495
 28496                    if (scene == null)
 497                        continue;
 498
 28499                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 500
 28501                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 502                    {
 5503                        worldState.currentSceneId = scene.sceneData.id;
 5504                        break;
 505                    }
 506                }
 581507            }
 508
 586509            if (!DataStore.i.debugConfig.isDebugMode.Get() && string.IsNullOrEmpty(worldState.currentSceneId))
 510            {
 511                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 578512                CommonScriptableObjects.rendererState.AddLock(this);
 578513            }
 514            else
 515            {
 516                // 1. Set current scene id
 8517                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 518
 519                // 2. Attempt to remove SceneController's lock on rendering
 8520                CommonScriptableObjects.rendererState.RemoveLock(this);
 521            }
 522
 586523            OnSortScenes?.Invoke();
 586524        }
 525
 526        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 527        {
 25528            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 25529            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 530
 25531            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 25532            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 533
 25534            return dist1 - dist2;
 535        }
 536
 537        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 538        {
 15539            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 540                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 541            {
 0542                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 543
 0544                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 545            }
 15546        }
 547
 548        public void LoadParcelScenesExecute(string scenePayload)
 549        {
 550            LoadParcelScenesMessage.UnityParcelScene scene;
 551
 26552            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 26553            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 26554            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 555
 26556            if (scene == null || scene.id == null)
 0557                return;
 558
 26559            var sceneToLoad = scene;
 560
 561
 26562            DebugConfig debugConfig = DataStore.i.debugConfig;
 563#if UNITY_EDITOR
 26564            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 565            {
 0566                SendSceneReady(sceneToLoad.id);
 0567                return;
 568            }
 569#endif
 570
 26571            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 572
 26573            IWorldState worldState = Environment.i.world.state;
 574
 26575            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 576            {
 26577                var newGameObject = new GameObject("New Scene");
 578
 26579                var newScene = newGameObject.AddComponent<ParcelScene>();
 26580                newScene.SetData(sceneToLoad);
 581
 26582                if (debugConfig.isDebugMode.Get())
 583                {
 26584                    newScene.InitializeDebugPlane();
 585                }
 586
 26587                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 26588                worldState.scenesSortedByDistance.Add(newScene);
 589
 26590                sceneSortDirty = true;
 591
 26592                OnNewSceneAdded?.Invoke(newScene);
 593
 26594                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 595
 26596                if (VERBOSE)
 0597                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 598            }
 599
 26600            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0601        }
 602
 603        public void UpdateParcelScenesExecute(string sceneId)
 604        {
 605            LoadParcelScenesMessage.UnityParcelScene sceneData;
 606
 0607            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0608            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0609            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 610
 0611            IWorldState worldState = Environment.i.world.state;
 612
 0613            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 614            {
 0615                ParcelScene scene = sceneInterface as ParcelScene;
 0616                scene.SetUpdateData(sceneData);
 0617            }
 618            else
 619            {
 0620                LoadParcelScenesExecute(sceneId);
 621            }
 0622        }
 623
 624        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 625        {
 15626            if (scene == null || scene.id == null)
 0627                return;
 628
 15629            var sceneToLoad = scene;
 630
 15631            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 632
 15633            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 634
 15635            if (parcelScene != null)
 15636                parcelScene.SetUpdateData(sceneToLoad);
 637
 15638            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0639        }
 640
 641        public void UnloadScene(string sceneKey)
 642        {
 1643            var queuedMessage = new QueuedSceneMessage()
 644                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 645
 1646            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 647
 1648            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 649
 1650            Environment.i.messaging.manager.RemoveController(sceneKey);
 651
 1652            IWorldState worldState = Environment.i.world.state;
 653
 1654            if (worldState.loadedScenes.ContainsKey(sceneKey))
 655            {
 1656                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1657                sceneToUnload.isPersistent = false;
 658
 1659                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0660                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 661            }
 1662        }
 663
 664        public void UnloadParcelSceneExecute(string sceneId)
 665        {
 412666            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 667
 412668            IWorldState worldState = Environment.i.world.state;
 669
 412670            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 671            {
 0672                return;
 673            }
 674
 412675            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 676
 412677            if (scene == null)
 9678                return;
 679
 403680            worldState.loadedScenes.Remove(sceneId);
 403681            worldState.globalSceneIds.Remove(sceneId);
 682
 683            // Remove the scene id from the msg. priorities list
 403684            worldState.scenesSortedByDistance.Remove(scene);
 685
 686            // Remove messaging controller for unloaded scene
 403687            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 688
 403689            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 690
 691
 403692            if (VERBOSE)
 693            {
 0694                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 695            }
 696
 403697            Environment.i.world.blockersController.SetupWorldBlockers();
 698
 403699            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0700        }
 701
 702        public void UnloadAllScenes(bool includePersistent = false)
 703        {
 655704            var worldState = Environment.i.world.state;
 705
 655706            if (includePersistent)
 707            {
 1066708                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 709
 2082710                foreach (var kvp in persistentScenes)
 711                {
 386712                    if (kvp.Value is ParcelScene scene)
 713                    {
 386714                        scene.isPersistent = false;
 715                    }
 716                }
 717            }
 718
 655719            var list = worldState.loadedScenes.ToArray();
 720
 2132721            for (int i = 0; i < list.Length; i++)
 722            {
 411723                UnloadParcelSceneExecute(list[i].Key);
 724            }
 655725        }
 726
 727        public void LoadParcelScenes(string decentralandSceneJSON)
 728        {
 26729            var queuedMessage = new QueuedSceneMessage()
 730            {
 731                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 732                message = decentralandSceneJSON
 733            };
 734
 26735            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 736
 26737            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 738
 26739            if (VERBOSE)
 0740                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 26741        }
 742
 743        public void UpdateParcelScenes(string decentralandSceneJSON)
 744        {
 0745            var queuedMessage = new QueuedSceneMessage()
 746                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 747
 0748            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 749
 0750            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0751        }
 752
 753        public void UnloadAllScenesQueued()
 754        {
 0755            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 756
 0757            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 758
 0759            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0760        }
 761
 762        public void CreateGlobalScene(string json)
 763        {
 764#if UNITY_EDITOR
 1765            DebugConfig debugConfig = DataStore.i.debugConfig;
 766
 1767            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0768                return;
 769#endif
 1770            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 771
 1772            string newGlobalSceneId = globalScene.id;
 773
 1774            IWorldState worldState = Environment.i.world.state;
 775
 1776            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0777                return;
 778
 1779            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 780
 1781            var newScene = newGameObject.AddComponent<GlobalScene>();
 1782            newScene.unloadWithDistance = false;
 1783            newScene.isPersistent = true;
 1784            newScene.sceneName = globalScene.name;
 1785            newScene.isPortableExperience = globalScene.isPortableExperience;
 786
 1787            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 788            {
 789                id = newGlobalSceneId,
 790                basePosition = new Vector2Int(0, 0),
 791                baseUrl = globalScene.baseUrl,
 792                contents = globalScene.contents
 793            };
 794
 1795            newScene.SetData(data);
 796
 1797            if (!string.IsNullOrEmpty(globalScene.icon))
 798            {
 0799                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 800            }
 801
 1802            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 1803            OnNewSceneAdded?.Invoke(newScene);
 804
 1805            if (newScene.isPortableExperience)
 0806                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 807
 1808            worldState.globalSceneIds.Add(newGlobalSceneId);
 809
 1810            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 811
 1812            if (VERBOSE)
 813            {
 0814                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 815            }
 1816        }
 817
 818        public void IsolateScene(IParcelScene sceneToActive)
 819        {
 152820            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 821            {
 38822                if (scene != sceneToActive)
 0823                    scene.GetSceneTransform().gameObject.SetActive(false);
 824            }
 38825        }
 826
 827        public void ReIntegrateIsolatedScene()
 828        {
 20829            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 830            {
 5831                scene.GetSceneTransform().gameObject.SetActive(true);
 832            }
 5833        }
 834
 835        //======================================================================
 836
 837        #endregion
 838
 839        //======================================================================
 840
 653841        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 842
 653843        public bool prewarmSceneMessagesPool { get; set; } = true;
 653844        public bool prewarmEntitiesPool { get; set; } = true;
 845
 846        private bool sceneSortDirty = false;
 653847        private bool positionDirty = true;
 848        private int lastSortFrame = 0;
 849
 850        public event Action OnSortScenes;
 851        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 852        public event Action<IParcelScene> OnNewSceneAdded;
 853        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 854        public event Action<string> OnNewPortableExperienceSceneRemoved;
 855
 653856        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 653857        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 858    }
 859}

Methods/Properties

enabled()
enabled(System.Boolean)
SceneController()
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)