< Summary

Class:DCL.Builder.SceneManager
Assembly:BuilderInWorld
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/BuilderInWorld/Scripts/SceneManager/SceneManager.cs
Covered lines:197
Uncovered lines:125
Coverable lines:322
Total lines:678
Line coverage:61.1% (197 of 322)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneManager()0%110100%
Initialize(...)0%110100%
Dispose()0%770100%
ConfigureLoadingController()0%110100%
NextState()0%660100%
SendManifestToScene()0%152.4515015.15%
WebRequestCreated(...)0%6200%
Update()0%30500%
OnPlayerTeleportedToEditScene(...)0%2100%
StartFlowFromProject(...)0%6200%
StartFlowFromLandCoords(...)0%2100%
ShowBuilderLoading()0%110100%
HideBuilderLoading()0%2100%
StartExitMode()0%7.195055.56%
FindSceneToEdit()0%3.033085.71%
UpdateLandsWithAccess()0%110100%
CatalogLoaded()0%220100%
StartFlow(...)0%330100%
GetCatalog()0%220100%
ChangeEditModeStatusByShortcut(...)0%8.056061.54%
CheckSceneToEditByShorcut()0%110100%
NewSceneAdded(...)0%22090%
NewSceneReady(...)0%220100%
UserHasPermissionOnParcelScene(...)0%5.25080%
GetDeployedSceneFromParcel(...)0%42600%
GetDeployedSceneFromParcel(...)0%12.415033.33%
IsParcelSceneDeployedFromSDK(...)0%660100%
EnterEditMode()0%110100%
ExitEditMode()0%110100%
StartFlowFromLandWithPermission(...)0%5.935066.67%
StartFromLand(...)0%110100%
LoadScene()0%110100%
ActivateLandAccessBackgroundChecker()0%3.043083.33%
UpdateSceneLoadingProgress(...)0%2100%
UpdateCatalogLoadingProgress(...)0%2100%
ExitAfterCharacterTeleport(...)0%110100%
CheckLandsAccess()0%3.333066.67%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/BuilderInWorld/Scripts/SceneManager/SceneManager.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Linq;
 5using DCL.Camera;
 6using DCL.Configuration;
 7using DCL.Controllers;
 8using DCL.Helpers;
 9using UnityEngine;
 10using Cysharp.Threading.Tasks;
 11using DCL.Builder.Manifest;
 12using DCL.Components;
 13using DCL.Interface;
 14using DCL.Models;
 15using Newtonsoft.Json;
 16using Newtonsoft.Json.Linq;
 17
 18namespace DCL.Builder
 19{
 20    public class SceneManager : ISceneManager
 21    {
 22        internal static bool BYPASS_LAND_OWNERSHIP_CHECK = false;
 23        private const float MAX_DISTANCE_STOP_TRYING_TO_ENTER = 16;
 24
 25        private const string SOURCE_BUILDER_PANEl = "BuilderPanel";
 26        private const string SOURCE_SHORTCUT = "Shortcut";
 27
 28        public enum State
 29        {
 30            IDLE = 0,
 31            LOADING_CATALOG = 1,
 32            CATALOG_LOADED = 2,
 33            LOADING_SCENE = 3,
 34            SCENE_LOADED = 4,
 35            EDITING = 5
 36        }
 37
 38        internal State currentState = State.IDLE;
 39
 40        private InputAction_Trigger editModeChangeInputAction;
 41
 42        internal IContext context;
 43        internal string sceneToEditId;
 44        private UserProfile userProfile;
 45        internal Coroutine updateLandsWithAcessCoroutine;
 46
 47        private bool alreadyAskedForLandPermissions = false;
 48        private Vector3 askPermissionLastPosition;
 49        private IWebRequestAsyncOperation catalogAsyncOp;
 50        internal bool isWaitingForPermission = false;
 51        internal IBuilderScene sceneToEdit;
 52        private BiwSceneMetricsAnalyticsHelper sceneMetricsAnalyticsHelper;
 53        private InputController inputController;
 54        internal BuilderInWorldBridge builderInWorldBridge;
 55        internal IInitialStateManager initialStateManager;
 56        internal IBuilderInWorldLoadingController initialLoadingController;
 57        private float beginStartFlowTimeStamp = 0;
 58        internal bool catalogLoaded = false;
 1459        internal List<string> portableExperiencesToResume = new List<string>();
 60        private BuilderInWorldBridge bridge;
 61
 62        public void Initialize(IContext context)
 63        {
 1464            this.context = context;
 1465            editModeChangeInputAction = context.inputsReferencesAsset.editModeChangeInputAction;
 1466            editModeChangeInputAction.OnTriggered += ChangeEditModeStatusByShortcut;
 1467            inputController = context.sceneReferences.inputController;
 68
 1469            builderInWorldBridge = context.sceneReferences.biwBridgeGameObject.GetComponent<BuilderInWorldBridge>();
 1470            userProfile = UserProfile.GetOwnUserProfile();
 71
 1472            bridge = context.sceneReferences.biwBridgeGameObject.GetComponent<BuilderInWorldBridge>();
 73
 1474            context.editorContext.editorHUD.OnStartExitAction += StartExitMode;
 1475            context.editorContext.editorHUD.OnLogoutAction += ExitEditMode;
 76
 1477            BIWTeleportAndEdit.OnTeleportEnd += OnPlayerTeleportedToEditScene;
 1478            context.builderAPIController.OnWebRequestCreated += WebRequestCreated;
 79
 1480            initialStateManager = new InitialStateManager();
 81
 1482            ConfigureLoadingController();
 1483        }
 84
 85        public void Dispose()
 86        {
 1487            if (context.editorContext.editorHUD != null)
 88            {
 1489                context.editorContext.editorHUD.OnStartExitAction -= StartExitMode;
 1490                context.editorContext.editorHUD.OnLogoutAction -= ExitEditMode;
 91            }
 92
 1493            sceneMetricsAnalyticsHelper?.Dispose();
 94
 1495            initialLoadingController?.Dispose();
 96
 1497            Environment.i.world.sceneController.OnNewSceneAdded -= NewSceneAdded;
 1498            Environment.i.world.sceneController.OnReadyScene -= NewSceneReady;
 1499            BIWTeleportAndEdit.OnTeleportEnd -= OnPlayerTeleportedToEditScene;
 14100            DCLCharacterController.OnPositionSet -= ExitAfterCharacterTeleport;
 101
 14102            if (sceneToEdit?.scene != null)
 8103                sceneToEdit.scene.OnLoadingStateUpdated -= UpdateSceneLoadingProgress;
 104
 14105            editModeChangeInputAction.OnTriggered -= ChangeEditModeStatusByShortcut;
 14106            context.builderAPIController.OnWebRequestCreated -= WebRequestCreated;
 107
 14108            CoroutineStarter.Stop(updateLandsWithAcessCoroutine);
 14109        }
 110
 111        private void ConfigureLoadingController()
 112        {
 14113            initialLoadingController = new BuilderInWorldLoadingController();
 14114            initialLoadingController.Initialize();
 14115        }
 116
 117        public void NextState()
 118        {
 15119            currentState++;
 15120            switch (currentState)
 121            {
 122                case State.LOADING_CATALOG:
 4123                    if (!catalogLoaded)
 1124                        GetCatalog();
 125                    else
 3126                        NextState();
 3127                    break;
 128
 129                case State.CATALOG_LOADED:
 5130                    NextState();
 5131                    break;
 132
 133                case State.LOADING_SCENE:
 5134                    LoadScene();
 5135                    break;
 136
 137                case State.SCENE_LOADED:
 1138                    EnterEditMode();
 139                    break;
 140            }
 1141        }
 142
 143        private void SendManifestToScene()
 144        {
 145            //We remove the old assets to they don't collide with the new ones
 1146            BIWUtils.RemoveAssetsFromCurrentScene();
 147
 148            //We add the assets from the scene to the catalog
 1149            var assets = sceneToEdit.manifest.scene.assets.Values.ToArray();
 1150            AssetCatalogBridge.i.AddScenesObjectToSceneCatalog(assets);
 151
 152            //We prepare the mappings to the scenes
 1153            Dictionary<string, string> contentDictionary = new Dictionary<string, string>();
 154
 2155            foreach (var sceneObject in assets)
 156            {
 0157                foreach (var content in sceneObject.contents)
 158                {
 0159                    if (!contentDictionary.ContainsKey(content.Key))
 0160                        contentDictionary.Add(content.Key, content.Value);
 161                }
 162            }
 163
 164            //We add the mappings to the scene
 1165            BIWUtils.AddSceneMappings(contentDictionary, BIWUrlUtils.GetUrlSceneObjectContent(), sceneToEdit.scene.scene
 166
 167            // We iterate all the entities to create the entity in the scene
 2168            foreach (BuilderEntity builderEntity in sceneToEdit.manifest.scene.entities.Values)
 169            {
 0170                var entity = sceneToEdit.scene.CreateEntity(builderEntity.id.GetHashCode());
 171
 0172                bool nameComponentFound = false;
 173                // We iterate all the id of components in the entity, to add the component
 0174                foreach (string idComponent in builderEntity.components)
 175                {
 176                    //This shouldn't happen, the component should be always in the scene, but just in case
 0177                    if (!sceneToEdit.manifest.scene.components.ContainsKey(idComponent))
 178                        continue;
 179
 180                    // We get the component from the scene and create it in the entity
 0181                    BuilderComponent component = sceneToEdit.manifest.scene.components[idComponent];
 182
 0183                    switch (component.type)
 184                    {
 185                        case "Transform":
 186                            DCLTransform.Model model;
 187
 188                            try
 189                            {
 190                                // This is a very ugly way to handle the things because some times the data can come ser
 191                                // It will be deleted when we create the new builder server that only have 1 way to hand
 0192                                model = JsonConvert.DeserializeObject<DCLTransform.Model>(component.data.ToString());
 0193                            }
 0194                            catch (Exception e)
 195                            {
 196                                // We may have create the component so de data is not serialized
 0197                                model = JsonConvert.DeserializeObject<DCLTransform.Model>(JsonConvert.SerializeObject(co
 0198                            }
 199
 0200                            EntityComponentsUtils.AddTransformComponent(sceneToEdit.scene, entity, model);
 0201                            break;
 202
 203                        case "GLTFShape":
 204                            LoadableShape.Model gltfModel;
 205
 206                            try
 207                            {
 208                                // This is a very ugly way to handle the things because some times the data can come ser
 209                                // It will be deleted when we create the new builder server that only have 1 way to hand
 0210                                gltfModel = JsonConvert.DeserializeObject<LoadableShape.Model>(component.data.ToString()
 0211                            }
 0212                            catch (Exception e)
 213                            {
 214                                // We may have create the component so de data is not serialized
 0215                                gltfModel = (GLTFShape.Model)component.data;
 0216                            }
 217
 0218                            EntityComponentsUtils.AddGLTFComponent(sceneToEdit.scene, entity, gltfModel, component.id);
 0219                            break;
 220
 221                        case "NFTShape":
 222                            //Builder use a different way to load the NFT so we convert it to our system
 0223                            JObject jObject = JObject.Parse(component.data.ToString());
 224
 0225                            string url = jObject["url"].ToString();
 0226                            string assedId = url.Replace(BIWSettings.NFT_ETHEREUM_PROTOCOL, "");
 0227                            int index = assedId.IndexOf("/", StringComparison.Ordinal);
 0228                            string partToremove = assedId.Substring(index);
 0229                            assedId = assedId.Replace(partToremove, "");
 230
 0231                            NFTShape.Model nftModel = new NFTShape.Model();
 0232                            nftModel.color = new Color(0.6404918f, 0.611472f, 0.8584906f);
 0233                            nftModel.src = url;
 0234                            nftModel.assetId = assedId;
 235
 0236                            EntityComponentsUtils.AddNFTShapeComponent(sceneToEdit.scene, entity, nftModel, component.id
 0237                            break;
 238
 239                        case "Name":
 0240                            nameComponentFound = true;
 0241                            DCLName.Model nameModel = JsonConvert.DeserializeObject<DCLName.Model>(component.data.ToStri
 0242                            nameModel.builderValue = builderEntity.name;
 0243                            EntityComponentsUtils.AddNameComponent(sceneToEdit.scene , entity, nameModel, Guid.NewGuid()
 0244                            break;
 245
 246                        case "LockedOnEdit":
 0247                            DCLLockedOnEdit.Model lockedModel = JsonConvert.DeserializeObject<DCLLockedOnEdit.Model>(com
 0248                            EntityComponentsUtils.AddLockedOnEditComponent(sceneToEdit.scene , entity, lockedModel, Guid
 0249                            break;
 250                        case "Script":
 0251                            SmartItemComponent.Model smartModel = JsonConvert.DeserializeObject<SmartItemComponent.Model
 0252                            sceneToEdit.scene.componentsManagerLegacy.EntityComponentCreateOrUpdate(entity.entityId, CLA
 253                            break;
 254                    }
 255                }
 256
 257                // We need to mantain the builder name of the entity, so we create the equivalent part in biw. We do thi
 0258                if (!nameComponentFound)
 259                {
 0260                    DCLName.Model nameModel = new DCLName.Model();
 0261                    nameModel.value = builderEntity.name;
 0262                    nameModel.builderValue = builderEntity.name;
 0263                    EntityComponentsUtils.AddNameComponent(sceneToEdit.scene , entity, nameModel, Guid.NewGuid().ToStrin
 264                }
 265            }
 1266        }
 267
 268        public void WebRequestCreated(IWebRequestAsyncOperation webRequest)
 269        {
 0270            if (currentState == State.LOADING_CATALOG)
 0271                catalogAsyncOp = webRequest;
 0272        }
 273
 274        public void Update()
 275        {
 0276            if (currentState != State.LOADING_CATALOG)
 0277                return;
 278
 0279            if (catalogAsyncOp?.webRequest != null)
 0280                UpdateCatalogLoadingProgress(catalogAsyncOp.webRequest.downloadProgress * 100);
 0281        }
 282
 283        private void OnPlayerTeleportedToEditScene(Vector2Int coords)
 284        {
 0285            StartFlowFromLandWithPermission(Environment.i.world.state.GetScene(coords), SOURCE_BUILDER_PANEl);
 0286        }
 287
 288        public void StartFlowFromProject(Manifest.Manifest manifest)
 289        {
 0290            bool hasBeenCreatedThisSession = !string.IsNullOrEmpty(DataStore.i.builderInWorld.lastProjectIdCreated.Get()
 0291            DataStore.i.builderInWorld.lastProjectIdCreated.Set("");
 292
 0293            BuilderScene builderScene = new BuilderScene(manifest, IBuilderScene.SceneType.PROJECT,hasBeenCreatedThisSes
 0294            StartFlow(builderScene, SOURCE_BUILDER_PANEl);
 0295        }
 296
 297        public void StartFlowFromLandCoords(Vector2Int coords)
 298        {
 0299            Scene deployedScene = GetDeployedSceneFromParcel(coords);
 0300            Vector2Int parcelSize = BIWUtils.GetSceneSize(deployedScene.parcels);
 301
 0302            StartFromLand(deployedScene.@base, deployedScene, parcelSize, SOURCE_BUILDER_PANEl);
 0303        }
 304
 305        public void ShowBuilderLoading()
 306        {
 1307            initialLoadingController.Show();
 1308            initialLoadingController.SetPercentage(0f);
 1309        }
 310
 311        public void HideBuilderLoading()
 312        {
 0313            initialLoadingController.Hide();
 0314        }
 315
 316        public void StartExitMode()
 317        {
 2318            context.cameraController.TakeSceneScreenshotFromResetPosition((sceneSnapshot) =>
 319            {
 0320                if (sceneSnapshot != null)
 321                {
 0322                    sceneToEdit.sceneScreenshotTexture = sceneSnapshot;
 323
 0324                    if (sceneToEdit.manifest != null)
 0325                        context.builderAPIController.SetThumbnail(sceneToEdit.manifest.project.id, sceneSnapshot);
 326                }
 0327            });
 328
 2329            if (context.editorContext.editorHUD == null )
 0330                return;
 331
 2332            if (context.editorContext.publishController.HasUnpublishChanges() && sceneToEdit.sceneType == IBuilderScene.
 333            {
 0334                if (sceneToEdit.sceneType == IBuilderScene.SceneType.LAND)
 0335                    context.editorContext.editorHUD.ConfigureConfirmationModal(
 336                        BIWSettings.EXIT_MODAL_TITLE,
 337                        BIWSettings.EXIT_WITHOUT_PUBLISH_MODAL_SUBTITLE,
 338                        BIWSettings.EXIT_WITHOUT_PUBLISH_MODAL_CANCEL_BUTTON,
 339                        BIWSettings.EXIT_WITHOUT_PUBLISH_MODAL_CONFIRM_BUTTON);
 0340            }
 341            else
 342            {
 2343                context.editorContext.editorHUD.ConfigureConfirmationModal(
 344                    BIWSettings.EXIT_MODAL_TITLE,
 345                    BIWSettings.EXIT_MODAL_SUBTITLE,
 346                    BIWSettings.EXIT_MODAL_CANCEL_BUTTON,
 347                    BIWSettings.EXIT_MODAL_CONFIRM_BUTTON);
 348            }
 2349        }
 350
 351        public IParcelScene FindSceneToEdit()
 352        {
 6353            foreach (IParcelScene scene in Environment.i.world.state.GetScenesSortedByDistance())
 354            {
 2355                if (WorldStateUtils.IsCharacterInsideScene(scene))
 2356                    return scene;
 357            }
 358
 0359            return null;
 2360        }
 361
 362        private void UpdateLandsWithAccess()
 363        {
 2364            ICatalyst catalyst = Environment.i.platform.serviceProviders.catalyst;
 2365            ITheGraph theGraph = Environment.i.platform.serviceProviders.theGraph;
 366
 2367            DeployedScenesFetcher.FetchLandsFromOwner(
 368                                     catalyst,
 369                                     theGraph,
 370                                     userProfile.ethAddress,
 371                                     KernelConfig.i.Get().network,
 372                                     BIWSettings.CACHE_TIME_LAND,
 373                                     BIWSettings.CACHE_TIME_SCENES)
 374                                 .Then(lands =>
 375                                 {
 0376                                     DataStore.i.builderInWorld.landsWithAccess.Set(lands.ToArray(), true);
 0377                                     if (isWaitingForPermission && Vector3.Distance(askPermissionLastPosition, DCLCharac
 378                                     {
 0379                                         CheckSceneToEditByShorcut();
 380                                     }
 381
 0382                                     isWaitingForPermission = false;
 0383                                     alreadyAskedForLandPermissions = true;
 0384                                 });
 2385        }
 386
 387        internal void CatalogLoaded()
 388        {
 5389            catalogLoaded = true;
 5390            if ( context.editorContext.editorHUD != null)
 5391                context.editorContext.editorHUD.RefreshCatalogContent();
 5392            NextState();
 5393        }
 394
 395        internal void StartFlow(IBuilderScene targetScene, string source)
 396        {
 2397            if (currentState != State.IDLE || targetScene == null)
 1398                return;
 399
 1400            DataStore.i.exploreV2.isOpen.Set(false);
 401
 1402            sceneToEditId = targetScene.manifest.project.scene_id;
 1403            sceneToEdit = targetScene;
 404
 1405            NotificationsController.i.allowNotifications = false;
 1406            CommonScriptableObjects.allUIHidden.Set(true);
 1407            NotificationsController.i.allowNotifications = true;
 1408            inputController.inputTypeMode = InputTypeMode.BUILD_MODE_LOADING;
 409
 410            // We prepare the bridge for the current scene
 1411            bridge.SetScene(targetScene);
 412
 413            // We configure the loading part
 1414            ShowBuilderLoading();
 415
 1416            DataStore.i.common.appMode.Set(AppMode.BUILDER_IN_WORLD_EDITION);
 1417            DataStore.i.virtualAudioMixer.sceneSFXVolume.Set(0f);
 1418            BIWAnalytics.StartEditorFlow(source);
 1419            beginStartFlowTimeStamp = Time.realtimeSinceStartup;
 420
 1421            NextState();
 1422        }
 423
 424        internal void GetCatalog()
 425        {
 3426            BIWNFTController.i.StartFetchingNft();
 3427            var catalogPromise = context.builderAPIController.GetCompleteCatalog(userProfile.ethAddress);
 3428            catalogPromise.Then(x =>
 429            {
 3430                CatalogLoaded();
 3431            });
 3432            catalogPromise.Catch(error =>
 433            {
 0434                BIWUtils.ShowGenericNotification(error);
 0435            });
 3436        }
 437
 438        public void ChangeEditModeStatusByShortcut(DCLAction_Trigger action)
 439        {
 1440            if (currentState != State.EDITING && currentState != State.IDLE)
 0441                return;
 442
 1443            if (currentState == State.EDITING )
 444            {
 0445                context.editorContext.editorHUD.ExitStart();
 0446                return;
 447            }
 448
 1449            if (DataStore.i.builderInWorld.landsWithAccess.Get().Length == 0 && !alreadyAskedForLandPermissions)
 450            {
 1451                ActivateLandAccessBackgroundChecker();
 1452                BIWUtils.ShowGenericNotification(BIWSettings.LAND_EDITION_WAITING_FOR_PERMISSIONS_MESSAGE, DCL.Notificat
 1453                isWaitingForPermission = true;
 1454                askPermissionLastPosition = DCLCharacterController.i.characterPosition.unityPosition;
 1455            }
 456            else
 457            {
 0458                CheckSceneToEditByShorcut();
 459            }
 0460        }
 461
 462        internal void CheckSceneToEditByShorcut()
 463        {
 1464            var scene = FindSceneToEdit();
 1465            StartFlowFromLandWithPermission(scene, SOURCE_SHORTCUT);
 1466        }
 467
 468        internal void NewSceneAdded(IParcelScene newScene)
 469        {
 1470            if (newScene.sceneData.id != sceneToEditId)
 0471                return;
 472
 1473            Environment.i.world.sceneController.OnNewSceneAdded -= NewSceneAdded;
 474
 1475            var scene = Environment.i.world.state.GetScene(sceneToEditId);
 1476            sceneToEdit.SetScene(scene);
 1477            sceneMetricsAnalyticsHelper = new BiwSceneMetricsAnalyticsHelper(sceneToEdit.scene);
 1478            sceneToEdit.scene.OnLoadingStateUpdated += UpdateSceneLoadingProgress;
 1479            SendManifestToScene();
 1480            context.cameraController.ActivateCamera(sceneToEdit.scene);
 1481        }
 482
 483        private void NewSceneReady(string id)
 484        {
 2485            if (sceneToEditId != id)
 1486                return;
 487
 1488            sceneToEdit.scene.OnLoadingStateUpdated -= UpdateSceneLoadingProgress;
 1489            Environment.i.world.sceneController.OnReadyScene -= NewSceneReady;
 1490            sceneToEditId = null;
 1491            NextState();
 1492        }
 493
 494        internal bool UserHasPermissionOnParcelScene(IParcelScene sceneToCheck)
 495        {
 2496            if (BYPASS_LAND_OWNERSHIP_CHECK)
 0497                return true;
 498
 4499            List<Vector2Int> allParcelsWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land => 
 6500            foreach (Vector2Int parcel in allParcelsWithAccess)
 501            {
 4502                if (sceneToCheck.sceneData.parcels.Any(currentParcel => currentParcel.x == parcel.x && currentParcel.y =
 2503                    return true;
 504            }
 505
 0506            return false;
 2507        }
 508
 509        internal Scene GetDeployedSceneFromParcel(Vector2Int coords)
 510        {
 0511            List<Scene> allDeployedScenesWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land =
 0512            foreach (Scene scene in allDeployedScenesWithAccess)
 513            {
 0514                List<Vector2Int> scenes = scene.parcels.ToList();
 0515                foreach (Vector2Int parcel in scenes)
 516                {
 0517                    if (coords.x == parcel.x && coords.y == parcel.y)
 0518                        return scene;
 519                }
 520            }
 0521            return null;
 0522        }
 523
 524        internal Scene GetDeployedSceneFromParcel(IParcelScene sceneToCheck)
 525        {
 2526            List<Scene> allDeployedScenesWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land =
 2527            foreach (Scene scene in allDeployedScenesWithAccess)
 528            {
 0529                List<Vector2Int> scenes = scene.parcels.ToList();
 0530                foreach (Vector2Int parcel in scenes)
 531                {
 0532                    if (sceneToCheck.sceneData.parcels.Any(currentParcel => currentParcel.x == parcel.x && currentParcel
 0533                        return scene;
 534                }
 535            }
 1536            return null;
 0537        }
 538
 539        internal bool IsParcelSceneDeployedFromSDK(IParcelScene sceneToCheck)
 540        {
 4541            List<Scene> allDeployedScenesWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land =
 5542            foreach (Scene scene in allDeployedScenesWithAccess)
 543            {
 1544                if (scene.source != Scene.Source.SDK)
 545                    continue;
 546
 1547                List<Vector2Int> parcelsDeployedFromSDK = scene.parcels.ToList();
 3548                foreach (Vector2Int parcel in parcelsDeployedFromSDK)
 549                {
 2550                    if (sceneToCheck.sceneData.parcels.Any(currentParcel => currentParcel.x == parcel.x && currentParcel
 1551                        return true;
 552                }
 553            }
 554
 1555            return false;
 1556        }
 557
 558        internal void EnterEditMode()
 559        {
 1560            initialLoadingController.SetPercentage(100f);
 1561            initialLoadingController.Hide(true, onHideAction: () =>
 562            {
 0563                inputController.inputTypeMode = InputTypeMode.BUILD_MODE;
 0564                context.editorContext.editorHUD?.SetVisibility(true);
 0565                CommonScriptableObjects.allUIHidden.Set(true);
 0566            });
 567
 1568            DCLCharacterController.OnPositionSet += ExitAfterCharacterTeleport;
 569
 1570            portableExperiencesToResume = DataStore.i.experiencesViewer.activeExperience.Get();
 1571            WebInterface.SetDisabledPortableExperiences(DataStore.i.experiencesViewer.activeExperience.Get().ToArray());
 572
 1573            context.editor.EnterEditMode(sceneToEdit);
 1574            DataStore.i.player.canPlayerMove.Set(false);
 1575            BIWAnalytics.EnterEditor( Time.realtimeSinceStartup - beginStartFlowTimeStamp);
 1576        }
 577
 578        internal void ExitEditMode()
 579        {
 2580            currentState = State.IDLE;
 2581            DataStore.i.HUDs.loadingHUD.visible.Set(true);
 2582            initialLoadingController.Hide(true);
 2583            inputController.inputTypeMode = InputTypeMode.GENERAL;
 2584            CommonScriptableObjects.allUIHidden.Set(false);
 2585            context.cameraController.DeactivateCamera();
 2586            context.editor.ExitEditMode();
 587
 2588            builderInWorldBridge.StopIsolatedMode();
 589
 2590            Utils.UnlockCursor();
 591
 2592            DataStore.i.player.canPlayerMove.Set(true);
 2593            DCLCharacterController.OnPositionSet -= ExitAfterCharacterTeleport;
 2594        }
 595
 596        public void StartFlowFromLandWithPermission(IParcelScene targetScene, string source)
 597        {
 2598            if (currentState != State.IDLE || targetScene == null)
 1599                return;
 600
 1601            if (!UserHasPermissionOnParcelScene(targetScene))
 602            {
 0603                BIWUtils.ShowGenericNotification(BIWSettings.LAND_EDITION_NOT_ALLOWED_BY_PERMISSIONS_MESSAGE);
 0604                return;
 605            }
 1606            else if (IsParcelSceneDeployedFromSDK(targetScene))
 607            {
 0608                BIWUtils.ShowGenericNotification(BIWSettings.LAND_EDITION_NOT_ALLOWED_BY_SDK_LIMITATION_MESSAGE);
 0609                return;
 610            }
 611
 1612            Scene deployedScene = GetDeployedSceneFromParcel(targetScene);
 1613            Vector2Int parcelSize = BIWUtils.GetSceneSize(targetScene);
 614
 1615            StartFromLand(targetScene.sceneData.basePosition, deployedScene, parcelSize, source);
 1616        }
 617
 618        private void StartFromLand(Vector2Int landCoordsVector, Scene deployedScene, Vector2Int parcelSize, string sourc
 619        {
 1620            string landCoords = landCoordsVector.x + "," + landCoordsVector.y;
 1621            Promise<InitialStateResponse> manifestPromise = initialStateManager.GetInitialManifest(context.builderAPICon
 622
 1623            manifestPromise.Then(response =>
 624            {
 1625                BuilderScene builderScene = new BuilderScene(response.manifest, IBuilderScene.SceneType.LAND, response.h
 1626                builderScene.landCoordsAsociated = landCoordsVector;
 1627                StartFlow(builderScene, source);
 1628            });
 629
 1630            manifestPromise.Catch( error =>
 631            {
 0632                BIWUtils.ShowGenericNotification(error);
 0633                ExitEditMode();
 0634            });
 1635        }
 636
 637        private void LoadScene()
 638        {
 5639            Environment.i.platform.cullingController.Stop();
 640
 641            // In this point we're sure that the catalog loading (the first half of our progress bar) has already finish
 5642            initialLoadingController.SetPercentage(50f);
 5643            Environment.i.world.sceneController.OnNewSceneAdded += NewSceneAdded;
 5644            Environment.i.world.sceneController.OnReadyScene += NewSceneReady;
 5645            Environment.i.world.blockersController.SetEnabled(false);
 646
 5647            ILand land = BIWUtils.CreateILandFromManifest(sceneToEdit.manifest, DataStore.i.player.playerGridPosition.Ge
 648
 5649            builderInWorldBridge.StartIsolatedMode(land);
 5650        }
 651
 652        internal void ActivateLandAccessBackgroundChecker()
 653        {
 2654            userProfile = UserProfile.GetOwnUserProfile();
 2655            if (!string.IsNullOrEmpty(userProfile.userId))
 656            {
 2657                if (updateLandsWithAcessCoroutine != null)
 0658                    CoroutineStarter.Stop(updateLandsWithAcessCoroutine);
 2659                updateLandsWithAcessCoroutine = CoroutineStarter.Start(CheckLandsAccess());
 660            }
 2661        }
 662
 0663        private void UpdateSceneLoadingProgress(float sceneLoadingProgress) { initialLoadingController.SetPercentage(50f
 664
 0665        private void UpdateCatalogLoadingProgress(float catalogLoadingProgress) { initialLoadingController.SetPercentage
 666
 2667        internal void ExitAfterCharacterTeleport(DCLCharacterPosition position) { ExitEditMode(); }
 668
 669        private IEnumerator CheckLandsAccess()
 670        {
 0671            while (true)
 672            {
 2673                UpdateLandsWithAccess();
 2674                yield return WaitForSecondsCache.Get(BIWSettings.REFRESH_LANDS_WITH_ACCESS_INTERVAL);
 675            }
 676        }
 677    }
 678}