< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:218
Uncovered lines:160
Coverable lines:378
Total lines:905
Line coverage:57.6% (218 of 378)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneController()0%110100%
Initialize()0%22092.86%
OnDebugModeSet(...)0%3.713057.14%
Start()0%6.744044.44%
Dispose()0%2.012087.5%
Update()0%440100%
LateUpdate()0%220100%
EnsureEntityPool()0%330100%
ProcessMessage(...)0%1101000%
ProcessMessage(...)0%22564700%
ParseQuery(...)0%6200%
SendSceneMessage(...)0%2100%
SendSceneMessage(...)0%12300%
DecodeAndEnqueue(...)0%30500%
DeferredDecoding()0%56700%
EnqueueSceneMessage(...)0%2100%
CreateTestScene(...)0%770100%
SendSceneReady(...)0%220100%
ActivateBuilderInWorldEditScene()0%110100%
DeactivateBuilderInWorldEditScene()0%110100%
SetPositionDirty(...)0%4.024090%
SortScenesByDistance()0%8.018095.24%
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
 72620        public bool enabled { get; set; } = true;
 21
 22        private Coroutine deferredDecodingCoroutine;
 23
 24        public void Initialize()
 25        {
 68926            sceneSortDirty = true;
 68927            positionDirty = true;
 68928            lastSortFrame = 0;
 68929            enabled = true;
 30
 68931            DataStore.i.debugConfig.isDebugMode.OnChange += OnDebugModeSet;
 32
 68933            if (deferredMessagesDecoding) // We should be able to delete this code
 034                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding()); //
 35
 68936            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 37
 68938            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 39
 40            //TODO(Brian): Move those subscriptions elsewhere.
 68941            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 68942            PoolManager.i.OnGet += Environment.i.platform.physicsSyncController.MarkDirty;
 43
 68944            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 68945            PoolManager.i.OnGet += Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 68946        }
 47
 48        private void OnDebugModeSet(bool current, bool previous)
 49        {
 950            if (current == previous)
 051                return;
 52
 953            if (current)
 54            {
 955                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedFlicker());
 956            }
 57            else
 58            {
 059                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_Simple());
 60            }
 061        }
 62
 63        public void Start()
 64        {
 12365            if (prewarmSceneMessagesPool)
 66            {
 067                for (int i = 0; i < 100000; i++)
 68                {
 069                    sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 70                }
 71            }
 72
 12373            if (prewarmEntitiesPool)
 74            {
 075                EnsureEntityPool();
 76            }
 77
 78            // Warmup some shader variants
 12379            Resources.Load<ShaderVariantCollection>("ShaderVariantCollections/shaderVariants-selected").WarmUp();
 12380        }
 81
 82        public void Dispose()
 83        {
 71084            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 71085            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 71086            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 71087            DataStore.i.debugConfig.isDebugMode.OnChange -= OnDebugModeSet;
 88
 71089            UnloadAllScenes(includePersistent: true);
 90
 71091            if (deferredDecodingCoroutine != null)
 092                CoroutineStarter.Stop(deferredDecodingCoroutine);
 71093        }
 94
 95        public void Update()
 96        {
 1982597            if (!enabled)
 5198                return;
 99
 19774100            InputController_Legacy.i.Update();
 101
 19774102            Environment.i.world.pointerEventsController.Update();
 103
 19774104            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 105            {
 835106                lastSortFrame = Time.frameCount;
 835107                sceneSortDirty = false;
 835108                SortScenesByDistance();
 109            }
 19774110        }
 111
 112        public void LateUpdate()
 113        {
 19819114            if (!enabled)
 51115                return;
 116
 19768117            Environment.i.platform.physicsSyncController.Sync();
 19768118        }
 119
 120        public void EnsureEntityPool() // TODO: Move to PoolManagerFactory
 121        {
 546122            if (PoolManager.i.ContainsPool(EMPTY_GO_POOL_NAME))
 276123                return;
 124
 270125            GameObject go = new GameObject();
 270126            Pool pool = PoolManager.i.AddPool(EMPTY_GO_POOL_NAME, go, maxPrewarmCount: 2000, isPersistent: true);
 127
 270128            if (prewarmEntitiesPool)
 19129                pool.ForcePrewarm();
 270130        }
 131
 132        //======================================================================
 133
 134        #region MESSAGES_HANDLING
 135
 136        //======================================================================
 137
 138#if UNITY_EDITOR
 139        public delegate void ProcessDelegate(string sceneId, string method);
 140
 141        public event ProcessDelegate OnMessageProcessInfoStart;
 142        public event ProcessDelegate OnMessageProcessInfoEnds;
 143#endif
 658144        public bool deferredMessagesDecoding { get; set; } = false;
 145
 689146        Queue<string> payloadsToDecode = new Queue<string>();
 147        const float MAX_TIME_FOR_DECODE = 0.005f;
 148
 149        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 150        {
 0151            string sceneId = msgObject.sceneId;
 0152            string method = msgObject.method;
 153
 0154            yieldInstruction = null;
 155
 156            IParcelScene scene;
 0157            bool res = false;
 0158            IWorldState worldState = Environment.i.world.state;
 0159            DebugConfig debugConfig = DataStore.i.debugConfig;
 160
 0161            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 162            {
 163#if UNITY_EDITOR
 0164                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 165                {
 0166                    return false;
 167                }
 168#endif
 0169                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 170                {
 0171                    return true;
 172                }
 173
 174#if UNITY_EDITOR
 0175                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 176#endif
 0177                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 178
 0179                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 180
 0181                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 182
 183#if UNITY_EDITOR
 0184                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 185#endif
 186
 0187                res = true;
 0188            }
 189
 190            else
 191            {
 0192                res = false;
 193            }
 194
 0195            sceneMessagesPool.Enqueue(msgObject);
 196
 0197            return res;
 198        }
 199
 200        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 201            out CustomYieldInstruction yieldInstruction)
 202        {
 0203            yieldInstruction = null;
 0204            IDelayedComponent delayedComponent = null;
 205
 206            try
 207            {
 208                switch (method)
 209                {
 210                    case MessagingTypes.ENTITY_CREATE:
 211                        {
 0212                            if (msgPayload is Protocol.CreateEntity payload)
 0213                                scene.CreateEntity(payload.entityId);
 214
 0215                            break;
 216                        }
 217                    case MessagingTypes.ENTITY_REPARENT:
 218                        {
 0219                            if (msgPayload is Protocol.SetEntityParent payload)
 0220                                scene.SetEntityParent(payload.entityId, payload.parentId);
 221
 0222                            break;
 223                        }
 224
 225                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 226                        {
 0227                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 228                            {
 0229                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 230                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 231                            }
 232
 0233                            break;
 234                        }
 235
 236                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 237                        {
 0238                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0239                                scene.EntityComponentRemove(payload.entityId, payload.name);
 240
 0241                            break;
 242                        }
 243
 244                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 245                        {
 0246                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0247                                scene.SharedComponentAttach(payload.entityId, payload.id);
 248
 0249                            break;
 250                        }
 251
 252                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 253                        {
 0254                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0255                                scene.SharedComponentCreate(payload.id, payload.classId);
 256
 0257                            break;
 258                        }
 259
 260                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 261                        {
 0262                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0263                                scene.SharedComponentDispose(payload.id);
 0264                            break;
 265                        }
 266
 267                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 268                        {
 0269                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0270                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 271
 0272                            break;
 273                        }
 274
 275                    case MessagingTypes.ENTITY_DESTROY:
 276                        {
 0277                            if (msgPayload is Protocol.RemoveEntity payload)
 0278                                scene.RemoveEntity(payload.entityId);
 0279                            break;
 280                        }
 281
 282                    case MessagingTypes.INIT_DONE:
 283                        {
 0284                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0285                            break;
 286                        }
 287
 288                    case MessagingTypes.QUERY:
 289                        {
 0290                            if (msgPayload is QueryMessage queryMessage)
 0291                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0292                            break;
 293                        }
 294
 295                    case MessagingTypes.OPEN_EXTERNAL_URL:
 296                        {
 0297                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0298                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0299                            break;
 300                        }
 301
 302                    case MessagingTypes.OPEN_NFT_DIALOG:
 303                        {
 0304                            if (msgPayload is Protocol.OpenNftDialog payload)
 0305                                DataStore.i.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payload.token
 306                                    payload.comment), true);
 0307                            break;
 308                        }
 309
 310                    default:
 0311                        Debug.LogError($"Unknown method {method}");
 312                        break;
 313                }
 0314            }
 0315            catch (Exception e)
 316            {
 0317                throw new Exception(
 318                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 319            }
 320
 0321            if (delayedComponent != null)
 322            {
 0323                if (delayedComponent.isRoutineRunning)
 0324                    yieldInstruction = delayedComponent.yieldInstruction;
 325            }
 0326        }
 327
 328        public void ParseQuery(object payload, string sceneId)
 329        {
 0330            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 331
 0332            if (!(payload is RaycastQuery raycastQuery))
 0333                return;
 334
 0335            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 336
 0337            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0338            raycastQuery.sceneId = sceneId;
 0339            PhysicsCast.i.Query(raycastQuery);
 0340        }
 341
 0342        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 343
 344        private void SendSceneMessage(string payload, bool enqueue)
 345        {
 0346            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0347            int count = chunks.Length;
 348
 0349            for (int i = 0; i < count; i++)
 350            {
 0351                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 352                {
 0353                    payloadsToDecode.Enqueue(chunks[i]);
 0354                }
 355                else
 356                {
 0357                    DecodeAndEnqueue(chunks[i]);
 358                }
 359            }
 0360        }
 361
 362        private void DecodeAndEnqueue(string payload)
 363        {
 0364            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 365
 366            string sceneId;
 367            string message;
 368            string messageTag;
 369            PB_SendSceneMessage sendSceneMessage;
 370
 0371            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 372            {
 0373                return;
 374            }
 375
 376            QueuedSceneMessage_Scene queuedMessage;
 377
 0378            if (sceneMessagesPool.Count > 0)
 0379                queuedMessage = sceneMessagesPool.Dequeue();
 380            else
 0381                queuedMessage = new QueuedSceneMessage_Scene();
 382
 0383            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 384
 0385            EnqueueSceneMessage(queuedMessage);
 386
 0387            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0388        }
 389
 390        private IEnumerator DeferredDecoding()
 391        {
 0392            float start = Time.realtimeSinceStartup;
 393            float maxTimeForDecode;
 394
 0395            while (true)
 396            {
 0397                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 398
 0399                if (payloadsToDecode.Count > 0)
 400                {
 0401                    string payload = payloadsToDecode.Dequeue();
 402
 0403                    DecodeAndEnqueue(payload);
 404
 0405                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 406                        continue;
 407                }
 408
 0409                yield return null;
 0410                start = Time.unscaledTime;
 411            }
 412        }
 413
 414        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 415        {
 0416            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0417            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0418            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0419        }
 420
 421        //======================================================================
 422
 423        #endregion
 424
 425        //======================================================================
 426
 427        //======================================================================
 428
 429        #region SCENES_MANAGEMENT
 430
 431        //======================================================================
 432        public event Action<string> OnReadyScene;
 433
 434        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 435        {
 690436            if (data == null)
 437            {
 682438                data = new LoadParcelScenesMessage.UnityParcelScene();
 439            }
 440
 690441            if (data.parcels == null)
 442            {
 682443                data.parcels = new Vector2Int[] { data.basePosition };
 444            }
 445
 690446            if (string.IsNullOrEmpty(data.id))
 447            {
 682448                data.id = $"(test):{data.basePosition.x},{data.basePosition.y}";
 449            }
 450
 690451            if (Environment.i.world.state.loadedScenes.ContainsKey(data.id))
 452            {
 12453                Debug.LogWarning($"Scene {data.id} is already loaded.");
 12454                return Environment.i.world.state.loadedScenes[data.id];
 455            }
 456
 678457            var go = new GameObject();
 678458            var newScene = go.AddComponent<ParcelScene>();
 678459            newScene.isTestScene = true;
 678460            newScene.isPersistent = true;
 678461            newScene.SetData(data);
 462
 678463            if (DCLCharacterController.i != null)
 678464                newScene.InitializeDebugPlane();
 465
 678466            Environment.i.world.state.scenesSortedByDistance.Add(newScene);
 467
 678468            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 469
 678470            Environment.i.world.state.loadedScenes.Add(data.id, newScene);
 678471            OnNewSceneAdded?.Invoke(newScene);
 678472            return newScene;
 473        }
 474
 475        public void SendSceneReady(string sceneId)
 476        {
 686477            Environment.i.world.state.readyScenes.Add(sceneId);
 478
 686479            Environment.i.messaging.manager.SetSceneReady(sceneId);
 480
 686481            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 482
 686483            Environment.i.world.blockersController.SetupWorldBlockers();
 484
 686485            OnReadyScene?.Invoke(sceneId);
 7486        }
 487
 14488        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 489
 8490        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 491
 492        private void SetPositionDirty(DCLCharacterPosition character)
 493        {
 2100494            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 2100495            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 496
 2100497            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 498
 2100499            if (positionDirty)
 500            {
 374501                sceneSortDirty = true;
 374502                currentGridSceneCoordinate.x = currentX;
 374503                currentGridSceneCoordinate.y = currentY;
 504
 505                // Since the first position for the character is not sent from Kernel until just-before calling
 506                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 507                // to lock the rendering accordingly...
 374508                if (!CommonScriptableObjects.rendererState.Get())
 509                {
 0510                    SortScenesByDistance();
 511                }
 512            }
 2100513        }
 514
 515        public void SortScenesByDistance()
 516        {
 839517            if (DCLCharacterController.i == null)
 0518                return;
 519
 839520            IWorldState worldState = Environment.i.world.state;
 521
 839522            worldState.currentSceneId = null;
 839523            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 524
 839525            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 526            {
 527                IParcelScene scene;
 528                bool characterIsInsideScene;
 529
 1480530                while (iterator.MoveNext())
 531                {
 798532                    scene = iterator.Current;
 533
 798534                    if (scene == null)
 535                        continue;
 536
 798537                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 538
 798539                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 540                    {
 157541                        worldState.currentSceneId = scene.sceneData.id;
 157542                        break;
 543                    }
 544                }
 682545            }
 546
 839547            if (!DataStore.i.debugConfig.isDebugMode.Get() && string.IsNullOrEmpty(worldState.currentSceneId))
 548            {
 549                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 675550                CommonScriptableObjects.rendererState.AddLock(this);
 675551            }
 552            else
 553            {
 554                // 1. Set current scene id
 164555                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 556
 557                // 2. Attempt to remove SceneController's lock on rendering
 164558                CommonScriptableObjects.rendererState.RemoveLock(this);
 559            }
 560
 839561            OnSortScenes?.Invoke();
 815562        }
 563
 564        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 565        {
 59566            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 59567            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 568
 59569            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 59570            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 571
 59572            return dist1 - dist2;
 573        }
 574
 575        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 576        {
 4038577            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 578                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 579            {
 0580                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 581
 0582                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 583            }
 4038584        }
 585
 586        public void LoadParcelScenesExecute(string scenePayload)
 587        {
 588            LoadParcelScenesMessage.UnityParcelScene scene;
 589
 26590            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 26591            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 26592            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 593
 26594            if (scene == null || scene.id == null)
 0595                return;
 596
 26597            var sceneToLoad = scene;
 598
 599
 26600            DebugConfig debugConfig = DataStore.i.debugConfig;
 601#if UNITY_EDITOR
 26602            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 603            {
 0604                SendSceneReady(sceneToLoad.id);
 0605                return;
 606            }
 607#endif
 608
 26609            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 610
 26611            IWorldState worldState = Environment.i.world.state;
 612
 26613            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 614            {
 26615                var newGameObject = new GameObject("New Scene");
 616
 26617                var newScene = newGameObject.AddComponent<ParcelScene>();
 26618                newScene.SetData(sceneToLoad);
 619
 26620                if (debugConfig.isDebugMode.Get())
 621                {
 26622                    newScene.InitializeDebugPlane();
 623                }
 624
 26625                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 26626                worldState.scenesSortedByDistance.Add(newScene);
 627
 26628                sceneSortDirty = true;
 629
 26630                OnNewSceneAdded?.Invoke(newScene);
 631
 26632                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 633
 26634                if (VERBOSE)
 0635                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 636            }
 637
 26638            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0639        }
 640
 641        public void UpdateParcelScenesExecute(string sceneId)
 642        {
 643            LoadParcelScenesMessage.UnityParcelScene sceneData;
 644
 0645            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0646            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0647            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 648
 0649            IWorldState worldState = Environment.i.world.state;
 650
 0651            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 652            {
 0653                ParcelScene scene = sceneInterface as ParcelScene;
 0654                scene.SetUpdateData(sceneData);
 0655            }
 656            else
 657            {
 0658                LoadParcelScenesExecute(sceneId);
 659            }
 0660        }
 661
 662        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 663        {
 15664            if (scene == null || scene.id == null)
 0665                return;
 666
 15667            var sceneToLoad = scene;
 668
 15669            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 670
 15671            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 672
 15673            if (parcelScene != null)
 15674                parcelScene.SetUpdateData(sceneToLoad);
 675
 15676            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0677        }
 678
 679        public void UnloadScene(string sceneKey)
 680        {
 1681            var queuedMessage = new QueuedSceneMessage()
 682                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 683
 1684            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 685
 1686            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 687
 1688            Environment.i.messaging.manager.RemoveController(sceneKey);
 689
 1690            IWorldState worldState = Environment.i.world.state;
 691
 1692            if (worldState.loadedScenes.ContainsKey(sceneKey))
 693            {
 1694                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1695                sceneToUnload.isPersistent = false;
 696
 1697                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0698                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 699            }
 1700        }
 701
 702        public void UnloadParcelSceneExecute(string sceneId)
 703        {
 727704            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 705
 727706            IWorldState worldState = Environment.i.world.state;
 707
 727708            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 709            {
 1710                return;
 711            }
 712
 726713            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 714
 726715            if (scene == null)
 0716                return;
 717
 726718            worldState.loadedScenes.Remove(sceneId);
 726719            worldState.globalSceneIds.Remove(sceneId);
 720
 721            // Remove the scene id from the msg. priorities list
 726722            worldState.scenesSortedByDistance.Remove(scene);
 723
 724            // Remove messaging controller for unloaded scene
 726725            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 726
 726727            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 728
 726729            if (VERBOSE)
 730            {
 0731                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 732            }
 733
 726734            Environment.i.world.blockersController.SetupWorldBlockers();
 735
 726736            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0737        }
 738
 739        public void UnloadAllScenes(bool includePersistent = false)
 740        {
 713741            var worldState = Environment.i.world.state;
 742
 713743            if (includePersistent)
 744            {
 1437745                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 746
 2824747                foreach (var kvp in persistentScenes)
 748                {
 700749                    if (kvp.Value is ParcelScene scene)
 750                    {
 700751                        scene.isPersistent = false;
 752                    }
 753                }
 754            }
 755
 713756            var list = worldState.loadedScenes.ToArray();
 757
 2878758            for (int i = 0; i < list.Length; i++)
 759            {
 726760                UnloadParcelSceneExecute(list[i].Key);
 761            }
 713762        }
 763
 764        public void LoadParcelScenes(string decentralandSceneJSON)
 765        {
 26766            var queuedMessage = new QueuedSceneMessage()
 767            {
 768                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 769                message = decentralandSceneJSON
 770            };
 771
 26772            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 773
 26774            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 775
 26776            if (VERBOSE)
 0777                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 26778        }
 779
 780        public void UpdateParcelScenes(string decentralandSceneJSON)
 781        {
 0782            var queuedMessage = new QueuedSceneMessage()
 783                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 784
 0785            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 786
 0787            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0788        }
 789
 790        public void UnloadAllScenesQueued()
 791        {
 0792            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 793
 0794            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 795
 0796            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0797        }
 798
 799        public void CreateGlobalScene(string json)
 800        {
 801#if UNITY_EDITOR
 22802            DebugConfig debugConfig = DataStore.i.debugConfig;
 803
 22804            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0805                return;
 806#endif
 22807            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 808
 22809            string newGlobalSceneId = globalScene.id;
 810
 22811            IWorldState worldState = Environment.i.world.state;
 812
 22813            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0814                return;
 815
 22816            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 817
 22818            var newScene = newGameObject.AddComponent<GlobalScene>();
 22819            newScene.unloadWithDistance = false;
 22820            newScene.isPersistent = true;
 22821            newScene.sceneName = globalScene.name;
 22822            newScene.isPortableExperience = globalScene.isPortableExperience;
 823
 22824            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 825            {
 826                id = newGlobalSceneId,
 827                basePosition = new Vector2Int(0, 0),
 828                baseUrl = globalScene.baseUrl,
 829                contents = globalScene.contents
 830            };
 831
 22832            newScene.SetData(data);
 833
 22834            if (!string.IsNullOrEmpty(globalScene.icon))
 835            {
 0836                if (globalScene.icon.StartsWith("http://") || globalScene.icon.StartsWith("https://"))
 837                {
 0838                    newScene.iconUrl = globalScene.icon;
 0839                }
 840                else
 841                {
 0842                    newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 843                }
 844            }
 845
 22846            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 22847            OnNewSceneAdded?.Invoke(newScene);
 848
 22849            if (newScene.isPortableExperience)
 0850                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 851
 22852            worldState.globalSceneIds.Add(newGlobalSceneId);
 853
 22854            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 855
 22856            if (VERBOSE)
 857            {
 0858                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 859            }
 22860        }
 861
 862        public void IsolateScene(IParcelScene sceneToActive)
 863        {
 200864            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 865            {
 50866                if (scene != sceneToActive)
 0867                    scene.GetSceneTransform().gameObject.SetActive(false);
 868            }
 50869        }
 870
 871        public void ReIntegrateIsolatedScene()
 872        {
 28873            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 874            {
 7875                scene.GetSceneTransform().gameObject.SetActive(true);
 876            }
 7877        }
 878
 879        //======================================================================
 880
 881        #endregion
 882
 883        //======================================================================
 884
 689885        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 886
 1347887        public bool prewarmSceneMessagesPool { get; set; } = true;
 1347888        public bool prewarmEntitiesPool { get; set; } = true;
 889
 890        private bool sceneSortDirty = false;
 689891        private bool positionDirty = true;
 892        private int lastSortFrame = 0;
 893
 894        public event Action OnSortScenes;
 895        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 896        public event Action<IParcelScene> OnNewSceneAdded;
 897        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 898        public event Action<string> OnNewPortableExperienceSceneRemoved;
 899
 689900        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 689901        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 902
 903        public const string EMPTY_GO_POOL_NAME = "Empty";
 904    }
 905}

Methods/Properties

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