< Summary

Class:DCL.SceneController
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneController.cs
Covered lines:204
Uncovered lines:184
Coverable lines:388
Total lines:945
Line coverage:52.5% (204 of 388)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneController()0%110100%
Initialize()0%22093.33%
SetupDeferredRunners()0%110100%
>c__DisplayClass14_0/<<SetupDeferredRunners()0%330100%
PrewarmSceneMessagesPool()0%20400%
OnDebugModeSet(...)0%3.713057.14%
Dispose()0%22092.86%
Update()0%440100%
LateUpdate()0%220100%
ProcessMessage(...)0%1101000%
ProcessMessage(...)0%22564700%
ParseQuery(...)0%6200%
SendSceneMessage(...)0%6200%
Decode(...)0%20400%
DeferredDecodingAndEnqueue()0%72800%
EnqueueChunk(...)0%12300%
WatchForNewChunksToDecode()0%5.685070%
ThreadedDecodeAndEnqueue(...)0%20400%
EnqueueSceneMessage(...)0%2100%
CreateTestScene(...)0%6200%
SendSceneReady(...)0%220100%
ActivateBuilderInWorldEditScene()0%110100%
DeactivateBuilderInWorldEditScene()0%110100%
SetPositionDirty(...)0%4.024090%
SortScenesByDistance()0%880100%
SortScenesByDistanceMethod(...)0%110100%
OnCurrentSceneIdChange(...)0%64050%
LoadParcelScenesExecute(...)0%14.0713081.48%
UpdateParcelScenesExecute(...)0%20400%
UpdateParcelScenesExecute(...)0%6.396077.78%
UnloadScene(...)0%6.036090.91%
UnloadParcelSceneExecute(...)0%7.277082.35%
UnloadAllScenes(...)0%770100%
LoadParcelScenes(...)0%3.043083.33%
UpdateParcelScenes(...)0%6200%
UnloadAllScenesQueued()0%6200%
CreateGlobalScene(...)0%12.0711079.31%
IsolateScene(...)0%3.043083.33%
ReIntegrateIsolatedScene()0%220100%

