< 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:127
Coverable lines:324
Total lines:680
Line coverage:60.8% (197 of 324)
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            var targetScene = Environment.i.world.state.scenesSortedByDistance
 0286                                         .FirstOrDefault(scene => scene.sceneData.parcels.Contains(coords));
 0287            StartFlowFromLandWithPermission(targetScene, SOURCE_BUILDER_PANEl);
 0288        }
 289
 290        public void StartFlowFromProject(Manifest.Manifest manifest)
 291        {
 0292            bool hasBeenCreatedThisSession = !string.IsNullOrEmpty(DataStore.i.builderInWorld.lastProjectIdCreated.Get()
 0293            DataStore.i.builderInWorld.lastProjectIdCreated.Set("");
 294
 0295            BuilderScene builderScene = new BuilderScene(manifest, IBuilderScene.SceneType.PROJECT,hasBeenCreatedThisSes
 0296            StartFlow(builderScene, SOURCE_BUILDER_PANEl);
 0297        }
 298
 299        public void StartFlowFromLandCoords(Vector2Int coords)
 300        {
 0301            Scene deployedScene = GetDeployedSceneFromParcel(coords);
 0302            Vector2Int parcelSize = BIWUtils.GetSceneSize(deployedScene.parcels);
 303
 0304            StartFromLand(deployedScene.@base, deployedScene, parcelSize, SOURCE_BUILDER_PANEl);
 0305        }
 306
 307        public void ShowBuilderLoading()
 308        {
 1309            initialLoadingController.Show();
 1310            initialLoadingController.SetPercentage(0f);
 1311        }
 312
 313        public void HideBuilderLoading()
 314        {
 0315            initialLoadingController.Hide();
 0316        }
 317
 318        public void StartExitMode()
 319        {
 2320            context.cameraController.TakeSceneScreenshotFromResetPosition((sceneSnapshot) =>
 321            {
 0322                if (sceneSnapshot != null)
 323                {
 0324                    sceneToEdit.sceneScreenshotTexture = sceneSnapshot;
 325
 0326                    if (sceneToEdit.manifest != null)
 0327                        context.builderAPIController.SetThumbnail(sceneToEdit.manifest.project.id, sceneSnapshot);
 328                }
 0329            });
 330
 2331            if (context.editorContext.editorHUD == null )
 0332                return;
 333
 2334            if (context.editorContext.publishController.HasUnpublishChanges() && sceneToEdit.sceneType == IBuilderScene.
 335            {
 0336                if (sceneToEdit.sceneType == IBuilderScene.SceneType.LAND)
 0337                    context.editorContext.editorHUD.ConfigureConfirmationModal(
 338                        BIWSettings.EXIT_MODAL_TITLE,
 339                        BIWSettings.EXIT_WITHOUT_PUBLISH_MODAL_SUBTITLE,
 340                        BIWSettings.EXIT_WITHOUT_PUBLISH_MODAL_CANCEL_BUTTON,
 341                        BIWSettings.EXIT_WITHOUT_PUBLISH_MODAL_CONFIRM_BUTTON);
 0342            }
 343            else
 344            {
 2345                context.editorContext.editorHUD.ConfigureConfirmationModal(
 346                    BIWSettings.EXIT_MODAL_TITLE,
 347                    BIWSettings.EXIT_MODAL_SUBTITLE,
 348                    BIWSettings.EXIT_MODAL_CANCEL_BUTTON,
 349                    BIWSettings.EXIT_MODAL_CONFIRM_BUTTON);
 350            }
 2351        }
 352
 353        public IParcelScene FindSceneToEdit()
 354        {
 6355            foreach (IParcelScene scene in Environment.i.world.state.scenesSortedByDistance)
 356            {
 2357                if (WorldStateUtils.IsCharacterInsideScene(scene))
 2358                    return scene;
 359            }
 360
 0361            return null;
 2362        }
 363
 364        private void UpdateLandsWithAccess()
 365        {
 2366            ICatalyst catalyst = Environment.i.platform.serviceProviders.catalyst;
 2367            ITheGraph theGraph = Environment.i.platform.serviceProviders.theGraph;
 368
 2369            DeployedScenesFetcher.FetchLandsFromOwner(
 370                                     catalyst,
 371                                     theGraph,
 372                                     userProfile.ethAddress,
 373                                     KernelConfig.i.Get().network,
 374                                     BIWSettings.CACHE_TIME_LAND,
 375                                     BIWSettings.CACHE_TIME_SCENES)
 376                                 .Then(lands =>
 377                                 {
 0378                                     DataStore.i.builderInWorld.landsWithAccess.Set(lands.ToArray(), true);
 0379                                     if (isWaitingForPermission && Vector3.Distance(askPermissionLastPosition, DCLCharac
 380                                     {
 0381                                         CheckSceneToEditByShorcut();
 382                                     }
 383
 0384                                     isWaitingForPermission = false;
 0385                                     alreadyAskedForLandPermissions = true;
 0386                                 });
 2387        }
 388
 389        internal void CatalogLoaded()
 390        {
 5391            catalogLoaded = true;
 5392            if ( context.editorContext.editorHUD != null)
 5393                context.editorContext.editorHUD.RefreshCatalogContent();
 5394            NextState();
 5395        }
 396
 397        internal void StartFlow(IBuilderScene targetScene, string source)
 398        {
 2399            if (currentState != State.IDLE || targetScene == null)
 1400                return;
 401
 1402            DataStore.i.exploreV2.isOpen.Set(false);
 403
 1404            sceneToEditId = targetScene.manifest.project.scene_id;
 1405            sceneToEdit = targetScene;
 406
 1407            NotificationsController.i.allowNotifications = false;
 1408            CommonScriptableObjects.allUIHidden.Set(true);
 1409            NotificationsController.i.allowNotifications = true;
 1410            inputController.inputTypeMode = InputTypeMode.BUILD_MODE_LOADING;
 411
 412            // We prepare the bridge for the current scene
 1413            bridge.SetScene(targetScene);
 414
 415            // We configure the loading part
 1416            ShowBuilderLoading();
 417
 1418            DataStore.i.common.appMode.Set(AppMode.BUILDER_IN_WORLD_EDITION);
 1419            DataStore.i.virtualAudioMixer.sceneSFXVolume.Set(0f);
 1420            BIWAnalytics.StartEditorFlow(source);
 1421            beginStartFlowTimeStamp = Time.realtimeSinceStartup;
 422
 1423            NextState();
 1424        }
 425
 426        internal void GetCatalog()
 427        {
 3428            BIWNFTController.i.StartFetchingNft();
 3429            var catalogPromise = context.builderAPIController.GetCompleteCatalog(userProfile.ethAddress);
 3430            catalogPromise.Then(x =>
 431            {
 3432                CatalogLoaded();
 3433            });
 3434            catalogPromise.Catch(error =>
 435            {
 0436                BIWUtils.ShowGenericNotification(error);
 0437            });
 3438        }
 439
 440        public void ChangeEditModeStatusByShortcut(DCLAction_Trigger action)
 441        {
 1442            if (currentState != State.EDITING && currentState != State.IDLE)
 0443                return;
 444
 1445            if (currentState == State.EDITING )
 446            {
 0447                context.editorContext.editorHUD.ExitStart();
 0448                return;
 449            }
 450
 1451            if (DataStore.i.builderInWorld.landsWithAccess.Get().Length == 0 && !alreadyAskedForLandPermissions)
 452            {
 1453                ActivateLandAccessBackgroundChecker();
 1454                BIWUtils.ShowGenericNotification(BIWSettings.LAND_EDITION_WAITING_FOR_PERMISSIONS_MESSAGE, DCL.Notificat
 1455                isWaitingForPermission = true;
 1456                askPermissionLastPosition = DCLCharacterController.i.characterPosition.unityPosition;
 1457            }
 458            else
 459            {
 0460                CheckSceneToEditByShorcut();
 461            }
 0462        }
 463
 464        internal void CheckSceneToEditByShorcut()
 465        {
 1466            var scene = FindSceneToEdit();
 1467            StartFlowFromLandWithPermission(scene, SOURCE_SHORTCUT);
 1468        }
 469
 470        internal void NewSceneAdded(IParcelScene newScene)
 471        {
 1472            if (newScene.sceneData.id != sceneToEditId)
 0473                return;
 474
 1475            Environment.i.world.sceneController.OnNewSceneAdded -= NewSceneAdded;
 476
 1477            var scene = Environment.i.world.state.GetScene(sceneToEditId);
 1478            sceneToEdit.SetScene(scene);
 1479            sceneMetricsAnalyticsHelper = new BiwSceneMetricsAnalyticsHelper(sceneToEdit.scene);
 1480            sceneToEdit.scene.OnLoadingStateUpdated += UpdateSceneLoadingProgress;
 1481            SendManifestToScene();
 1482            context.cameraController.ActivateCamera(sceneToEdit.scene);
 1483        }
 484
 485        private void NewSceneReady(string id)
 486        {
 2487            if (sceneToEditId != id)
 1488                return;
 489
 1490            sceneToEdit.scene.OnLoadingStateUpdated -= UpdateSceneLoadingProgress;
 1491            Environment.i.world.sceneController.OnReadyScene -= NewSceneReady;
 1492            sceneToEditId = null;
 1493            NextState();
 1494        }
 495
 496        internal bool UserHasPermissionOnParcelScene(IParcelScene sceneToCheck)
 497        {
 2498            if (BYPASS_LAND_OWNERSHIP_CHECK)
 0499                return true;
 500
 4501            List<Vector2Int> allParcelsWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land => 
 6502            foreach (Vector2Int parcel in allParcelsWithAccess)
 503            {
 4504                if (sceneToCheck.sceneData.parcels.Any(currentParcel => currentParcel.x == parcel.x && currentParcel.y =
 2505                    return true;
 506            }
 507
 0508            return false;
 2509        }
 510
 511        internal Scene GetDeployedSceneFromParcel(Vector2Int coords)
 512        {
 0513            List<Scene> allDeployedScenesWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land =
 0514            foreach (Scene scene in allDeployedScenesWithAccess)
 515            {
 0516                List<Vector2Int> scenes = scene.parcels.ToList();
 0517                foreach (Vector2Int parcel in scenes)
 518                {
 0519                    if (coords.x == parcel.x && coords.y == parcel.y)
 0520                        return scene;
 521                }
 522            }
 0523            return null;
 0524        }
 525
 526        internal Scene GetDeployedSceneFromParcel(IParcelScene sceneToCheck)
 527        {
 2528            List<Scene> allDeployedScenesWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land =
 2529            foreach (Scene scene in allDeployedScenesWithAccess)
 530            {
 0531                List<Vector2Int> scenes = scene.parcels.ToList();
 0532                foreach (Vector2Int parcel in scenes)
 533                {
 0534                    if (sceneToCheck.sceneData.parcels.Any(currentParcel => currentParcel.x == parcel.x && currentParcel
 0535                        return scene;
 536                }
 537            }
 1538            return null;
 0539        }
 540
 541        internal bool IsParcelSceneDeployedFromSDK(IParcelScene sceneToCheck)
 542        {
 4543            List<Scene> allDeployedScenesWithAccess = DataStore.i.builderInWorld.landsWithAccess.Get().SelectMany(land =
 5544            foreach (Scene scene in allDeployedScenesWithAccess)
 545            {
 1546                if (scene.source != Scene.Source.SDK)
 547                    continue;
 548
 1549                List<Vector2Int> parcelsDeployedFromSDK = scene.parcels.ToList();
 3550                foreach (Vector2Int parcel in parcelsDeployedFromSDK)
 551                {
 2552                    if (sceneToCheck.sceneData.parcels.Any(currentParcel => currentParcel.x == parcel.x && currentParcel
 1553                        return true;
 554                }
 555            }
 556
 1557            return false;
 1558        }
 559
 560        internal void EnterEditMode()
 561        {
 1562            initialLoadingController.SetPercentage(100f);
 1563            initialLoadingController.Hide(true, onHideAction: () =>
 564            {
 0565                inputController.inputTypeMode = InputTypeMode.BUILD_MODE;
 0566                context.editorContext.editorHUD?.SetVisibility(true);
 0567                CommonScriptableObjects.allUIHidden.Set(true);
 0568            });
 569
 1570            DCLCharacterController.OnPositionSet += ExitAfterCharacterTeleport;
 571
 1572            portableExperiencesToResume = DataStore.i.experiencesViewer.activeExperience.Get();
 1573            WebInterface.SetDisabledPortableExperiences(DataStore.i.experiencesViewer.activeExperience.Get().ToArray());
 574
 1575            context.editor.EnterEditMode(sceneToEdit);
 1576            DataStore.i.player.canPlayerMove.Set(false);
 1577            BIWAnalytics.EnterEditor( Time.realtimeSinceStartup - beginStartFlowTimeStamp);
 1578        }
 579
 580        internal void ExitEditMode()
 581        {
 2582            currentState = State.IDLE;
 2583            DataStore.i.HUDs.loadingHUD.visible.Set(true);
 2584            initialLoadingController.Hide(true);
 2585            inputController.inputTypeMode = InputTypeMode.GENERAL;
 2586            CommonScriptableObjects.allUIHidden.Set(false);
 2587            context.cameraController.DeactivateCamera();
 2588            context.editor.ExitEditMode();
 589
 2590            builderInWorldBridge.StopIsolatedMode();
 591
 2592            Utils.UnlockCursor();
 593
 2594            DataStore.i.player.canPlayerMove.Set(true);
 2595            DCLCharacterController.OnPositionSet -= ExitAfterCharacterTeleport;
 2596        }
 597
 598        public void StartFlowFromLandWithPermission(IParcelScene targetScene, string source)
 599        {
 2600            if (currentState != State.IDLE || targetScene == null)
 1601                return;
 602
 1603            if (!UserHasPermissionOnParcelScene(targetScene))
 604            {
 0605                BIWUtils.ShowGenericNotification(BIWSettings.LAND_EDITION_NOT_ALLOWED_BY_PERMISSIONS_MESSAGE);
 0606                return;
 607            }
 1608            else if (IsParcelSceneDeployedFromSDK(targetScene))
 609            {
 0610                BIWUtils.ShowGenericNotification(BIWSettings.LAND_EDITION_NOT_ALLOWED_BY_SDK_LIMITATION_MESSAGE);
 0611                return;
 612            }
 613
 1614            Scene deployedScene = GetDeployedSceneFromParcel(targetScene);
 1615            Vector2Int parcelSize = BIWUtils.GetSceneSize(targetScene);
 616
 1617            StartFromLand(targetScene.sceneData.basePosition, deployedScene, parcelSize, source);
 1618        }
 619
 620        private void StartFromLand(Vector2Int landCoordsVector, Scene deployedScene, Vector2Int parcelSize, string sourc
 621        {
 1622            string landCoords = landCoordsVector.x + "," + landCoordsVector.y;
 1623            Promise<InitialStateResponse> manifestPromise = initialStateManager.GetInitialManifest(context.builderAPICon
 624
 1625            manifestPromise.Then(response =>
 626            {
 1627                BuilderScene builderScene = new BuilderScene(response.manifest, IBuilderScene.SceneType.LAND, response.h
 1628                builderScene.landCoordsAsociated = landCoordsVector;
 1629                StartFlow(builderScene, source);
 1630            });
 631
 1632            manifestPromise.Catch( error =>
 633            {
 0634                BIWUtils.ShowGenericNotification(error);
 0635                ExitEditMode();
 0636            });
 1637        }
 638
 639        private void LoadScene()
 640        {
 5641            Environment.i.platform.cullingController.Stop();
 642
 643            // In this point we're sure that the catalog loading (the first half of our progress bar) has already finish
 5644            initialLoadingController.SetPercentage(50f);
 5645            Environment.i.world.sceneController.OnNewSceneAdded += NewSceneAdded;
 5646            Environment.i.world.sceneController.OnReadyScene += NewSceneReady;
 5647            Environment.i.world.blockersController.SetEnabled(false);
 648
 5649            ILand land = BIWUtils.CreateILandFromManifest(sceneToEdit.manifest, DataStore.i.player.playerGridPosition.Ge
 650
 5651            builderInWorldBridge.StartIsolatedMode(land);
 5652        }
 653
 654        internal void ActivateLandAccessBackgroundChecker()
 655        {
 2656            userProfile = UserProfile.GetOwnUserProfile();
 2657            if (!string.IsNullOrEmpty(userProfile.userId))
 658            {
 2659                if (updateLandsWithAcessCoroutine != null)
 0660                    CoroutineStarter.Stop(updateLandsWithAcessCoroutine);
 2661                updateLandsWithAcessCoroutine = CoroutineStarter.Start(CheckLandsAccess());
 662            }
 2663        }
 664
 0665        private void UpdateSceneLoadingProgress(float sceneLoadingProgress) { initialLoadingController.SetPercentage(50f
 666
 0667        private void UpdateCatalogLoadingProgress(float catalogLoadingProgress) { initialLoadingController.SetPercentage
 668
 2669        internal void ExitAfterCharacterTeleport(DCLCharacterPosition position) { ExitEditMode(); }
 670
 671        private IEnumerator CheckLandsAccess()
 672        {
 0673            while (true)
 674            {
 2675                UpdateLandsWithAccess();
 2676                yield return WaitForSecondsCache.Get(BIWSettings.REFRESH_LANDS_WITH_ACCESS_INTERVAL);
 677            }
 678        }
 679    }
 680}