< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:223
Uncovered lines:156
Coverable lines:379
Total lines:901
Line coverage:58.8% (223 of 379)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneController()0%110100%
Initialize()0%22093.33%
OnDebugModeSet(...)0%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%440100%
SortScenesByDistance()0%8.018095.24%
SortScenesByDistanceMethod(...)0%110100%
OnCurrentSceneIdChange(...)0%64050%
LoadParcelScenesExecute(...)0%13.9613082.14%
UpdateParcelScenesExecute(...)0%20400%
UpdateParcelScenesExecute(...)0%6.396077.78%
UnloadScene(...)0%6.036090.91%
UnloadParcelSceneExecute(...)0%7.277082.35%
UnloadAllScenes(...)0%770100%
LoadParcelScenes(...)0%3.043083.33%
UpdateParcelScenes(...)0%6200%
UnloadAllScenesQueued()0%6200%
CreateGlobalScene(...)0%9.469082.14%
IsolateScene(...)0%3.043083.33%
ReIntegrateIsolatedScene()0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using DCL.Models;
 5using DCL.Configuration;
 6using System;
 7using System.Collections;
 8using System.Collections.Generic;
 9using System.Linq;
 10using DCL.Components;
 11using Newtonsoft.Json;
 12using UnityEngine;
 13
 14namespace DCL
 15{
 16    public class SceneController : ISceneController
 17    {
 18        public static bool VERBOSE = false;
 19
 71820        public bool enabled { get; set; } = true;
 21
 22        private Coroutine deferredDecodingCoroutine;
 23
 24        public void Initialize()
 25        {
 68226            sceneSortDirty = true;
 68227            positionDirty = true;
 68228            lastSortFrame = 0;
 68229            enabled = true;
 30
 68231            DataStore.i.debugConfig.isDebugMode.OnChange += OnDebugModeSet;
 32
 33            // We trigger the Decentraland logic once SceneController has been instanced and is ready to act.
 68234            WebInterface.StartDecentraland();
 35
 68236            if (deferredMessagesDecoding) // We should be able to delete this code
 037                deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecoding()); //
 38
 68239            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 40
 68241            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 42
 43            //TODO(Brian): Move those subscriptions elsewhere.
 68244            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 68245            PoolManager.i.OnGet += Environment.i.platform.physicsSyncController.MarkDirty;
 46
 68247            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 68248            PoolManager.i.OnGet += Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 68249        }
 50        private void OnDebugModeSet(bool current, bool previous)
 51        {
 152            if (current == previous)
 053                return;
 54
 155            if (current)
 56            {
 157                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedFlicker());
 158            }
 59            else
 60            {
 061                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_Simple());
 62            }
 063        }
 64
 65        public void Start()
 66        {
 12367            if (prewarmSceneMessagesPool)
 68            {
 069                for (int i = 0; i < 100000; i++)
 70                {
 071                    sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 72                }
 73            }
 74
 12375            if (prewarmEntitiesPool)
 76            {
 077                EnsureEntityPool();
 78            }
 79
 80            // Warmup some shader variants
 12381            Resources.Load<ShaderVariantCollection>("ShaderVariantCollections/shaderVariants-selected").WarmUp();
 12382        }
 83
 84        public void Dispose()
 85        {
 70286            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 70287            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 70288            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 70289            DataStore.i.debugConfig.isDebugMode.OnChange -= OnDebugModeSet;
 90
 70291            UnloadAllScenes(includePersistent: true);
 92
 70293            if (deferredDecodingCoroutine != null)
 094                CoroutineStarter.Stop(deferredDecodingCoroutine);
 70295        }
 96
 97        public void Update()
 98        {
 1735999            if (!enabled)
 51100                return;
 101
 17308102            InputController_Legacy.i.Update();
 103
 17308104            Environment.i.world.pointerEventsController.Update();
 105
 17308106            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 107            {
 872108                lastSortFrame = Time.frameCount;
 872109                sceneSortDirty = false;
 872110                SortScenesByDistance();
 111            }
 17308112        }
 113
 114        public void LateUpdate()
 115        {
 17353116            if (!enabled)
 51117                return;
 118
 17302119            Environment.i.platform.physicsSyncController.Sync();
 17302120        }
 121
 122        public void EnsureEntityPool() // TODO: Move to PoolManagerFactory
 123        {
 542124            if (PoolManager.i.ContainsPool(EMPTY_GO_POOL_NAME))
 275125                return;
 126
 267127            GameObject go = new GameObject();
 267128            Pool pool = PoolManager.i.AddPool(EMPTY_GO_POOL_NAME, go, maxPrewarmCount: 2000, isPersistent: true);
 129
 267130            if (prewarmEntitiesPool)
 14131                pool.ForcePrewarm();
 267132        }
 133
 134        //======================================================================
 135
 136        #region MESSAGES_HANDLING
 137
 138        //======================================================================
 139
 140#if UNITY_EDITOR
 141        public delegate void ProcessDelegate(string sceneId, string method);
 142
 143        public event ProcessDelegate OnMessageProcessInfoStart;
 144        public event ProcessDelegate OnMessageProcessInfoEnds;
 145#endif
 657146        public bool deferredMessagesDecoding { get; set; } = false;
 147
 682148        Queue<string> payloadsToDecode = new Queue<string>();
 149        const float MAX_TIME_FOR_DECODE = 0.005f;
 150
 151        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 152        {
 0153            string sceneId = msgObject.sceneId;
 0154            string method = msgObject.method;
 155
 0156            yieldInstruction = null;
 157
 158            IParcelScene scene;
 0159            bool res = false;
 0160            IWorldState worldState = Environment.i.world.state;
 0161            DebugConfig debugConfig = DataStore.i.debugConfig;
 162
 0163            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 164            {
 165#if UNITY_EDITOR
 0166                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 167                {
 0168                    return false;
 169                }
 170#endif
 0171                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 172                {
 0173                    return true;
 174                }
 175
 176#if UNITY_EDITOR
 0177                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 178#endif
 0179                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 180
 0181                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 182
 0183                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 184
 185#if UNITY_EDITOR
 0186                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 187#endif
 188
 0189                res = true;
 0190            }
 191
 192            else
 193            {
 0194                res = false;
 195            }
 196
 0197            sceneMessagesPool.Enqueue(msgObject);
 198
 0199            return res;
 200        }
 201
 202        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 203            out CustomYieldInstruction yieldInstruction)
 204        {
 0205            yieldInstruction = null;
 0206            IDelayedComponent delayedComponent = null;
 207
 208            try
 209            {
 210                switch (method)
 211                {
 212                    case MessagingTypes.ENTITY_CREATE:
 213                        {
 0214                            if (msgPayload is Protocol.CreateEntity payload)
 0215                                scene.CreateEntity(payload.entityId);
 216
 0217                            break;
 218                        }
 219                    case MessagingTypes.ENTITY_REPARENT:
 220                        {
 0221                            if (msgPayload is Protocol.SetEntityParent payload)
 0222                                scene.SetEntityParent(payload.entityId, payload.parentId);
 223
 0224                            break;
 225                        }
 226
 227                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 228                        {
 0229                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 230                            {
 0231                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 232                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 233                            }
 234
 0235                            break;
 236                        }
 237
 238                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 239                        {
 0240                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0241                                scene.EntityComponentRemove(payload.entityId, payload.name);
 242
 0243                            break;
 244                        }
 245
 246                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 247                        {
 0248                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0249                                scene.SharedComponentAttach(payload.entityId, payload.id);
 250
 0251                            break;
 252                        }
 253
 254                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 255                        {
 0256                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0257                                scene.SharedComponentCreate(payload.id, payload.classId);
 258
 0259                            break;
 260                        }
 261
 262                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 263                        {
 0264                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0265                                scene.SharedComponentDispose(payload.id);
 0266                            break;
 267                        }
 268
 269                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 270                        {
 0271                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0272                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 273
 0274                            break;
 275                        }
 276
 277                    case MessagingTypes.ENTITY_DESTROY:
 278                        {
 0279                            if (msgPayload is Protocol.RemoveEntity payload)
 0280                                scene.RemoveEntity(payload.entityId);
 0281                            break;
 282                        }
 283
 284                    case MessagingTypes.INIT_DONE:
 285                        {
 0286                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 0287                            break;
 288                        }
 289
 290                    case MessagingTypes.QUERY:
 291                        {
 0292                            if (msgPayload is QueryMessage queryMessage)
 0293                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 0294                            break;
 295                        }
 296
 297                    case MessagingTypes.OPEN_EXTERNAL_URL:
 298                        {
 0299                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0300                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 0301                            break;
 302                        }
 303
 304                    case MessagingTypes.OPEN_NFT_DIALOG:
 305                        {
 0306                            if (msgPayload is Protocol.OpenNftDialog payload)
 0307                                DataStore.i.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payload.token
 308                                    payload.comment), true);
 0309                            break;
 310                        }
 311
 312                    default:
 0313                        Debug.LogError($"Unknown method {method}");
 314                        break;
 315                }
 0316            }
 0317            catch (Exception e)
 318            {
 0319                throw new Exception(
 320                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 321            }
 322
 0323            if (delayedComponent != null)
 324            {
 0325                if (delayedComponent.isRoutineRunning)
 0326                    yieldInstruction = delayedComponent.yieldInstruction;
 327            }
 0328        }
 329
 330        public void ParseQuery(object payload, string sceneId)
 331        {
 0332            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 333
 0334            if (!(payload is RaycastQuery raycastQuery))
 0335                return;
 336
 0337            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 338
 0339            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0340            raycastQuery.sceneId = sceneId;
 0341            PhysicsCast.i.Query(raycastQuery);
 0342        }
 343
 0344        public void SendSceneMessage(string payload) { SendSceneMessage(payload, deferredMessagesDecoding); }
 345
 346        private void SendSceneMessage(string payload, bool enqueue)
 347        {
 0348            string[] chunks = payload.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0349            int count = chunks.Length;
 350
 0351            for (int i = 0; i < count; i++)
 352            {
 0353                if (CommonScriptableObjects.rendererState.Get() && enqueue)
 354                {
 0355                    payloadsToDecode.Enqueue(chunks[i]);
 0356                }
 357                else
 358                {
 0359                    DecodeAndEnqueue(chunks[i]);
 360                }
 361            }
 0362        }
 363
 364        private void DecodeAndEnqueue(string payload)
 365        {
 0366            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 367
 368            string sceneId;
 369            string message;
 370            string messageTag;
 371            PB_SendSceneMessage sendSceneMessage;
 372
 0373            if (!MessageDecoder.DecodePayloadChunk(payload, out sceneId, out message, out messageTag, out sendSceneMessa
 374            {
 0375                return;
 376            }
 377
 378            QueuedSceneMessage_Scene queuedMessage;
 379
 0380            if (sceneMessagesPool.Count > 0)
 0381                queuedMessage = sceneMessagesPool.Dequeue();
 382            else
 0383                queuedMessage = new QueuedSceneMessage_Scene();
 384
 0385            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 386
 0387            EnqueueSceneMessage(queuedMessage);
 388
 0389            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 0390        }
 391
 392        private IEnumerator DeferredDecoding()
 393        {
 0394            float start = Time.realtimeSinceStartup;
 395            float maxTimeForDecode;
 396
 0397            while (true)
 398            {
 0399                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 400
 0401                if (payloadsToDecode.Count > 0)
 402                {
 0403                    string payload = payloadsToDecode.Dequeue();
 404
 0405                    DecodeAndEnqueue(payload);
 406
 0407                    if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 408                        continue;
 409                }
 410
 0411                yield return null;
 0412                start = Time.unscaledTime;
 413            }
 414        }
 415
 416        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 417        {
 0418            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0419            Environment.i.messaging.manager.AddControllerIfNotExists(this, message.sceneId);
 0420            Environment.i.messaging.manager.Enqueue(isGlobalScene, message);
 0421        }
 422
 423        //======================================================================
 424
 425        #endregion
 426
 427        //======================================================================
 428
 429        //======================================================================
 430
 431        #region SCENES_MANAGEMENT
 432
 433        //======================================================================
 434        public event Action<string> OnReadyScene;
 435
 436        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 437        {
 682438            if (data == null)
 439            {
 674440                data = new LoadParcelScenesMessage.UnityParcelScene();
 441            }
 442
 682443            if (data.parcels == null)
 444            {
 674445                data.parcels = new Vector2Int[] { data.basePosition };
 446            }
 447
 682448            if (string.IsNullOrEmpty(data.id))
 449            {
 674450                data.id = $"(test):{data.basePosition.x},{data.basePosition.y}";
 451            }
 452
 682453            if (Environment.i.world.state.loadedScenes.ContainsKey(data.id))
 454            {
 12455                Debug.LogWarning($"Scene {data.id} is already loaded.");
 12456                return Environment.i.world.state.loadedScenes[data.id];
 457            }
 458
 670459            var go = new GameObject();
 670460            var newScene = go.AddComponent<ParcelScene>();
 670461            newScene.ownerController = this;
 670462            newScene.isTestScene = true;
 670463            newScene.isPersistent = true;
 670464            newScene.SetData(data);
 465
 670466            if (DCLCharacterController.i != null)
 670467                newScene.InitializeDebugPlane();
 468
 670469            Environment.i.world.state.scenesSortedByDistance.Add(newScene);
 470
 670471            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);
 472
 670473            Environment.i.world.state.loadedScenes.Add(data.id, newScene);
 670474            OnNewSceneAdded?.Invoke(newScene);
 670475            return newScene;
 476        }
 477
 478        public void SendSceneReady(string sceneId)
 479        {
 678480            Environment.i.world.state.readyScenes.Add(sceneId);
 481
 678482            Environment.i.messaging.manager.SetSceneReady(sceneId);
 483
 678484            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 485
 678486            Environment.i.world.blockersController.SetupWorldBlockers();
 487
 678488            OnReadyScene?.Invoke(sceneId);
 7489        }
 490
 14491        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 492
 8493        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 494
 495        private void SetPositionDirty(DCLCharacterPosition character)
 496        {
 1868497            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 1868498            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 499
 1868500            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 501
 1868502            if (positionDirty)
 503            {
 361504                sceneSortDirty = true;
 361505                currentGridSceneCoordinate.x = currentX;
 361506                currentGridSceneCoordinate.y = currentY;
 507
 508                // Since the first position for the character is not sent from Kernel until just-before calling
 509                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 510                // to lock the rendering accordingly...
 361511                if (!CommonScriptableObjects.rendererState.Get())
 512                {
 1513                    SortScenesByDistance();
 514                }
 515            }
 1868516        }
 517
 518        public void SortScenesByDistance()
 519        {
 876520            if (DCLCharacterController.i == null)
 0521                return;
 522
 876523            IWorldState worldState = Environment.i.world.state;
 524
 876525            worldState.currentSceneId = null;
 876526            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 527
 876528            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 529            {
 530                IParcelScene scene;
 531                bool characterIsInsideScene;
 532
 1562533                while (iterator.MoveNext())
 534                {
 844535                    scene = iterator.Current;
 536
 844537                    if (scene == null)
 538                        continue;
 539
 844540                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 541
 844542                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 543                    {
 158544                        worldState.currentSceneId = scene.sceneData.id;
 158545                        break;
 546                    }
 547                }
 718548            }
 549
 876550            if (!DataStore.i.debugConfig.isDebugMode.Get() && string.IsNullOrEmpty(worldState.currentSceneId))
 551            {
 552                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 682553                CommonScriptableObjects.rendererState.AddLock(this);
 682554            }
 555            else
 556            {
 557                // 1. Set current scene id
 194558                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 559
 560                // 2. Attempt to remove SceneController's lock on rendering
 194561                CommonScriptableObjects.rendererState.RemoveLock(this);
 562            }
 563
 876564            OnSortScenes?.Invoke();
 860565        }
 566
 567        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 568        {
 60569            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 60570            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 571
 60572            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 60573            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 574
 60575            return dist1 - dist2;
 576        }
 577
 578        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 579        {
 7277580            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 581                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 582            {
 0583                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 584
 0585                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 586            }
 7277587        }
 588
 589        public void LoadParcelScenesExecute(string scenePayload)
 590        {
 591            LoadParcelScenesMessage.UnityParcelScene scene;
 592
 27593            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 27594            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 27595            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 596
 27597            if (scene == null || scene.id == null)
 0598                return;
 599
 27600            var sceneToLoad = scene;
 601
 602
 27603            DebugConfig debugConfig = DataStore.i.debugConfig;
 604#if UNITY_EDITOR
 27605            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 606            {
 0607                SendSceneReady(sceneToLoad.id);
 0608                return;
 609            }
 610#endif
 611
 27612            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 613
 27614            IWorldState worldState = Environment.i.world.state;
 615
 27616            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 617            {
 27618                var newGameObject = new GameObject("New Scene");
 619
 27620                var newScene = newGameObject.AddComponent<ParcelScene>();
 27621                newScene.SetData(sceneToLoad);
 622
 27623                if (debugConfig.isDebugMode.Get())
 624                {
 27625                    newScene.InitializeDebugPlane();
 626                }
 627
 27628                newScene.ownerController = this;
 27629                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 27630                worldState.scenesSortedByDistance.Add(newScene);
 631
 27632                sceneSortDirty = true;
 633
 27634                OnNewSceneAdded?.Invoke(newScene);
 635
 27636                Environment.i.messaging.manager.AddControllerIfNotExists(this, newScene.sceneData.id);
 637
 27638                if (VERBOSE)
 0639                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 640            }
 641
 27642            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0643        }
 644
 645        public void UpdateParcelScenesExecute(string sceneId)
 646        {
 647            LoadParcelScenesMessage.UnityParcelScene sceneData;
 648
 0649            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0650            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0651            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 652
 0653            IWorldState worldState = Environment.i.world.state;
 654
 0655            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 656            {
 0657                ParcelScene scene = sceneInterface as ParcelScene;
 0658                scene.SetUpdateData(sceneData);
 0659            }
 660            else
 661            {
 0662                LoadParcelScenesExecute(sceneId);
 663            }
 0664        }
 665
 666        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 667        {
 16668            if (scene == null || scene.id == null)
 0669                return;
 670
 16671            var sceneToLoad = scene;
 672
 16673            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 674
 16675            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 676
 16677            if (parcelScene != null)
 16678                parcelScene.SetUpdateData(sceneToLoad);
 679
 16680            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0681        }
 682
 683        public void UnloadScene(string sceneKey)
 684        {
 1685            var queuedMessage = new QueuedSceneMessage()
 686                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 687
 1688            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 689
 1690            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 691
 1692            Environment.i.messaging.manager.RemoveController(sceneKey);
 693
 1694            IWorldState worldState = Environment.i.world.state;
 695
 1696            if (worldState.loadedScenes.ContainsKey(sceneKey))
 697            {
 1698                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1699                sceneToUnload.isPersistent = false;
 700
 1701                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0702                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 703            }
 1704        }
 705
 706        public void UnloadParcelSceneExecute(string sceneId)
 707        {
 719708            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 709
 719710            IWorldState worldState = Environment.i.world.state;
 711
 719712            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 713            {
 1714                return;
 715            }
 716
 718717            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 718
 718719            if (scene == null)
 0720                return;
 721
 718722            worldState.loadedScenes.Remove(sceneId);
 718723            worldState.globalSceneIds.Remove(sceneId);
 724
 725            // Remove the scene id from the msg. priorities list
 718726            worldState.scenesSortedByDistance.Remove(scene);
 727
 728            // Remove messaging controller for unloaded scene
 718729            Environment.i.messaging.manager.RemoveController(scene.sceneData.id);
 730
 718731            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 732
 718733            if (VERBOSE)
 734            {
 0735                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 736            }
 737
 718738            Environment.i.world.blockersController.SetupWorldBlockers();
 739
 718740            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0741        }
 742
 743        public void UnloadAllScenes(bool includePersistent = false)
 744        {
 705745            var worldState = Environment.i.world.state;
 746
 705747            if (includePersistent)
 748            {
 1420749                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 750
 2790751                foreach (var kvp in persistentScenes)
 752                {
 691753                    if (kvp.Value is ParcelScene scene)
 754                    {
 691755                        scene.isPersistent = false;
 756                    }
 757                }
 758            }
 759
 705760            var list = worldState.loadedScenes.ToArray();
 761
 2846762            for (int i = 0; i < list.Length; i++)
 763            {
 718764                UnloadParcelSceneExecute(list[i].Key);
 765            }
 705766        }
 767
 768        public void LoadParcelScenes(string decentralandSceneJSON)
 769        {
 27770            var queuedMessage = new QueuedSceneMessage()
 771            {
 772                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 773                message = decentralandSceneJSON
 774            };
 775
 27776            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 777
 27778            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 779
 27780            if (VERBOSE)
 0781                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 27782        }
 783
 784        public void UpdateParcelScenes(string decentralandSceneJSON)
 785        {
 0786            var queuedMessage = new QueuedSceneMessage()
 787                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 788
 0789            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 790
 0791            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0792        }
 793
 794        public void UnloadAllScenesQueued()
 795        {
 0796            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 797
 0798            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 799
 0800            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0801        }
 802
 803        public void CreateGlobalScene(string json)
 804        {
 805#if UNITY_EDITOR
 21806            DebugConfig debugConfig = DataStore.i.debugConfig;
 807
 21808            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0809                return;
 810#endif
 21811            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 812
 21813            string newGlobalSceneId = globalScene.id;
 814
 21815            IWorldState worldState = Environment.i.world.state;
 816
 21817            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0818                return;
 819
 21820            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 821
 21822            var newScene = newGameObject.AddComponent<GlobalScene>();
 21823            newScene.ownerController = this;
 21824            newScene.unloadWithDistance = false;
 21825            newScene.isPersistent = true;
 21826            newScene.sceneName = globalScene.name;
 21827            newScene.isPortableExperience = globalScene.isPortableExperience;
 828
 21829            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 830            {
 831                id = newGlobalSceneId,
 832                basePosition = new Vector2Int(0, 0),
 833                baseUrl = globalScene.baseUrl,
 834                contents = globalScene.contents
 835            };
 836
 21837            newScene.SetData(data);
 838
 21839            if (!string.IsNullOrEmpty(globalScene.icon))
 0840                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 841
 21842            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 21843            OnNewSceneAdded?.Invoke(newScene);
 844
 21845            if (newScene.isPortableExperience)
 0846                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 847
 21848            worldState.globalSceneIds.Add(newGlobalSceneId);
 849
 21850            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 851
 21852            if (VERBOSE)
 853            {
 0854                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 855            }
 21856        }
 857
 858        public void IsolateScene(IParcelScene sceneToActive)
 859        {
 196860            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 861            {
 49862                if (scene != sceneToActive)
 0863                    scene.GetSceneTransform().gameObject.SetActive(false);
 864            }
 49865        }
 866
 867        public void ReIntegrateIsolatedScene()
 868        {
 28869            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 870            {
 7871                scene.GetSceneTransform().gameObject.SetActive(true);
 872            }
 7873        }
 874
 875        //======================================================================
 876
 877        #endregion
 878
 879        //======================================================================
 880
 682881        public Queue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new Queue<QueuedSceneMessage_Scene>();
 882
 1339883        public bool prewarmSceneMessagesPool { get; set; } = true;
 1339884        public bool prewarmEntitiesPool { get; set; } = true;
 885
 886        private bool sceneSortDirty = false;
 682887        private bool positionDirty = true;
 888        private int lastSortFrame = 0;
 889
 890        public event Action OnSortScenes;
 891        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 892        public event Action<IParcelScene> OnNewSceneAdded;
 893        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 894        public event Action<string> OnNewPortableExperienceSceneRemoved;
 895
 682896        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 682897        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 898
 899        public const string EMPTY_GO_POOL_NAME = "Empty";
 900    }
 901}

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)