File(s)

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

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using DCL.Models;
 5using DCL.Configuration;
 6using System;
 7using System.Collections;
 8using System.Collections.Concurrent;
 9using System.ComponentModel;
 10using System.Linq;
 11using System.Threading;
 12using Cysharp.Threading.Tasks;
 13using DCL.Components;
 14using UnityEngine;
 15using Debug = UnityEngine.Debug;
 16
 17namespace DCL
 18{
 19    public class SceneController : ISceneController
 20    {
 21        public static bool VERBOSE = false;
 22        const int SCENE_MESSAGES_PREWARM_COUNT = 100000;
 23
 67524        public bool enabled { get; set; } = true;
 025        internal BaseVariable<Transform> isPortableExperiencesInitialized => DataStore.i.experiencesViewer.isInitialized
 26
 27        //TODO(Brian): Move to WorldRuntimePlugin later
 28        private LoadingFeedbackController loadingFeedbackController;
 29        private Coroutine deferredDecodingCoroutine;
 30
 31        private CancellationTokenSource tokenSource;
 84832        private IMessagingControllersManager messagingControllersManager => Environment.i.messaging.manager;
 33
 34        public void Initialize()
 35        {
 65236            tokenSource = new CancellationTokenSource();
 65237            sceneSortDirty = true;
 65238            positionDirty = true;
 65239            lastSortFrame = 0;
 65240            enabled = true;
 41
 65242            loadingFeedbackController = new LoadingFeedbackController();
 43
 65244            DataStore.i.debugConfig.isDebugMode.OnChange += OnDebugModeSet;
 45
 65246            SetupDeferredRunners();
 47
 65248            DCLCharacterController.OnCharacterMoved += SetPositionDirty;
 49
 65250            CommonScriptableObjects.sceneID.OnChange += OnCurrentSceneIdChange;
 51
 52            // TODO(Brian): Move this later to Main.cs
 65253            if ( !EnvironmentSettings.RUNNING_TESTS )
 54            {
 055                PrewarmSceneMessagesPool();
 56            }
 57
 65258            Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 65259            Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.LateUpdate, LateUpdate);
 65260        }
 61        private void SetupDeferredRunners()
 62        {
 63#if UNITY_WEBGL
 64            deferredDecodingCoroutine = CoroutineStarter.Start(DeferredDecodingAndEnqueue());
 65#else
 65266            CancellationToken tokenSourceToken = tokenSource.Token;
 260867            TaskUtils.Run(async () => await WatchForNewChunksToDecode(tokenSourceToken), cancellationToken: tokenSourceT
 68#endif
 65269        }
 70
 71        private void PrewarmSceneMessagesPool()
 72        {
 073            if (prewarmSceneMessagesPool)
 74            {
 075                for (int i = 0; i < SCENE_MESSAGES_PREWARM_COUNT; i++)
 76                {
 077                    sceneMessagesPool.Enqueue(new QueuedSceneMessage_Scene());
 78                }
 79            }
 80
 081            if (prewarmEntitiesPool)
 82            {
 083                PoolManagerFactory.EnsureEntityPool(prewarmEntitiesPool);
 84            }
 085        }
 86
 87        private void OnDebugModeSet(bool current, bool previous)
 88        {
 989            if (current == previous)
 090                return;
 91
 992            if (current)
 93            {
 994                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_RedBox());
 995            }
 96            else
 97            {
 098                Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new SceneBoundsFeedbackStyle_Simple());
 99            }
 0100        }
 101
 102        public void Dispose()
 103        {
 652104            tokenSource.Cancel();
 652105            tokenSource.Dispose();
 652106            loadingFeedbackController.Dispose();
 107
 652108            Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 652109            Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.LateUpdate, LateUpdat
 110
 652111            PoolManager.i.OnGet -= Environment.i.platform.physicsSyncController.MarkDirty;
 652112            PoolManager.i.OnGet -= Environment.i.platform.cullingController.objectsTracker.MarkDirty;
 113
 652114            DCLCharacterController.OnCharacterMoved -= SetPositionDirty;
 652115            DataStore.i.debugConfig.isDebugMode.OnChange -= OnDebugModeSet;
 116
 652117            CommonScriptableObjects.sceneID.OnChange -= OnCurrentSceneIdChange;
 118
 652119            UnloadAllScenes(includePersistent: true);
 120
 652121            if (deferredDecodingCoroutine != null)
 0122                CoroutineStarter.Stop(deferredDecodingCoroutine);
 652123        }
 124
 125        public void Update()
 126        {
 6967127            if (!enabled)
 161128                return;
 129
 6806130            InputController_Legacy.i.Update();
 131
 6806132            if (lastSortFrame != Time.frameCount && sceneSortDirty)
 133            {
 648134                lastSortFrame = Time.frameCount;
 648135                sceneSortDirty = false;
 648136                SortScenesByDistance();
 137            }
 6806138        }
 139
 140        public void LateUpdate()
 141        {
 6967142            if (!enabled)
 161143                return;
 144
 6806145            Environment.i.platform.physicsSyncController.Sync();
 6806146        }
 147
 148        //======================================================================
 149
 150        #region MESSAGES_HANDLING
 151
 152        //======================================================================
 153
 154#if UNITY_EDITOR
 155        public delegate void ProcessDelegate(string sceneId, string method);
 156
 157        public event ProcessDelegate OnMessageProcessInfoStart;
 158        public event ProcessDelegate OnMessageProcessInfoEnds;
 159#endif
 0160        public bool deferredMessagesDecoding { get; set; } = false;
 161
 652162        readonly ConcurrentQueue<string> chunksToDecode = new ConcurrentQueue<string>();
 652163        private readonly ConcurrentQueue<QueuedSceneMessage_Scene> messagesToProcess = new ConcurrentQueue<QueuedSceneMe
 164
 165        const float MAX_TIME_FOR_DECODE = 0.005f;
 166
 167        public bool ProcessMessage(QueuedSceneMessage_Scene msgObject, out CustomYieldInstruction yieldInstruction)
 168        {
 0169            string sceneId = msgObject.sceneId;
 0170            string method = msgObject.method;
 171
 0172            yieldInstruction = null;
 173
 174            IParcelScene scene;
 0175            bool res = false;
 0176            IWorldState worldState = Environment.i.world.state;
 0177            DebugConfig debugConfig = DataStore.i.debugConfig;
 178
 0179            if (worldState.loadedScenes.TryGetValue(sceneId, out scene))
 180            {
 181#if UNITY_EDITOR
 0182                if (debugConfig.soloScene && scene is GlobalScene && debugConfig.ignoreGlobalScenes)
 183                {
 0184                    return false;
 185                }
 186#endif
 0187                if (!scene.GetSceneTransform().gameObject.activeInHierarchy)
 188                {
 0189                    return true;
 190                }
 191
 192#if UNITY_EDITOR
 0193                OnMessageProcessInfoStart?.Invoke(sceneId, method);
 194#endif
 0195                ProfilingEvents.OnMessageProcessStart?.Invoke(method);
 196
 0197                ProcessMessage(scene as ParcelScene, method, msgObject.payload, out yieldInstruction);
 198
 0199                ProfilingEvents.OnMessageProcessEnds?.Invoke(method);
 200
 201#if UNITY_EDITOR
 0202                OnMessageProcessInfoEnds?.Invoke(sceneId, method);
 203#endif
 204
 0205                res = true;
 0206            }
 207
 208            else
 209            {
 0210                res = false;
 211            }
 212
 0213            sceneMessagesPool.Enqueue(msgObject);
 214
 0215            return res;
 216        }
 217
 218        private void ProcessMessage(ParcelScene scene, string method, object msgPayload,
 219            out CustomYieldInstruction yieldInstruction)
 220        {
 0221            yieldInstruction = null;
 0222            IDelayedComponent delayedComponent = null;
 223
 224            try
 225            {
 226                switch (method)
 227                {
 228                    case MessagingTypes.ENTITY_CREATE:
 229                        {
 0230                            if (msgPayload is Protocol.CreateEntity payload)
 0231                                scene.CreateEntity(payload.entityId);
 232
 0233                            break;
 234                        }
 235                    case MessagingTypes.ENTITY_REPARENT:
 236                        {
 0237                            if (msgPayload is Protocol.SetEntityParent payload)
 0238                                scene.SetEntityParent(payload.entityId, payload.parentId);
 239
 0240                            break;
 241                        }
 242
 243                    case MessagingTypes.ENTITY_COMPONENT_CREATE_OR_UPDATE:
 244                        {
 0245                            if (msgPayload is Protocol.EntityComponentCreateOrUpdate payload)
 246                            {
 0247                                delayedComponent = scene.EntityComponentCreateOrUpdate(payload.entityId,
 248                                    (CLASS_ID_COMPONENT) payload.classId, payload.json) as IDelayedComponent;
 249                            }
 250
 0251                            break;
 252                        }
 253
 254                    case MessagingTypes.ENTITY_COMPONENT_DESTROY:
 255                        {
 0256                            if (msgPayload is Protocol.EntityComponentDestroy payload)
 0257                                scene.EntityComponentRemove(payload.entityId, payload.name);
 258
 0259                            break;
 260                        }
 261
 262                    case MessagingTypes.SHARED_COMPONENT_ATTACH:
 263                        {
 0264                            if (msgPayload is Protocol.SharedComponentAttach payload)
 0265                                scene.SharedComponentAttach(payload.entityId, payload.id);
 266
 0267                            break;
 268                        }
 269
 270                    case MessagingTypes.SHARED_COMPONENT_CREATE:
 271                        {
 0272                            if (msgPayload is Protocol.SharedComponentCreate payload)
 0273                                scene.SharedComponentCreate(payload.id, payload.classId);
 274
 0275                            break;
 276                        }
 277
 278                    case MessagingTypes.SHARED_COMPONENT_DISPOSE:
 279                        {
 0280                            if (msgPayload is Protocol.SharedComponentDispose payload)
 0281                                scene.SharedComponentDispose(payload.id);
 282
 0283                            break;
 284                        }
 285
 286                    case MessagingTypes.SHARED_COMPONENT_UPDATE:
 287                        {
 0288                            if (msgPayload is Protocol.SharedComponentUpdate payload)
 0289                                delayedComponent = scene.SharedComponentUpdate(payload.componentId, payload.json) as IDe
 290
 0291                            break;
 292                        }
 293
 294                    case MessagingTypes.ENTITY_DESTROY:
 295                        {
 0296                            if (msgPayload is Protocol.RemoveEntity payload)
 0297                                scene.RemoveEntity(payload.entityId);
 298
 0299                            break;
 300                        }
 301
 302                    case MessagingTypes.INIT_DONE:
 303                        {
 0304                            scene.sceneLifecycleHandler.SetInitMessagesDone();
 305
 0306                            break;
 307                        }
 308
 309                    case MessagingTypes.QUERY:
 310                        {
 0311                            if (msgPayload is QueryMessage queryMessage)
 0312                                ParseQuery(queryMessage.payload, scene.sceneData.id);
 313
 0314                            break;
 315                        }
 316
 317                    case MessagingTypes.OPEN_EXTERNAL_URL:
 318                        {
 0319                            if (msgPayload is Protocol.OpenExternalUrl payload)
 0320                                OnOpenExternalUrlRequest?.Invoke(scene, payload.url);
 321
 0322                            break;
 323                        }
 324
 325                    case MessagingTypes.OPEN_NFT_DIALOG:
 326                        {
 0327                            if (msgPayload is Protocol.OpenNftDialog payload)
 0328                                DataStore.i.common.onOpenNFTPrompt.Set(new NFTPromptModel(payload.contactAddress, payloa
 329                                    payload.comment), true);
 330
 0331                            break;
 332                        }
 333
 334                    default:
 0335                        Debug.LogError($"Unknown method {method}");
 336
 337                        break;
 338                }
 0339            }
 0340            catch (Exception e)
 341            {
 0342                throw new Exception(
 343                    $"Scene message error. scene: {scene.sceneData.id} method: {method} payload: {JsonUtility.ToJson(msg
 344            }
 345
 0346            if (delayedComponent != null)
 347            {
 0348                if (delayedComponent.isRoutineRunning)
 0349                    yieldInstruction = delayedComponent.yieldInstruction;
 350            }
 0351        }
 352
 353        public void ParseQuery(object payload, string sceneId)
 354        {
 0355            IParcelScene scene = Environment.i.world.state.loadedScenes[sceneId];
 356
 0357            if (!(payload is RaycastQuery raycastQuery))
 0358                return;
 359
 0360            Vector3 worldOrigin = raycastQuery.ray.origin + Utils.GridToWorldPosition(scene.sceneData.basePosition.x, sc
 361
 0362            raycastQuery.ray.unityOrigin = PositionUtils.WorldToUnityPosition(worldOrigin);
 0363            raycastQuery.sceneId = sceneId;
 0364            PhysicsCast.i.Query(raycastQuery);
 0365        }
 366
 367        public void SendSceneMessage(string chunk)
 368        {
 0369            var renderer = CommonScriptableObjects.rendererState.Get();
 370
 0371            if (!renderer)
 372            {
 0373                EnqueueChunk(chunk);
 0374            }
 375            else
 376            {
 0377                chunksToDecode.Enqueue(chunk);
 378            }
 0379        }
 380
 381        private QueuedSceneMessage_Scene Decode(string payload, QueuedSceneMessage_Scene queuedMessage)
 382        {
 0383            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 384
 0385            if (!MessageDecoder.DecodePayloadChunk(payload,
 386                    out string sceneId,
 387                    out string message,
 388                    out string messageTag,
 389                    out PB_SendSceneMessage sendSceneMessage))
 390            {
 0391                return null;
 392            }
 393
 0394            MessageDecoder.DecodeSceneMessage(sceneId, message, messageTag, sendSceneMessage, ref queuedMessage);
 395
 0396            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 397
 0398            return queuedMessage;
 399        }
 400
 401        private IEnumerator DeferredDecodingAndEnqueue()
 402        {
 0403            float start = Time.realtimeSinceStartup;
 404            float maxTimeForDecode;
 405
 0406            while (true)
 407            {
 0408                maxTimeForDecode = CommonScriptableObjects.rendererState.Get() ? MAX_TIME_FOR_DECODE : float.MaxValue;
 409
 0410                if (chunksToDecode.Count > 0)
 411                {
 0412                    if (chunksToDecode.TryDequeue(out string chunk))
 413                    {
 0414                        EnqueueChunk(chunk);
 415
 0416                        if (Time.realtimeSinceStartup - start < maxTimeForDecode)
 417                            continue;
 418                    }
 419                }
 420
 0421                yield return null;
 422
 0423                start = Time.unscaledTime;
 424            }
 425        }
 426        private void EnqueueChunk(string chunk)
 427        {
 0428            string[] payloads = chunk.Split(new [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0429            var count = payloads.Length;
 430
 0431            for (int i = 0; i < count; i++)
 432            {
 0433                bool availableMessage = sceneMessagesPool.TryDequeue(out QueuedSceneMessage_Scene freeMessage);
 434
 0435                if (availableMessage)
 436                {
 0437                    EnqueueSceneMessage(Decode(payloads[i], freeMessage));
 0438                }
 439                else
 440                {
 0441                    EnqueueSceneMessage(Decode(payloads[i], new QueuedSceneMessage_Scene()));
 442                }
 443            }
 0444        }
 445        private async UniTask WatchForNewChunksToDecode(CancellationToken cancellationToken)
 446        {
 8472447            while (!cancellationToken.IsCancellationRequested)
 448            {
 449                try
 450                {
 7820451                    if (chunksToDecode.Count > 0)
 452                    {
 0453                        ThreadedDecodeAndEnqueue(cancellationToken);
 454                    }
 7820455                }
 456                catch (Exception e)
 457                {
 0458                    Debug.LogException(e);
 0459                }
 460
 23460461                await UniTask.Yield();
 462            }
 652463        }
 464        private void ThreadedDecodeAndEnqueue(CancellationToken cancellationToken)
 465        {
 0466            while (chunksToDecode.TryDequeue(out string chunk))
 467            {
 0468                cancellationToken.ThrowIfCancellationRequested();
 469
 0470                string[] payloads = chunk.Split(new [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
 0471                var count = payloads.Length;
 472
 0473                for (int i = 0; i < count; i++)
 474                {
 0475                    var payload = payloads[i];
 0476                    bool availableMessage = sceneMessagesPool.TryDequeue(out QueuedSceneMessage_Scene freeMessage);
 477
 0478                    if (availableMessage)
 479                    {
 0480                        EnqueueSceneMessage(Decode(payload, freeMessage));
 0481                    }
 482                    else
 483                    {
 0484                        EnqueueSceneMessage(Decode(payload, new QueuedSceneMessage_Scene()));
 485                    }
 486                }
 0487            }
 0488        }
 489
 490        public void EnqueueSceneMessage(QueuedSceneMessage_Scene message)
 491        {
 0492            bool isGlobalScene = WorldStateUtils.IsGlobalScene(message.sceneId);
 0493            messagingControllersManager.AddControllerIfNotExists(this, message.sceneId);
 0494            messagingControllersManager.Enqueue(isGlobalScene, message);
 0495        }
 496
 497        //======================================================================
 498
 499        #endregion
 500
 501        //======================================================================
 502
 503        //======================================================================
 504
 505        #region SCENES_MANAGEMENT
 506
 507        //======================================================================
 508        public event Action<string> OnReadyScene;
 509
 510        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
 511        {
 0512            IParcelScene result = WorldStateUtils.CreateTestScene(data);
 0513            messagingControllersManager.AddControllerIfNotExists(this, data.id);
 0514            OnNewSceneAdded?.Invoke(result);
 515
 0516            return result;
 517        }
 518
 519        public void SendSceneReady(string sceneId)
 520        {
 389521            Environment.i.world.state.readyScenes.Add(sceneId);
 522
 389523            messagingControllersManager.SetSceneReady(sceneId);
 524
 389525            WebInterface.ReportControlEvent(new WebInterface.SceneReady(sceneId));
 389526            WebInterface.ReportCameraChanged(CommonScriptableObjects.cameraMode.Get(), sceneId);
 527
 389528            Environment.i.world.blockersController.SetupWorldBlockers();
 529
 389530            OnReadyScene?.Invoke(sceneId);
 2531        }
 532
 10533        public void ActivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Scen
 534
 2535        public void DeactivateBuilderInWorldEditScene() { Environment.i.world.sceneBoundsChecker.SetFeedbackStyle(new Sc
 536
 537        private void SetPositionDirty(DCLCharacterPosition character)
 538        {
 5004539            var currentX = (int) Math.Floor(character.worldPosition.x / ParcelSettings.PARCEL_SIZE);
 5004540            var currentY = (int) Math.Floor(character.worldPosition.z / ParcelSettings.PARCEL_SIZE);
 541
 5004542            positionDirty = currentX != currentGridSceneCoordinate.x || currentY != currentGridSceneCoordinate.y;
 543
 5004544            if (positionDirty)
 545            {
 578546                sceneSortDirty = true;
 578547                currentGridSceneCoordinate.x = currentX;
 578548                currentGridSceneCoordinate.y = currentY;
 549
 550                // Since the first position for the character is not sent from Kernel until just-before calling
 551                // the rendering activation from Kernel, we need to sort the scenes to get the current scene id
 552                // to lock the rendering accordingly...
 578553                if (!CommonScriptableObjects.rendererState.Get())
 554                {
 0555                    SortScenesByDistance();
 556                }
 557            }
 5004558        }
 559
 560        public void SortScenesByDistance()
 561        {
 648562            if (DCLCharacterController.i == null)
 63563                return;
 564
 585565            IWorldState worldState = Environment.i.world.state;
 566
 585567            worldState.currentSceneId = null;
 585568            worldState.scenesSortedByDistance.Sort(SortScenesByDistanceMethod);
 569
 585570            using (var iterator = Environment.i.world.state.scenesSortedByDistance.GetEnumerator())
 571            {
 572                IParcelScene scene;
 573                bool characterIsInsideScene;
 574
 603575                while (iterator.MoveNext())
 576                {
 23577                    scene = iterator.Current;
 578
 23579                    if (scene == null)
 580                        continue;
 581
 23582                    characterIsInsideScene = WorldStateUtils.IsCharacterInsideScene(scene);
 583
 23584                    if (!worldState.globalSceneIds.Contains(scene.sceneData.id) && characterIsInsideScene)
 585                    {
 5586                        worldState.currentSceneId = scene.sceneData.id;
 587
 5588                        break;
 589                    }
 590                }
 580591            }
 592
 585593            if (!DataStore.i.debugConfig.isDebugMode.Get() && string.IsNullOrEmpty(worldState.currentSceneId))
 594            {
 595                // When we don't know the current scene yet, we must lock the rendering from enabling until it is set
 577596                CommonScriptableObjects.rendererState.AddLock(this);
 577597            }
 598            else
 599            {
 600                // 1. Set current scene id
 8601                CommonScriptableObjects.sceneID.Set(worldState.currentSceneId);
 602
 603                // 2. Attempt to remove SceneController's lock on rendering
 8604                CommonScriptableObjects.rendererState.RemoveLock(this);
 605            }
 606
 585607            OnSortScenes?.Invoke();
 585608        }
 609
 610        private int SortScenesByDistanceMethod(IParcelScene sceneA, IParcelScene sceneB)
 611        {
 21612            sortAuxiliaryVector = sceneA.sceneData.basePosition - currentGridSceneCoordinate;
 21613            int dist1 = sortAuxiliaryVector.sqrMagnitude;
 614
 21615            sortAuxiliaryVector = sceneB.sceneData.basePosition - currentGridSceneCoordinate;
 21616            int dist2 = sortAuxiliaryVector.sqrMagnitude;
 617
 21618            return dist1 - dist2;
 619        }
 620
 621        private void OnCurrentSceneIdChange(string newSceneId, string prevSceneId)
 622        {
 15623            if (Environment.i.world.state.TryGetScene(newSceneId, out IParcelScene newCurrentScene)
 624                && !(newCurrentScene as ParcelScene).sceneLifecycleHandler.isReady)
 625            {
 0626                CommonScriptableObjects.rendererState.AddLock(newCurrentScene);
 627
 0628                (newCurrentScene as ParcelScene).sceneLifecycleHandler.OnSceneReady += (readyScene) => { CommonScriptabl
 629            }
 15630        }
 631
 632        public void LoadParcelScenesExecute(string scenePayload)
 633        {
 634            LoadParcelScenesMessage.UnityParcelScene scene;
 635
 26636            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_LOAD);
 26637            scene = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(scenePayload);
 26638            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 639
 26640            if (scene == null || scene.id == null)
 0641                return;
 642
 26643            var sceneToLoad = scene;
 644
 26645            DebugConfig debugConfig = DataStore.i.debugConfig;
 646#if UNITY_EDITOR
 26647            if (debugConfig.soloScene && sceneToLoad.basePosition.ToString() != debugConfig.soloSceneCoords.ToString())
 648            {
 0649                SendSceneReady(sceneToLoad.id);
 650
 0651                return;
 652            }
 653#endif
 654
 26655            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_LOAD);
 656
 26657            IWorldState worldState = Environment.i.world.state;
 658
 26659            if (!worldState.loadedScenes.ContainsKey(sceneToLoad.id))
 660            {
 26661                var newGameObject = new GameObject("New Scene");
 662
 26663                var newScene = newGameObject.AddComponent<ParcelScene>();
 26664                newScene.SetData(sceneToLoad);
 665
 26666                if (debugConfig.isDebugMode.Get())
 667                {
 26668                    newScene.InitializeDebugPlane();
 669                }
 670
 26671                worldState.loadedScenes.Add(sceneToLoad.id, newScene);
 26672                worldState.scenesSortedByDistance.Add(newScene);
 673
 26674                sceneSortDirty = true;
 675
 26676                OnNewSceneAdded?.Invoke(newScene);
 677
 26678                messagingControllersManager.AddControllerIfNotExists(this, newScene.sceneData.id);
 679
 26680                if (VERBOSE)
 0681                    Debug.Log($"{Time.frameCount} : Load parcel scene {newScene.sceneData.basePosition}");
 682            }
 683
 26684            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_LOAD);
 0685        }
 686
 687        public void UpdateParcelScenesExecute(string sceneId)
 688        {
 689            LoadParcelScenesMessage.UnityParcelScene sceneData;
 690
 0691            ProfilingEvents.OnMessageDecodeStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 0692            sceneData = Utils.SafeFromJson<LoadParcelScenesMessage.UnityParcelScene>(sceneId);
 0693            ProfilingEvents.OnMessageDecodeEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 694
 0695            IWorldState worldState = Environment.i.world.state;
 696
 0697            if (worldState.TryGetScene(sceneData.id, out IParcelScene sceneInterface))
 698            {
 0699                ParcelScene scene = sceneInterface as ParcelScene;
 0700                scene.SetUpdateData(sceneData);
 0701            }
 702            else
 703            {
 0704                LoadParcelScenesExecute(sceneId);
 705            }
 0706        }
 707
 708        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
 709        {
 15710            if (scene == null || scene.id == null)
 0711                return;
 712
 15713            var sceneToLoad = scene;
 714
 15715            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
 716
 15717            ParcelScene parcelScene = Environment.i.world.state.GetScene(sceneToLoad.id) as ParcelScene;
 718
 15719            if (parcelScene != null)
 15720                parcelScene.SetUpdateData(sceneToLoad);
 721
 15722            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
 0723        }
 724
 725        public void UnloadScene(string sceneKey)
 726        {
 1727            var queuedMessage = new QueuedSceneMessage()
 728                { type = QueuedSceneMessage.Type.UNLOAD_PARCEL, message = sceneKey };
 729
 1730            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 731
 1732            messagingControllersManager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 733
 1734            messagingControllersManager.RemoveController(sceneKey);
 735
 1736            IWorldState worldState = Environment.i.world.state;
 737
 1738            if (worldState.loadedScenes.ContainsKey(sceneKey))
 739            {
 1740                ParcelScene sceneToUnload = worldState.GetScene(sceneKey) as ParcelScene;
 1741                sceneToUnload.isPersistent = false;
 742
 1743                if (sceneToUnload is GlobalScene globalScene && globalScene.isPortableExperience)
 0744                    OnNewPortableExperienceSceneRemoved?.Invoke(sceneKey);
 745            }
 1746        }
 747
 748        public void UnloadParcelSceneExecute(string sceneId)
 749        {
 413750            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_DESTROY);
 751
 413752            IWorldState worldState = Environment.i.world.state;
 753
 413754            if (!worldState.Contains(sceneId) || worldState.loadedScenes[sceneId].isPersistent)
 755            {
 0756                return;
 757            }
 758
 413759            var scene = worldState.loadedScenes[sceneId] as ParcelScene;
 760
 413761            if (scene == null)
 9762                return;
 763
 404764            worldState.loadedScenes.Remove(sceneId);
 404765            worldState.globalSceneIds.Remove(sceneId);
 766
 767            // Remove the scene id from the msg. priorities list
 404768            worldState.scenesSortedByDistance.Remove(scene);
 769
 770            // Remove messaging controller for unloaded scene
 404771            messagingControllersManager.RemoveController(scene.sceneData.id);
 772
 404773            scene.Cleanup(!CommonScriptableObjects.rendererState.Get());
 774
 404775            if (VERBOSE)
 776            {
 0777                Debug.Log($"{Time.frameCount} : Destroying scene {scene.sceneData.basePosition}");
 778            }
 779
 404780            Environment.i.world.blockersController.SetupWorldBlockers();
 781
 404782            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_DESTROY);
 0783        }
 784
 785        public void UnloadAllScenes(bool includePersistent = false)
 786        {
 654787            var worldState = Environment.i.world.state;
 788
 654789            if (includePersistent)
 790            {
 1066791                var persistentScenes = worldState.loadedScenes.Where(x => x.Value.isPersistent);
 792
 2082793                foreach (var kvp in persistentScenes)
 794                {
 387795                    if (kvp.Value is ParcelScene scene)
 796                    {
 387797                        scene.isPersistent = false;
 798                    }
 799                }
 800            }
 801
 654802            var list = worldState.loadedScenes.ToArray();
 803
 2132804            for (int i = 0; i < list.Length; i++)
 805            {
 412806                UnloadParcelSceneExecute(list[i].Key);
 807            }
 654808        }
 809
 810        public void LoadParcelScenes(string decentralandSceneJSON)
 811        {
 26812            var queuedMessage = new QueuedSceneMessage()
 813            {
 814                type = QueuedSceneMessage.Type.LOAD_PARCEL,
 815                message = decentralandSceneJSON
 816            };
 817
 26818            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_LOAD);
 819
 26820            messagingControllersManager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 821
 26822            if (VERBOSE)
 0823                Debug.Log($"{Time.frameCount} : Load parcel scene queue {decentralandSceneJSON}");
 26824        }
 825
 826        public void UpdateParcelScenes(string decentralandSceneJSON)
 827        {
 0828            var queuedMessage = new QueuedSceneMessage()
 829                { type = QueuedSceneMessage.Type.UPDATE_PARCEL, message = decentralandSceneJSON };
 830
 0831            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_UPDATE);
 832
 0833            messagingControllersManager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0834        }
 835
 836        public void UnloadAllScenesQueued()
 837        {
 0838            var queuedMessage = new QueuedSceneMessage() { type = QueuedSceneMessage.Type.UNLOAD_SCENES };
 839
 0840            ProfilingEvents.OnMessageWillQueue?.Invoke(MessagingTypes.SCENE_DESTROY);
 841
 0842            Environment.i.messaging.manager.ForceEnqueueToGlobal(MessagingBusType.INIT, queuedMessage);
 0843        }
 844
 845        public void CreateGlobalScene(string json)
 846        {
 847#if UNITY_EDITOR
 1848            DebugConfig debugConfig = DataStore.i.debugConfig;
 849
 1850            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
 0851                return;
 852#endif
 1853            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson<CreateGlobalSceneMessage>(json);
 854
 1855            if (globalScene.isPortableExperience && !isPortableExperiencesInitialized.Get())
 0856                return;
 857
 1858            string newGlobalSceneId = globalScene.id;
 859
 1860            IWorldState worldState = Environment.i.world.state;
 861
 1862            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
 0863                return;
 864
 1865            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);
 866
 1867            var newScene = newGameObject.AddComponent<GlobalScene>();
 1868            newScene.unloadWithDistance = false;
 1869            newScene.isPersistent = true;
 1870            newScene.sceneName = globalScene.name;
 1871            newScene.isPortableExperience = globalScene.isPortableExperience;
 872
 1873            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
 874            {
 875                id = newGlobalSceneId,
 876                basePosition = new Vector2Int(0, 0),
 877                baseUrl = globalScene.baseUrl,
 878                contents = globalScene.contents
 879            };
 880
 1881            newScene.SetData(data);
 882
 1883            if (!string.IsNullOrEmpty(globalScene.icon))
 884            {
 0885                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
 886            }
 887
 1888            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
 1889            OnNewSceneAdded?.Invoke(newScene);
 890
 1891            if (newScene.isPortableExperience)
 0892                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
 893
 1894            worldState.globalSceneIds.Add(newGlobalSceneId);
 895
 1896            messagingControllersManager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);
 897
 1898            if (VERBOSE)
 899            {
 0900                Debug.Log($"Creating Global scene {newGlobalSceneId}");
 901            }
 1902        }
 903
 904        public void IsolateScene(IParcelScene sceneToActive)
 905        {
 152906            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 907            {
 38908                if (scene != sceneToActive)
 0909                    scene.GetSceneTransform().gameObject.SetActive(false);
 910            }
 38911        }
 912
 913        public void ReIntegrateIsolatedScene()
 914        {
 20915            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 916            {
 5917                scene.GetSceneTransform().gameObject.SetActive(true);
 918            }
 5919        }
 920
 921        //======================================================================
 922
 923        #endregion
 924
 925        //======================================================================
 926
 652927        public ConcurrentQueue<QueuedSceneMessage_Scene> sceneMessagesPool { get; } = new ConcurrentQueue<QueuedSceneMes
 928
 652929        public bool prewarmSceneMessagesPool { get; set; } = true;
 652930        public bool prewarmEntitiesPool { get; set; } = true;
 931
 932        private bool sceneSortDirty = false;
 652933        private bool positionDirty = true;
 934        private int lastSortFrame = 0;
 935
 936        public event Action OnSortScenes;
 937        public event Action<IParcelScene, string> OnOpenExternalUrlRequest;
 938        public event Action<IParcelScene> OnNewSceneAdded;
 939        public event Action<IParcelScene> OnNewPortableExperienceSceneAdded;
 940        public event Action<string> OnNewPortableExperienceSceneRemoved;
 941
 652942        private Vector2Int currentGridSceneCoordinate = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSet
 652943        private Vector2Int sortAuxiliaryVector = new Vector2Int(EnvironmentSettings.MORDOR_SCALAR, EnvironmentSettings.M
 944    }
 945}

Methods/Properties

enabled()
enabled(System.Boolean)
SceneController()
isPortableExperiencesInitialized()
messagingControllersManager()
Initialize()
SetupDeferredRunners()
>c__DisplayClass14_0/<<SetupDeferredRunners()
PrewarmSceneMessagesPool()
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)
Decode(System.String, DCL.QueuedSceneMessage_Scene)
DeferredDecodingAndEnqueue()
EnqueueChunk(System.String)
WatchForNewChunksToDecode()
ThreadedDecodeAndEnqueue(System.Threading.CancellationToken)
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)