public static Rectangle GetRect(this IslandInstanceData Data, Project currentProject, IDictionary <string, Island> islands)
        {
            if (currentProject == null)
            {
                return(new Rectangle());
            }

            Island referencedIsland = Data.GetReferencedIsland(islands);

            float relativeX = referencedIsland.x * currentProject.coordsScaling;
            float relativeY = referencedIsland.y * currentProject.coordsScaling;

            return(new Rectangle((int)Math.Round(Data.worldX * currentProject.coordsScaling - relativeX / 2f), (int)Math.Round(Data.worldY * currentProject.coordsScaling - relativeY / 2f), (int)Math.Round(relativeX), (int)Math.Round(relativeY)));
        }
        //Removes overrides with the same value as template
        public static void SyncOverridesWithTemplates(this IslandInstanceData Data, MainForm mainForm)
        {
            Island referencedIsland = Data.GetReferencedIsland(mainForm.islands);

            if (referencedIsland.spawnerOverrides == null)
            {
                return;
            }

            List <string> keysToRemove = new List <string>();

            foreach (KeyValuePair <string, string> templateSpawnerOverride in referencedIsland.spawnerOverrides)
            {
                if (Data.spawnerOverrides.ContainsKey(templateSpawnerOverride.Key) && Data.spawnerOverrides[templateSpawnerOverride.Key] == templateSpawnerOverride.Value)
                {
                    keysToRemove.Add(templateSpawnerOverride.Key);
                }
            }

            foreach (string keyToRemove in keysToRemove)
            {
                Data.spawnerOverrides.Remove(keyToRemove);
            }
        }
        public static ServerData SetFrom(this ServerData Data, Server server, float gridSize, int gridX, int gridY, string MachineIdTag, string ip, int port,
                                         int gamePort, int seamlessDataPort, List <IslandInstanceData> islandInstances, List <DiscoveryZoneData> discoZones, List <SpawnRegionData> spawnRegions, MainForm mainForm,
                                         bool isHomeServer, string AdditionalCmdLineParams, Dictionary <string, string> OverrideShooterGameModeDefaultGameIni, string name, int floorZDist, int transitionMinZ, int utcOffset, string OceanDinoDepthEntriesOverride,
                                         string OceanFloatsamCratesOverride, string TreasureMapLootTablesOverride, DateTime lastModified, DateTime lastImageOverride, string GlobalBiomeSeamlessServerGridPreOffsetValues, string GlobalBiomeSeamlessServerGridPreOffsetValuesOceanWater,
                                         bool islandLocked, bool discoLocked, bool pathsLocked, List <string> extraSublevels, string oceanEpicSpawnEntriesOverrideTemplateName, string NPCShipSpawnEntriesOverrideTemplateName, string regionOverrides,
                                         float waterColorR, float waterColorG, float waterColorB, int skyStyleIndex, float serverIslandPointsMultiplier, string ServerCustomDatas1, string ServerCustomDatas2, string ClientCustomDatas1, string ClientCustomDatas2, string serverTemplateName, string OceanEpicSpawnEntriesOverrideValues)
        {
            Data.gridX                   = gridX;
            Data.gridY                   = gridY;
            Data.MachineIdTag            = MachineIdTag;
            Data.ip                      = ip;
            Data.port                    = port;
            Data.gamePort                = gamePort;
            Data.seamlessDataPort        = seamlessDataPort;
            Data.islandInstances         = islandInstances;
            Data.discoZones              = discoZones;
            Data.spawnRegions            = spawnRegions;
            Data.isHomeServer            = isHomeServer;
            Data.AdditionalCmdLineParams = AdditionalCmdLineParams;
            Data.OverrideShooterGameModeDefaultGameIni = OverrideShooterGameModeDefaultGameIni;
            Data.name           = name;
            Data.floorZDist     = floorZDist;
            Data.transitionMinZ = transitionMinZ;
            Data.utcOffset      = utcOffset;
            Data.OceanDinoDepthEntriesOverride             = OceanDinoDepthEntriesOverride;
            Data.OceanEpicSpawnEntriesOverrideValues       = OceanEpicSpawnEntriesOverrideValues;
            Data.oceanEpicSpawnEntriesOverrideTemplateName = oceanEpicSpawnEntriesOverrideTemplateName;
            Data.NPCShipSpawnEntriesOverrideTemplateName   = NPCShipSpawnEntriesOverrideTemplateName;
            Data.regionOverrides = regionOverrides;
            Data.waterColorR     = waterColorR;
            Data.waterColorG     = waterColorG;
            Data.waterColorB     = waterColorB;
            Data.skyStyleIndex   = skyStyleIndex;
            Data.serverIslandPointsMultiplier  = serverIslandPointsMultiplier;
            Data.ServerCustomDatas1            = ServerCustomDatas1;
            Data.ServerCustomDatas2            = ServerCustomDatas2;
            Data.ClientCustomDatas1            = ClientCustomDatas1;
            Data.ClientCustomDatas2            = ClientCustomDatas2;
            Data.oceanFloatsamCratesOverride   = OceanFloatsamCratesOverride;
            Data.treasureMapLootTablesOverride = TreasureMapLootTablesOverride;
            Data.lastModified      = lastModified;
            Data.lastImageOverride = lastImageOverride;
            Data.GlobalBiomeSeamlessServerGridPreOffsetValues           = GlobalBiomeSeamlessServerGridPreOffsetValues;
            Data.GlobalBiomeSeamlessServerGridPreOffsetValuesOceanWater = GlobalBiomeSeamlessServerGridPreOffsetValuesOceanWater;
            Data.islandLocked       = islandLocked;
            Data.discoLocked        = discoLocked;
            Data.pathsLocked        = pathsLocked;
            Data.extraSublevels     = extraSublevels;
            Data.serverTemplateName = serverTemplateName;

            Data.totalExtraSublevels = new List <string>();

            foreach (IslandInstanceData instance in islandInstances)
            {
                PointF relativePoint = server.WorldToRelativePoint(gridSize, new PointF(instance.worldX, instance.worldY));

                Island referencedIsland = instance.GetReferencedIsland(mainForm.islands);
                if (referencedIsland != null)
                {
                    foreach (string sublevelName in referencedIsland.sublevelNames)
                    {
                        Data.sublevels.Add(new SublevelSerializationObject()
                        {
                            name = sublevelName, id = instance.id, additionalTranslationX = relativePoint.X, additionalTranslationY = relativePoint.Y, additionalRotationYaw = instance.rotation, landscapeMaterialOverride = referencedIsland.landscapeMaterialOverride
                        });
                    }

                    instance.minTreasureQuality        = referencedIsland.minTreasureQuality;
                    instance.maxTreasureQuality        = referencedIsland.maxTreasureQuality;
                    instance.useNpcVolumesForTreasures = referencedIsland.useNpcVolumesForTreasures;
                    instance.islandTreasureBottleSupplyCrateOverrides = referencedIsland.islandTreasureBottleSupplyCrateOverrides;
                    //instance.spawnPointRegionOverride = referencedIsland.spawnPointRegionOverride;
                    instance.useLevelBoundsForTreasures    = referencedIsland.useLevelBoundsForTreasures;
                    instance.prioritizeVolumesForTreasures = referencedIsland.prioritizeVolumesForTreasures;
                    instance.islandWidth  = referencedIsland.x;
                    instance.islandHeight = referencedIsland.y;
                    instance.islandPoints = referencedIsland.islandPoints;
                }

                instance.SyncOverridesWithTemplates(mainForm);

                //Add the template spawner overrides if not already existing in the island
                if (referencedIsland.spawnerOverrides != null)
                {
                    foreach (KeyValuePair <string, string> spawnerOverride in referencedIsland.spawnerOverrides)
                    {
                        if (!instance.spawnerOverrides.ContainsKey(spawnerOverride.Key))
                        {
                            instance.spawnerOverrides.Add(spawnerOverride.Key, spawnerOverride.Value);
                        }
                    }
                }

                if (referencedIsland.extraSublevels != null)
                {
                    foreach (string extraSublevel in referencedIsland.extraSublevels)
                    {
                        if (!Data.totalExtraSublevels.Contains(extraSublevel) && !string.IsNullOrWhiteSpace(extraSublevel))
                        {
                            Data.totalExtraSublevels.Add(extraSublevel);
                        }
                    }
                }
            }


            if (extraSublevels != null)
            {
                foreach (string extraSublevel in extraSublevels)
                {
                    if (!Data.totalExtraSublevels.Contains(extraSublevel) && !string.IsNullOrWhiteSpace(extraSublevel))
                    {
                        Data.totalExtraSublevels.Add(extraSublevel);
                    }
                }
            }

            return(Data);
        }
        public string Serialize(MainForm mainForm, bool bIsFinalExport = false)
        {
            List <string> referencedIslandNames = new List <string>();

            foreach (IslandInstanceData instance in islandInstances)
            {
                Island referenceIsland = instance.GetReferencedIsland(mainForm.islands);
                if (referenceIsland == null)
                {
                    continue;
                }

                if (referenceIsland.sublevelNames == null || referenceIsland.sublevelNames.Count == 0)
                {
                    string emptyIslandName = referenceIsland.name;
                    if (!referencedIslandNames.Contains(emptyIslandName))
                    {
                        referencedIslandNames.Add(emptyIslandName);
                    }
                }
            }

            foreach (string islandName in referencedIslandNames)
            {
                MessageBox.Show(string.Format("The island \"{0}\" has no defined sublevels and will not appear ingame", islandName), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }


            AtlasGridData ProjectObj = new AtlasGridData().SetFromData(cellSize, servers, islandInstances, discoZones, spawnRegions, WorldAtlasId, WorldFriendlyName, MetaWorldURL,
                                                                       coordsScaling, showServerInfo, showLines, alphaBackground, showBackground, backgroundImgPath, mainForm, idGenerator, regionsIdGenerator, mainForm.spawners.spawnersInfo, bUseUTCTime,
                                                                       Day0, globalTransitionMinZ, AdditionalCmdLineParams, OverrideShooterGameModeDefaultGameIni, LastImageOverrideUTC, showDiscoZoneInfo, discoZonesImagePath, shipPaths,
                                                                       shipPathsIdGenerator, showShipPathsInfo, ModIDs, showIslandNames, showForeground, foregroundImgPath, globalGameplaySetup, serverTemplates, bIsFinalExport, MapImageURL, AuthListURL,
                                                                       WorldAtlasPassword, columnUTCOffset);

            ProjectObj.BaseServerArgs = BaseServerArgs;
            ProjectObj.totalGridsX    = numOfCellsX;
            ProjectObj.totalGridsY    = numOfCellsY;
            if (!bIsFinalExport)
            {
                ProjectObj.LocalS3URL          = LocalS3URL;
                ProjectObj.LocalS3AccessKeyId  = LocalS3AccessKeyId;
                ProjectObj.LocalS3SecretKey    = LocalS3SecretKey;
                ProjectObj.LocalS3BucketName   = LocalS3BucketName;
                ProjectObj.LocalS3Region       = LocalS3Region;
                ProjectObj.TribeLogConfig      = TribeLogConfig;
                ProjectObj.SharedLogConfig     = SharedLogConfig;
                ProjectObj.TravelDataConfig    = TravelDataConfig;
                ProjectObj.DatabaseConnections = DatabaseConnections;
            }
            else
            {
                ProjectObj.LocalS3URL          = null;
                ProjectObj.LocalS3AccessKeyId  = null;
                ProjectObj.LocalS3SecretKey    = null;
                ProjectObj.LocalS3BucketName   = null;
                ProjectObj.LocalS3Region       = null;
                ProjectObj.TribeLogConfig      = null;
                ProjectObj.SharedLogConfig     = null;
                ProjectObj.TravelDataConfig    = null;
                ProjectObj.DatabaseConnections = null;
                ProjectObj.serverTemplates.Clear();
            }
            return(JsonConvert.SerializeObject(ProjectObj, Formatting.Indented, new JsonSerializerSettings()
            {
                NullValueHandling = NullValueHandling.Ignore
            }));
        }