diff --git a/OpenSim/ApplicationPlugins/LoadRegions/EstateLoaderFileSystem.cs b/OpenSim/ApplicationPlugins/LoadRegions/EstateLoaderFileSystem.cs new file mode 100644 index 0000000000..2eb2700962 --- /dev/null +++ b/OpenSim/ApplicationPlugins/LoadRegions/EstateLoaderFileSystem.cs @@ -0,0 +1,136 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.ApplicationPlugins.LoadRegions +{ + public class EstateLoaderFileSystem : IEstateLoader + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IConfigSource m_configSource; + + private OpenSimBase m_application; + + public EstateLoaderFileSystem(OpenSimBase openSim) + { + m_application = openSim; + } + + public void SetIniConfigSource(IConfigSource configSource) + { + m_configSource = configSource; + } + + public void LoadEstates() + { + string estateConfigPath = Path.Combine(Util.configDir(), "Estates"); + + try + { + IConfig startupConfig = m_configSource.Configs["Startup"]; + estateConfigPath = startupConfig.GetString("regionload_estatesdir", estateConfigPath).Trim(); + } + catch (Exception) + { + // No INI setting recorded. + } + + if (Directory.Exists(estateConfigPath) == false) + { + Directory.CreateDirectory(estateConfigPath); + } + + string[] iniFiles = Directory.GetFiles(estateConfigPath, "*.ini"); + + // No Estate.ini Found + if (iniFiles.Length == 0) + return; + + m_log.InfoFormat("[ESTATE LOADER FILE SYSTEM]: Loading estate config files from {0}", estateConfigPath); + + List existingEstates; + + int i = 0; + foreach (string file in iniFiles) + { + m_log.InfoFormat("[ESTATE LOADER FILE SYSTEM]: Loading config file {0}", file); + + IConfigSource source = new IniConfigSource(file); + + foreach (IConfig config in source.Configs) + { + // Read Estate Config From Source File + string estateName = config.Name; + string ownerString = config.GetString("Owner", string.Empty); + + if (UUID.TryParse(ownerString, out UUID estateOwner) == false) + estateOwner = UUID.Zero; + + // Check Name Is Valid + if (estateName == string.Empty || estateOwner == UUID.Zero) + continue; + + // Check If Estate Exists (Skip If So) + existingEstates = m_application.EstateDataService.GetEstates(estateName); + + if (existingEstates.Count > 0) + continue; + + //### Should check Estate Owner ID but no Scene object available at this point + + // Create a new estate with the name provided + EstateSettings estateSettings = m_application.EstateDataService.CreateNewEstate(); + + estateSettings.EstateName = estateName; + estateSettings.EstateOwner = estateOwner; + + // Persistence does not seem to effect the need to save a new estate + m_application.EstateDataService.StoreEstateSettings(estateSettings); + + m_log.InfoFormat("[ESTATE LOADER FILE SYSTEM]: Loaded config for estate {0}", estateName); + + i++; + } + } + + } + } +} diff --git a/OpenSim/ApplicationPlugins/LoadRegions/IEstateLoader.cs b/OpenSim/ApplicationPlugins/LoadRegions/IEstateLoader.cs new file mode 100644 index 0000000000..e69cc70017 --- /dev/null +++ b/OpenSim/ApplicationPlugins/LoadRegions/IEstateLoader.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using Nini.Config; + +namespace OpenSim.ApplicationPlugins.LoadRegions +{ + public interface IEstateLoader + { + void SetIniConfigSource(IConfigSource configSource); + void LoadEstates(); + } +} diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index feb73a992c..f4c75d5b5a 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -84,11 +84,14 @@ namespace OpenSim.ApplicationPlugins.LoadRegions { //m_log.Info("[LOADREGIONS]: Load Regions addin being initialised"); + IEstateLoader estateLoader = null; IRegionLoader regionLoader; if (m_openSim.ConfigSource.Source.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem") { m_log.Info("[LOAD REGIONS PLUGIN]: Loading region configurations from filesystem"); regionLoader = new RegionLoaderFileSystem(); + + estateLoader = new EstateLoaderFileSystem(m_openSim); } else { @@ -96,6 +99,14 @@ namespace OpenSim.ApplicationPlugins.LoadRegions regionLoader = new RegionLoaderWebServer(); } + // Load Estates Before Regions! + if(estateLoader != null) + { + estateLoader.SetIniConfigSource(m_openSim.ConfigSource.Source); + + estateLoader.LoadEstates(); + } + regionLoader.SetIniConfigSource(m_openSim.ConfigSource.Source); RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 525f87a937..c2432650a2 100755 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -1040,11 +1040,54 @@ namespace OpenSim foreach (EstateSettings estate in estates) estatesByName[estate.EstateName] = estate; - string defaultEstateName = null; + //## + // Target Estate Specified in Region.ini + string targetEstateName = regInfo.GetSetting("TargetEstate"); + if (targetEstateName != null && targetEstateName != string.Empty) + { + bool targetEstateJoined = false; + + if (Int32.TryParse(targetEstateName, out int targetEstateID) && targetEstateID > 99) + { + // Attempt to join the target estate given in Config by ID + foreach (EstateSettings estate in estates) + { + if (estate.EstateID == targetEstateID) + { + if (EstateDataService.LinkRegion(regInfo.RegionID, targetEstateID)) + targetEstateJoined = true; + + break; + } + } + } + else + { + // Attempt to join the target estate given in Config by name + EstateSettings targetEstate; + + if (estatesByName.ContainsKey(targetEstateName)) + { + targetEstate = estatesByName[targetEstateName]; + + if (EstateDataService.LinkRegion(regInfo.RegionID, (int)targetEstate.EstateID)) + targetEstateJoined = true; + } + } + + if (targetEstateJoined) + return true; // need to update the database + else + m_log.ErrorFormat( + "[OPENSIM BASE]: Joining target estate specified in region config {0} failed", targetEstateName); + } + //## + + // Default Estate if (Config.Configs[ESTATE_SECTION_NAME] != null) { - defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null); + string defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null); if (defaultEstateName != null) { diff --git a/bin/Estates/.keep b/bin/Estates/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bin/Estates/Estates.ini.example b/bin/Estates/Estates.ini.example new file mode 100644 index 0000000000..38ac3649af --- /dev/null +++ b/bin/Estates/Estates.ini.example @@ -0,0 +1,18 @@ +; * This is an example estate config file. +; * +; * If a Region is loaded without an estate, OpenSimulator will ask you configuration questions to create or join an existing estate. +; * So there is no need to change this file directly, it is only for reference. +; * However, if you prefer you can also copy this file to Estates.ini and appropriately change the parameters below. +; * Only files ending with .ini and .xml in this directly will be loaded by OpenSimulator. +; * +; * You can add multiple estates into one file or make one file per estate +; * The section name is the estate name +; * + +[Example Estate] + +; * +; * You MUST change this! It will NOT be done for you! +; * + +Owner = 11111111-2222-3333-4444-555555555555 \ No newline at end of file diff --git a/bin/Regions/Regions.ini.example b/bin/Regions/Regions.ini.example index 97d1c4f628..3f47cca51e 100644 --- a/bin/Regions/Regions.ini.example +++ b/bin/Regions/Regions.ini.example @@ -23,6 +23,10 @@ InternalPort = 9000 AllowAlternatePorts = False ExternalHostName = SYSTEMIP +;; Estate ID or Name to connect region to, leave blank for console prompt, remember estate id can not be less than 100 +;; this value is only used when creating a region and after that will be ignored. 0 Will use the next auto id provided by the database +;TargetEstate = 0 + ; * ; * Variable-sized regions allows the creation of large, borderless spaces. ; * The default is 256 meters. For larger spaces, set these to multiples of 256.