Describes a base layer for a city map, contains: cityRegion A link that denotes which region (scene) is being used for this map in the server instance. age The age of the city (simulated) in years, future to allow for the city to change dynamically with age. multiRegion A flag used to represent whether or not the city is in a single region (scene) or spread over multiple regions. cityBuildings A list of buildings that are within the city limits. cityPlots A list of plots used in the city map, note that a plot can contain other things apart from buildings. cityClaims An array of values indicating the type of claim on the land, part of a complex, transport etc. estateIdent UUID of owning estate. cityMapOwner UUID of owning avatar. cityLandData Parcel settings for all regions contained within the city. cityEstateSettings Estate settings for all regions in the city.
        /// <summary>
        /// This method will produce a random city with the central region of the city being
        /// specified as a parameter. More parameters need to be made available for this method
        /// to produce a better quality city, note for now the minimum area for a city is a
        /// 3x3 grid of regions. This code is based on the original C++ version called pixel city.
        /// </summary>
        /// <param name="seed_value">Random integer seed value.</param>
        /// <returns>true / false indicator of success or failure.</returns>
        private bool doGenerate(int seed_value)
        {
            int rx, ry;

            //  Based on the initial seed value populate the regions that this shared module
            // is connected to, this means first get a list of the region, determine which
            // region is in the center of all the regions and set this as the hotzone, or
            // central part of the city (this is where the tallest/largest buildings will
            // be created) and will extend out to cover virtually all of the connected
            // regions if desired. No support for aging of the buildings or the city exists
            // yet it is a possible course for the future of this module.

            //  First quick check to see if the module is enabled or not.
            if (!m_fEnabled)
            {
                m_log.Info("[CITY BUILDER]: Disabled, aborting auto generation.");
                return(false);
            }

            m_log.Info("[CITY BUILDER]: Auto generating the city.");

            //  Now we need to ask some basic values for the city generation, we already have
            // the base seed value as this is part of the 'city generate' command, now what
            // about a name, position, size, densities etc. Some of this can be generated
            // based on the seed value, but then, it would need to be confirmed by the user
            // or allow them to change it. TODO move all requested data into the configuration file.
            if (m_UserAccountService == null)
            {
                m_UserAccountService = simulationBase.ApplicationRegistry.RequestModuleInterface <IUserAccountService>();
            }

            //  Decide where the city is to be placed within the server instance.
            int r = this.randomValue(10);

            string regionCount = MainConsole.Instance.CmdPrompt("Region Count ", r.ToString());

            r = Convert.ToInt32(regionCount);
            m_log.InfoFormat("[CITY BUILDER]: City area {0} x {1} regions ", r, r);

            cityName          = MainConsole.Instance.CmdPrompt("City Name ", cityName);
            cityOwner         = MainConsole.Instance.CmdPrompt("City Owner ", cityOwner);
            m_DefaultUserName = cityOwner;

            //  Make sure that the user and estate information specified in the configuration file
            // have been loaded and the information has either been found or has been created.
            m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, cityOwner);
            if (m_DefaultUserAccount == null)
            {
                m_log.InfoFormat("[CITY BUILDER]: Creating default account {0}", m_DefaultUserName);
                m_UserAccountService.CreateUser(m_DefaultUserName, Util.Md5Hash(m_DefaultUserPword), m_DefaultUserEmail);
                m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, m_DefaultUserName);
                cityOwner            = m_DefaultUserName;
            }
            else
            {
                m_log.InfoFormat("[CITY BUILDER]: Account found for {0}", m_DefaultUserName);
            }

            // Obtain the scene manager that the server instance is using.
            sceneManager = simulationBase.ApplicationRegistry.RequestModuleInterface <SceneManager>();

            //  Construct the data instance for a city map to hold the total regions in the simulation.
            cityMap               = new CityMap();
            citySeed              = seed_value;
            cityMap.cityRegions   = new Scene[r, r];
            cityMap.cityPlots     = new List <BuildingPlot>();
            cityMap.cityBuildings = new List <CityBuilding>();

            //  Construct land and estate data and update to reflect the found user or the newly created one.
            cityLandData = new LandData();
            RegionInfo regionInfo = new RegionInfo();

            regionInfo.RegionID = UUID.Random();

            //Create an estate
            m_DefaultEstate = new EstateSettings();

            m_log.InfoFormat("[CITY BUILDER]: No estates found for user {0}, constructing default estate.", m_DefaultUserAccount.Name);

            m_DefaultEstate.EstateOwner = m_DefaultUserAccount.PrincipalID;
            m_DefaultEstate.EstateName  = m_DefaultEstateName;
            m_DefaultEstate.EstatePass  = Util.Md5Hash(Util.Md5Hash(m_DefaultEstatePassword));
            m_DefaultEstate.EstateID    = (uint)this.randomValue(1000);

            regionInfo.EstateSettings = m_DefaultEstate; //Just set the estate, this module took care of the loading and the rest will leave it alone

            cityLandData.OwnerID  = m_DefaultUserAccount.PrincipalID;
            cityLandData.Name     = m_DefaultEstateName;
            cityLandData.GlobalID = UUID.Random();
            cityLandData.GroupID  = UUID.Zero;

            int regionPort = startPort;

            //  Construct the region.
            regionInfo.RegionSizeX    = cityConfig.GetInt("DefaultRegionSize", 256);
            regionInfo.RegionSizeY    = regionInfo.RegionSizeX;
            regionInfo.RegionType     = "Mainland";
            regionInfo.ObjectCapacity = 100000;
            regionInfo.Startup        = StartupType.Normal;
            regionInfo.ScopeID        = UUID.Zero;

            IParcelServiceConnector parcelService = Aurora.DataManager.DataManager.RequestPlugin <IParcelServiceConnector>();

            if (r == 1)
            {
                m_log.Info("[CITY BUILDER]: Single region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName          = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                regionInfo.InternalEndPoint          = new IPEndPoint(address, regionPort++);
                cityLandData.RegionID = regionInfo.RegionID;
                if (parcelService != null)
                {
                    parcelService.StoreLandObject(cityLandData.LandData);
                }
                regionInfo.RegionName = "Region00";
                regionInfo.RegionLocX = (int)m_DefaultStartLocation.X;
                regionInfo.RegionLocY = (int)m_DefaultStartLocation.Y;
                if (!createRegion(0, 0, regionInfo))
                {
                    m_log.Info("[CITY BUILDER]: Failed to construct region.");
                    return(false);
                }
            }
            else if (r > 1)
            {
                m_log.Info("[CITY BUILDER]: Multi-region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName          = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                //  Construct the regions for the city.
                regionPort = startPort;
                for (rx = 0; rx < r; rx++)
                {
                    for (ry = 0; ry < r; ry++)
                    {
                        regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                        cityLandData.RegionID       = regionInfo.RegionID;
                        if (parcelService != null)
                        {
                            parcelService.StoreLandObject(cityLandData.LandData);
                        }
                        regionInfo.RegionName = "Region" + rx + ry;
                        regionInfo.RegionLocX = (int)(m_DefaultStartLocation.X + rx);
                        regionInfo.RegionLocY = (int)(m_DefaultStartLocation.Y + ry);
                        m_log.InfoFormat("[CITY BUILDER]: '{0}' @ {1},{2}, http://{3}/", regionInfo.RegionName,
                                         regionInfo.RegionLocX, regionInfo.RegionLocY, regionInfo.InternalEndPoint);
                        //We already set the estate before, we don't need to deal with linking it or anything
                        //EstateConnector.LinkRegion(regionInfo.RegionID, (int)m_DefaultEstate.EstateID, m_DefaultEstate.EstatePass);
                        if (!createRegion(rx, ry, regionInfo))
                        {
                            m_log.InfoFormat("[CITY BUILDER]: Failed to construct region at {0},{1}", rx, ry);
                            return(false);
                        }
                    }
                }
            }

            //  Either generate the terrain or loading from an existing file, DEM for example.
            m_log.Info("[CITY BUILDER]: [TERRAIN]");

            //  For each region, just fill the terrain to be 21. This is just above the default
            // water level for Aurora.
            float[,] tHeight = new float[256, 256];
            for (rx = 0; rx < 256; rx++)
            {
                for (ry = 0; ry < 256; ry++)
                {
                    tHeight[rx, ry] = 21.0f;
                }
            }
            //  Construct the new terrain for each region and pass the height map to it.
            for (rx = 0; rx < r; rx++)
            {
                for (ry = 0; ry < r; ry++)
                {
                    Scene           region   = cityMap.cityRegions[rx, ry];
                    ITerrainChannel tChannel = new TerrainChannel(true, region);
                    ITerrain        terrain  = null;
                    try
                    {
                        region.TryRequestModuleInterface <ITerrain>(out terrain);
                        terrain.SetHeights2D(tHeight);
                    }
                    catch
                    {
                    }
                }
            }

            //  Rivers and other waterways.

            //  From the total number of regions pick a number of regions that will be 'centers'
            // for the entire city, record these in the centralRegions list.
            m_log.Info("[CITY BUILDER]: [CENTERS]");
            //  ( region count * region count ) / 3
            int aNum = this.randomValue((cityMap.cityRegions.GetUpperBound(0) * cityMap.cityRegions.GetUpperBound(1)) / 3);

            if (aNum == 0)
            {
                aNum = 1;
            }
            m_log.InfoFormat("[CITY BUILDER]: Total regions {0}, selecting {1} regions for centers.", (r * r), aNum);
            int prevRegionX = 0;
            int prevRegionY = 0;

            while (aNum > 0)
            {
                int currRegionX = randomValue(cityMap.cityRegions.GetUpperBound(0)) / 2;
                int currRegionY = randomValue(cityMap.cityRegions.GetUpperBound(1)) / 2;

                // If the location selected is the same as the previous location try again.
                if (currRegionX == prevRegionX && currRegionY == prevRegionY)
                {
                    aNum--;
                    continue;
                }

                m_log.InfoFormat("[CITY BUILDER]: Region {0}, located {1},{2}", aNum, prevRegionX, prevRegionY);

                try
                {
                    Scene region = cityMap.centralRegions[(prevRegionX * cityMap.cityRegions.GetUpperBound(0)) + prevRegionY];
                    if (region != null)
                    {
                        cityMap.centralRegions.Add(region);
                    }
                }
                catch
                {
                }
                aNum--;
                prevRegionX = currRegionX;
                prevRegionY = currRegionY;
            }

            m_log.Info("[CITY BUILDER]: [DENSITY]");
            float avgDensity = 0.0f;

            avgDensity += cityDensities[0];
            avgDensity += cityDensities[1];
            avgDensity += cityDensities[2];
            avgDensity += cityDensities[3];
            avgDensity /= 4;

            //  Before ANYTHING else is created construct the transport systems, priority is given
            // to the road network before the rail network, perhaps a configuration option to allow
            // for the prioritisation value of the transport system is possible.
            m_log.Info("[CITY BUILDER]: [FREEWAYS]");
            m_log.Info("[CITY BUILDER]: [HIGHWAYS]");
            m_log.Info("[CITY BUILDER]: [STREETS]");
            m_log.Info("[CITY BUILDER]: [RAILWAYS]");

            m_log.InfoFormat("[CITY BUILDER]: [RESIDENTIAL DENSITY] {0}%", cityDensities[0] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [COMMERCIAL DENSITY] {0}%", cityDensities[1] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [CORPORATE DENSITY] {0}%", cityDensities[2] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [INDUSTRIAL DENISTY] {0}%", cityDensities[3] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [AVERAGE DENSITY] {0}%", avgDensity);

            m_log.Info("[CITY BUILDER]: [BLOCKS]");
            m_log.Info("[CITY BUILDER]: [ALLOTMENT PLOTS]");
            m_log.Info("[CITY BUILDER]: [BUILDINGS]");

            return(true);
        }
        /// <summary>
        /// This method will produce a random city with the central region of the city being
        /// specified as a parameter. More parameters need to be made available for this method
        /// to produce a better quality city, note for now the minimum area for a city is a
        /// 3x3 grid of regions. This code is based on the original C++ version called pixel city.
        /// </summary>
        /// <param name="seed_value">Random integer seed value.</param>
        /// <returns>true / false indicator of success or failure.</returns>
        private bool doGenerate(int seed_value)
        {
            int rx, ry;
            //  Based on the initial seed value populate the regions that this shared module
            // is connected to, this means first get a list of the region, determine which
            // region is in the center of all the regions and set this as the hotzone, or
            // central part of the city (this is where the tallest/largest buildings will
            // be created) and will extend out to cover virtually all of the connected
            // regions if desired. No support for aging of the buildings or the city exists
            // yet it is a possible course for the future of this module.

            //  First quick check to see if the module is enabled or not.
            if (!m_fEnabled)
            {
                m_log.Info("[CITY BUILDER]: Disabled, aborting auto generation.");
                return (false);
            }

            m_log.Info("[CITY BUILDER]: Auto generating the city.");

            //  Now we need to ask some basic values for the city generation, we already have
            // the base seed value as this is part of the 'city generate' command, now what
            // about a name, position, size, densities etc. Some of this can be generated
            // based on the seed value, but then, it would need to be confirmed by the user
            // or allow them to change it. TODO move all requested data into the configuration file.
            if (m_UserAccountService == null)
            {
                m_UserAccountService = simulationBase.ApplicationRegistry.RequestModuleInterface<IUserAccountService>();
            }

            //  Decide where the city is to be placed within the server instance.
            int r = this.randomValue(10);

            string regionCount = MainConsole.Instance.CmdPrompt("Region Count ", r.ToString());
            r = Convert.ToInt32(regionCount);
            m_log.InfoFormat("[CITY BUILDER]: City area {0} x {1} regions ", r, r);

            cityName = MainConsole.Instance.CmdPrompt("City Name ", cityName);
            cityOwner = MainConsole.Instance.CmdPrompt("City Owner ", cityOwner);
            m_DefaultUserName = cityOwner;

            //  Make sure that the user and estate information specified in the configuration file
            // have been loaded and the information has either been found or has been created.
            m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, cityOwner);
            if (m_DefaultUserAccount == null)
            {
                m_log.InfoFormat("[CITY BUILDER]: Creating default account {0}", m_DefaultUserName);
                m_UserAccountService.CreateUser(m_DefaultUserName, Util.Md5Hash(m_DefaultUserPword), m_DefaultUserEmail);
                m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, m_DefaultUserName);
                cityOwner = m_DefaultUserName;
            }
            else
                m_log.InfoFormat("[CITY BUILDER]: Account found for {0}", m_DefaultUserName);

            // Obtain the scene manager that the server instance is using.
            sceneManager = simulationBase.ApplicationRegistry.RequestModuleInterface<SceneManager>();

            //  Construct the data instance for a city map to hold the total regions in the simulation.
            cityMap = new CityMap();
            citySeed = seed_value;
            cityMap.cityRegions = new Scene[r, r];
            cityMap.cityPlots = new List<BuildingPlot>();
            cityMap.cityBuildings = new List<CityBuilding>();

            //  Construct land and estate data and update to reflect the found user or the newly created one.
            cityLandData = new LandData();
            RegionInfo regionInfo = new RegionInfo();

            regionInfo.RegionID = UUID.Random();

            //Create an estate
            m_DefaultEstate = new EstateSettings();

            m_log.InfoFormat("[CITY BUILDER]: No estates found for user {0}, constructing default estate.", m_DefaultUserAccount.Name);

            m_DefaultEstate.EstateOwner = m_DefaultUserAccount.PrincipalID;
            m_DefaultEstate.EstateName = m_DefaultEstateName;
            m_DefaultEstate.EstatePass = Util.Md5Hash(Util.Md5Hash(m_DefaultEstatePassword));
            m_DefaultEstate.EstateID = (uint)this.randomValue(1000);

            regionInfo.EstateSettings = m_DefaultEstate; //Just set the estate, this module took care of the loading and the rest will leave it alone

            cityLandData.OwnerID = m_DefaultUserAccount.PrincipalID;
            cityLandData.Name = m_DefaultEstateName;
            cityLandData.GlobalID = UUID.Random();
            cityLandData.GroupID = UUID.Zero;

            int regionPort = startPort;

            //  Construct the region.
            regionInfo.RegionSizeX = cityConfig.GetInt("DefaultRegionSize", 256);
            regionInfo.RegionSizeY = regionInfo.RegionSizeX;
            regionInfo.RegionType = "Mainland";
            regionInfo.ObjectCapacity = 100000;
            regionInfo.Startup = StartupType.Normal;
            regionInfo.ScopeID = UUID.Zero;

            IParcelServiceConnector parcelService = Aurora.DataManager.DataManager.RequestPlugin<IParcelServiceConnector>();
            if (r == 1)
            {
                m_log.Info("[CITY BUILDER]: Single region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                cityLandData.RegionID = regionInfo.RegionID;
                if(parcelService != null)
                    parcelService.StoreLandObject(cityLandData.LandData);
                regionInfo.RegionName = "Region00";
                regionInfo.RegionLocX = (int)m_DefaultStartLocation.X;
                regionInfo.RegionLocY = (int)m_DefaultStartLocation.Y;
                if (!createRegion(0, 0, regionInfo))
                {
                    m_log.Info("[CITY BUILDER]: Failed to construct region.");
                    return (false);
                }
            }
            else if (r > 1)
            {
                m_log.Info("[CITY BUILDER]: Multi-region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                //  Construct the regions for the city.
                regionPort = startPort;
                for (rx = 0; rx < r; rx++)
                {
                    for (ry = 0; ry < r; ry++)
                    {
                        regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                        cityLandData.RegionID = regionInfo.RegionID;
                        if(parcelService != null)
                            parcelService.StoreLandObject(cityLandData.LandData);
                        regionInfo.RegionName = "Region" + rx + ry;
                        regionInfo.RegionLocX = (int)(m_DefaultStartLocation.X + rx);
                        regionInfo.RegionLocY = (int)(m_DefaultStartLocation.Y + ry);
                        m_log.InfoFormat("[CITY BUILDER]: '{0}' @ {1},{2}, http://{3}/", regionInfo.RegionName,
                            regionInfo.RegionLocX, regionInfo.RegionLocY, regionInfo.InternalEndPoint);
                        //We already set the estate before, we don't need to deal with linking it or anything
                        //EstateConnector.LinkRegion(regionInfo.RegionID, (int)m_DefaultEstate.EstateID, m_DefaultEstate.EstatePass);
                        if (!createRegion(rx, ry, regionInfo))
                        {
                            m_log.InfoFormat("[CITY BUILDER]: Failed to construct region at {0},{1}", rx, ry);
                            return (false);
                        }
                    }
                }
            }

            //  Either generate the terrain or loading from an existing file, DEM for example.
            m_log.Info("[CITY BUILDER]: [TERRAIN]");

            //  For each region, just fill the terrain to be 21. This is just above the default
            // water level for Aurora.
            float[,] tHeight = new float[256, 256];
            for (rx = 0; rx < 256; rx++)
            {
                for (ry = 0; ry < 256; ry++)
                {
                    tHeight[rx, ry] = 21.0f;
                }
            }
            //  Construct the new terrain for each region and pass the height map to it.
            for (rx = 0; rx < r; rx++)
            {
                for (ry = 0; ry < r; ry++)
                {
                    Scene region = cityMap.cityRegions[rx, ry];
                    ITerrainChannel tChannel = new TerrainChannel(true, region);
                    ITerrain terrain = null;
                    try
                    {
                        region.TryRequestModuleInterface<ITerrain>(out terrain);
                        terrain.SetHeights2D(tHeight);
                    }
                    catch
                    {
                    }
                }
            }

            //  Rivers and other waterways.

            //  From the total number of regions pick a number of regions that will be 'centers'
            // for the entire city, record these in the centralRegions list.
            m_log.Info("[CITY BUILDER]: [CENTERS]");
            //  ( region count * region count ) / 3
            int aNum = this.randomValue((cityMap.cityRegions.GetUpperBound(0) * cityMap.cityRegions.GetUpperBound(1))/3);
            if (aNum == 0)
            {
                aNum = 1;
            }
            m_log.InfoFormat("[CITY BUILDER]: Total regions {0}, selecting {1} regions for centers.", (r*r), aNum );
            int prevRegionX = 0;
            int prevRegionY = 0;
            while ( aNum > 0 )
            {
                int currRegionX = randomValue( cityMap.cityRegions.GetUpperBound(0) ) / 2;
                int currRegionY = randomValue( cityMap.cityRegions.GetUpperBound(1) ) / 2;

                // If the location selected is the same as the previous location try again.
                if (currRegionX == prevRegionX && currRegionY == prevRegionY)
                {
                    aNum--;
                    continue;
                }

                m_log.InfoFormat("[CITY BUILDER]: Region {0}, located {1},{2}", aNum, prevRegionX, prevRegionY);

                try
                {
                    Scene region = cityMap.centralRegions[(prevRegionX * cityMap.cityRegions.GetUpperBound(0)) + prevRegionY];
                    if (region!=null)
                    {
                        cityMap.centralRegions.Add(region);
                    }
                }
                catch
                {
                }
                aNum--;
                prevRegionX = currRegionX;
                prevRegionY = currRegionY;
            }

            m_log.Info("[CITY BUILDER]: [DENSITY]");
            float avgDensity = 0.0f;

            avgDensity += cityDensities[0];
            avgDensity += cityDensities[1];
            avgDensity += cityDensities[2];
            avgDensity += cityDensities[3];
            avgDensity /= 4;

            //  Before ANYTHING else is created construct the transport systems, priority is given
            // to the road network before the rail network, perhaps a configuration option to allow
            // for the prioritisation value of the transport system is possible.
            m_log.Info("[CITY BUILDER]: [FREEWAYS]");
            m_log.Info("[CITY BUILDER]: [HIGHWAYS]");
            m_log.Info("[CITY BUILDER]: [STREETS]");
            m_log.Info("[CITY BUILDER]: [RAILWAYS]");

            m_log.InfoFormat("[CITY BUILDER]: [RESIDENTIAL DENSITY] {0}%", cityDensities[0] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [COMMERCIAL DENSITY] {0}%", cityDensities[1] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [CORPORATE DENSITY] {0}%", cityDensities[2] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [INDUSTRIAL DENISTY] {0}%", cityDensities[3] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [AVERAGE DENSITY] {0}%", avgDensity);

            m_log.Info("[CITY BUILDER]: [BLOCKS]");
            m_log.Info("[CITY BUILDER]: [ALLOTMENT PLOTS]");
            m_log.Info("[CITY BUILDER]: [BUILDINGS]");

            return (true);
        }
Beispiel #3
0
        /// <summary>
        /// This method will produce a random city with the central region of the city being
        /// specified as a parameter. More parameters need to be made available for this method
        /// to produce a better quality city, note for now the minimum area for a city is a
        /// 3x3 grid of regions. This code is based on the original C++ version called pixel city.
        /// </summary>
        /// <param name="seed_value">Random integer seed value.</param>
        /// <returns>true / false indicator of success or failure.</returns>
        private bool doGenerate(int seed_value)
        {
            int rx, ry;
            //  Based on the initial seed value populate the regions that this shared module
            // is connected to, this means first get a list of the region, determine which
            // region is in the center of all the regions and set this as the hotzone, or
            // central part of the city (this is where the tallest/largest buildings will
            // be created) and will extend out to cover virtually all of the connected
            // regions if desired. No support for aging of the buildings or the city exists
            // yet it is a possible course for the future of this module.

            //  TODO
            //
            //      Validate the details in the configuration file against the settings in
            // the database, otherwise a new user/estate/parcel could be created which will
            // negate any of the security systems that Aurora has in place.

            //  First quick check to see if the module is enabled or not.
            if (!m_fEnabled)
            {
                m_log.Info("[CITY BUILDER]: Disabled, aborting auto generation.");
                return (false);
            }

            m_log.Info("[CITY BUILDER]: Auto generating the city.");

            //  Now we need to ask some basic values for the city generation, we already have
            // the base seed value as this is part of the 'city generate' command, now what
            // about a name, position, size, densities etc. Some of this can be generated
            // based on the seed value, but then, it would need to be confirmed by the user
            // or allow them to change it. TODO move all requested data into the configuration file.
            if (m_UserAccountService == null)
            {
                m_UserAccountService = simulationBase.ApplicationRegistry.RequestModuleInterface<IUserAccountService>();
            }

            //  Decide where the city is to be placed within the server instance.
            int r = CityModule.randomValue(10);

            string regionCount = MainConsole.Instance.CmdPrompt("Region Count ", r.ToString());
            r = Convert.ToInt32(regionCount);
            m_log.InfoFormat("[CITY BUILDER]: City area {0} x {1} regions ", r, r);

            //  Needs to be changed to use the 'defualt' properties and ask about the default
            // estate settings that are to be used, even if it is nothing more than just a
            // confirmation of the settings that are in the configuration file.
            cityName = MainConsole.Instance.CmdPrompt("City Name ", cityName);
            cityOwner = MainConsole.Instance.CmdPrompt("City Owner ", cityOwner);
            m_DefaultUserName = cityOwner;

            //  Make sure that the user and estate information specified in the configuration file
            // have been loaded and the information has either been found or has been created.
            m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, cityOwner);
            if (m_DefaultUserAccount == null)
            {
                m_log.InfoFormat("[CITY BUILDER]: Creating default account {0}", m_DefaultUserName);
                m_UserAccountService.CreateUser(m_DefaultUserName, Util.Md5Hash(m_DefaultUserPword), m_DefaultUserEmail);
                m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, m_DefaultUserName);
                cityOwner = m_DefaultUserName;
            }
            else
                m_log.InfoFormat("[CITY BUILDER]: Account found for {0}", m_DefaultUserName);

            // Obtain the scene manager that the server instance is using.
            sceneManager = simulationBase.ApplicationRegistry.RequestModuleInterface<SceneManager>();

            //  Construct the data instance for a city map to hold the total regions in the simulation.
            cityMap = new CityMap();
            citySeed = seed_value;
            cityMap.cityRegions = new Scene[r, r];
            cityMap.cityPlots = new List<BuildingPlot>();
            cityMap.cityBuildings = new List<CityBuilding>();

            //  Construct land and estate data and update to reflect the found user or the newly created one.
            cityLandData = new LandData();
            RegionInfo regionInfo = new RegionInfo();

            regionInfo.RegionID = UUID.Random();

            //  Determine if the default user account as specified in City Builder's configuration file
            // has any predefined estates, if so, just select the first one for now. Perhaps a search of
            // the estates to attempt to find a match to the details from the configuration file.
            EstateConnector = Aurora.DataManager.DataManager.RequestPlugin<IEstateConnector>();
            // Valid estate connection established.
            if (EstateConnector != null)
            {
                //  Valid estate connector, determine if the default user account has any estates.
                List<EstateSettings> estates = EstateConnector.GetEstates(m_DefaultUserAccount.PrincipalID);
                // No estates are found, so construct a new one based on the default estate settings
                // from the configuration file.
                if (estates == null)
                {
                    // No estates present so construct one.
                    m_DefaultEstate = new EstateSettings();

                    m_log.InfoFormat("[CITY BUILDER]: No estates found for user {0}, constructing default estate.", m_DefaultUserAccount.Name);

                    m_DefaultEstate.EstateOwner = m_DefaultUserAccount.PrincipalID;
                    m_DefaultEstate.EstateName = m_DefaultEstateName;
                    m_DefaultEstate.EstatePass = Util.Md5Hash(Util.Md5Hash(m_DefaultEstatePassword));
                    m_DefaultEstate.EstateID = (uint)CityModule.randomValue(1000);

                    regionInfo.EstateSettings = EstateConnector.CreateEstate(m_DefaultEstate, regionInfo.RegionID);
                }
                else
                {
                    //  Estates have been found, select the first estate in the list. No checking is done
                    // against the configuration file settings. TODO validate the estate against the
                    // configuration file.
                    m_DefaultEstate = estates[0];
                    regionInfo.EstateSettings = m_DefaultEstate;
                    m_log.InfoFormat("[CITY BUILDER]: {0} estates found for user {1}, selecting {2}",
                        estates.Count, m_DefaultUserAccount.Name, m_DefaultEstate.EstateName);
                }
            }
            else
            {
                m_log.Info("[CITY BUILDER]: No connection with server.");
                return (false);
            }

            //  Fill in land data for the estate/owner.
            cityLandData.OwnerID = m_DefaultUserAccount.PrincipalID;
            cityLandData.Name = m_DefaultEstateName;
            cityLandData.GlobalID = UUID.Random();
            cityLandData.GroupID = UUID.Zero;

            int regionPort = startPort;

            //  Construct the region.
            regionInfo.RegionSizeX = cityConfig.GetInt("DefaultRegionSize", 256);
            regionInfo.RegionSizeY = regionInfo.RegionSizeX;
            regionInfo.RegionType = "Mainland";
            regionInfo.ObjectCapacity = 100000;
            regionInfo.Startup = StartupType.Normal;
            regionInfo.ScopeID = UUID.Zero;

            IParcelServiceConnector parcelService = simulationBase.ApplicationRegistry.RequestModuleInterface<IParcelServiceConnector>();
            if (parcelService == null)
            {
                m_log.Info("[CITY BUILDER]: Unable to connect to servers parcel service.");
            }

            if (r == 1)
            {
                m_log.Info("[CITY BUILDER]: Single region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                cityLandData.RegionID = regionInfo.RegionID;
                regionInfo.RegionName = "Region00";
                regionInfo.RegionLocX = (int)m_DefaultStartLocation.X;
                regionInfo.RegionLocY = (int)m_DefaultStartLocation.Y;
                if (parcelService != null)
                    parcelService.StoreLandObject(cityLandData);
                if (!createRegion(0, 0, regionInfo))
                {
                    m_log.Info("[CITY BUILDER]: Failed to construct region.");
                    return (false);
                }
            }
            else if (r > 1)
            {
                m_log.Info("[CITY BUILDER]: Multi-region city.");
                m_log.Info("[CITY BUILDER]: Finding external IP, please wait ... ");
                regionInfo.ExternalHostName = Aurora.Framework.Utilities.GetExternalIp();
                if (regionInfo.ExternalHostName.Length <= 0)
                {
                    regionInfo.FindExternalAutomatically = false;
                }
                else
                {
                    m_log.InfoFormat("[CITY BUILDER]: External IP address is {0}", regionInfo.ExternalHostName);
                    regionInfo.FindExternalAutomatically = true;
                }
                //  Construct the regions for the city.
                regionPort = startPort;
                INeighborService neighbours = simulationBase.ApplicationRegistry.RequestModuleInterface<INeighborService>();
                if (neighbours == null)
                {
                    m_log.Info("[CITY BUILDER]: No neighbours.");
                }
                else
                {
                    m_log.Info("[CITY BUILDER]: Neighbours service found.");
                }
                IPAddress address = IPAddress.Parse("0.0.0.0");

                for (rx = 0; rx < r; rx++)
                {
                    for (ry = 0; ry < r; ry++)
                    {
                        regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                        cityLandData.RegionID = regionInfo.RegionID;
                        regionInfo.RegionName = "Region" + rx + ry;
                        regionInfo.RegionLocX = (int)(m_DefaultStartLocation.X + rx);
                        regionInfo.RegionLocY = (int)(m_DefaultStartLocation.Y + ry);
                        m_log.InfoFormat("[CITY BUILDER]: '{0}' @ {1},{2}, http://{3}/", regionInfo.RegionName,
                            regionInfo.RegionLocX, regionInfo.RegionLocY, regionInfo.InternalEndPoint);
                        if (parcelService != null)
                            parcelService.StoreLandObject(cityLandData);
                        if (!createRegion(rx, ry, regionInfo))
                        {
                            m_log.InfoFormat("[CITY BUILDER]: Failed to construct region at {0},{1}", rx, ry);
                            return (false);
                        }
                        if (neighbours != null)
                        {
                            m_log.Info("[CITY BUILDER]: Informing neighbours.");
                            neighbours.InformOurRegionsOfNewNeighbor(regionInfo);
                        }
                    }
                }
            }

            //  Either generate the terrain or loading from an existing file, DEM for example.
            m_log.Info("[CITY BUILDER]: [TERRAIN]");

            //  Construct the new terrain for each region and pass the height map to it.
            //  For the entire area covered by all of the regions construct a new terrain heightfield for it.
            // Also construct several maps that can be blended together in order to provide a suitablly natural
            // looking terrain which is not too flat or doesn't entirely consist of mountains.
            float[,] terrainMap;
            float[,] hMap1;
            float[,] hMap2;
            float[,] hMap3;
            float[,] hMap4;
            float[] bFactors = new float[4];
            int size = regionInfo.RegionSizeX;
            int y;
            int x;

            terrainMap = new float[ size * r, size * r ];
            hMap1 = new float[ size * r, size * r ];
            hMap2 = new float[ size * r, size * r ];
            hMap3 = new float[ size * r, size * r ];
            hMap4 = new float[ size * r, size * r ];
            //  Set blending factors.
            bFactors[0] = 0.75f;
            bFactors[1] = 0.55f;
            bFactors[2] = 0.35f;
            bFactors[3] = 0.05f;

            //  Generate four layers for the initial height map and then blend them together.
            for (x = 0; x < size; x++)
            {
                for (y = 0; y < size; y++)
                {
                    for (int i = 0; i < r; i++)
                    {
                        for (int j = 0; j < r; j++)
                        {
                            hMap1[i * x, i * y] = Perlin.noise2((float)x+i, (float)y+i);
                            hMap2[i * x, i * y] = Perlin.noise2((float)x, (float)y+i);
                            hMap3[i * x, i * y] = Perlin.noise2((float)x+i, (float)y);
                            hMap4[i * x, i * y] = Perlin.noise2((float)x+j, (float)y+i);
                            terrainMap[i*x, i*y] = (hMap1[i*x, i*y] * bFactors[0]) + (hMap2[i*x, i*y] * bFactors[1]) +
                                (hMap3[i*x, i*y] * bFactors[2]) + (hMap4[i*x, i*y] * bFactors[3]);
                        }
                    }
                }
            }

            //  DEBUG code that will save the resulting terrainMap as a jpeg image.
            m_log.Info("[CITY BUILDER]: Debug, save terrain map (full) as a jpeg image.");
            ManagedImage mImage = new ManagedImage(r * size, r * size, ManagedImage.ImageChannels.Bump);

            //   Find a way of copying the terrainMap array into the newly created image, then save
            // the image to disk.

            m_log.Info("[CITY BUILDER]: Terrain built and blended, tiling and region application.");

            //  Set the height map of each region based on the newly created terrainMap.
            ITerrain terrain = null;
            for (rx = 0; rx < r; rx++)
            {
                for (ry = 0; ry < r; ry++)
                {
                    Scene region = cityMap.cityRegions[rx, ry];
                    ITerrainChannel tChannel = new TerrainChannel(true, region);
                    region.TryRequestModuleInterface<ITerrain>(out terrain);

                    m_log.InfoFormat("[CITY BUILDER]: Region [ {0}, {1} ]", rx, ry);

                    float[,] tile = new float[ size, size ];
                    for (int i = 0; i < size; i++)
                    {
                        for (int j = 0; i < size; j++)
                        {
                            tile[i, j] = terrainMap[(rx * size) + i, (ry * size) + j];
                        }
                    }

                    if (terrain != null & tile!=null)
                        terrain.SetHeights2D(tile);

                    // dispose of the tile now thats its not needed as a new tile is allocated next loop run.
                    tile = null;
                }
            }

            //  Rivers and other waterways. Randomly select a number of rivers for the entire area
            // and place them.
            int rCount = CityModule.randomValue(size / r);
            m_log.InfoFormat("[CITY BUILDER]: River count for entire area {0}", rCount);

            //  From the total number of regions pick a number of regions that will be 'centers'
            // for the entire city, record these in the centralRegions list.
            m_log.Info("[CITY BUILDER]: [CENTERS]");
            //  ( region count * region count ) / 3
            int aNum = CityModule.randomValue((cityMap.cityRegions.GetUpperBound(0) * cityMap.cityRegions.GetUpperBound(1))/3);
            if (aNum == 0)
            {
                aNum = 1;
            }
            m_log.InfoFormat("[CITY BUILDER]: Total regions {0}, selecting {1} regions for centers.", (r*r), aNum );
            int prevRegionX = 0;
            int prevRegionY = 0;
            while ( aNum > 0 )
            {
                int currRegionX = randomValue( cityMap.cityRegions.GetUpperBound(0) ) / 2;
                int currRegionY = randomValue( cityMap.cityRegions.GetUpperBound(1) ) / 2;

                // If the location selected is the same as the previous location try again.
                if (currRegionX == prevRegionX && currRegionY == prevRegionY)
                {
                    aNum--;
                    continue;
                }

                m_log.InfoFormat("[CITY BUILDER]: Region {0}, located {1},{2}", aNum, prevRegionX, prevRegionY);

                try
                {
                    Scene region = cityMap.centralRegions[(prevRegionX * cityMap.cityRegions.GetUpperBound(0)) + prevRegionY];
                    if (region!=null)
                    {
                        cityMap.centralRegions.Add(region);
                    }
                }
                catch
                {
                }
                aNum--;
                prevRegionX = currRegionX;
                prevRegionY = currRegionY;
            }

            m_log.Info("[CITY BUILDER]: [DENSITY]");
            float avgDensity = 0.0f;

            avgDensity += cityDensities[0];
            avgDensity += cityDensities[1];
            avgDensity += cityDensities[2];
            avgDensity += cityDensities[3];
            avgDensity /= 4;

            //  Before ANYTHING else is created construct the transport systems, priority is given
            // to the road network before the rail network, perhaps a configuration option to allow
            // for the prioritisation value of the transport system is possible.
            m_log.Info("[CITY BUILDER]: [FREEWAYS]");

            //  Construct a road system (high speed ~50-70 mph) between and around the city center regions.

            m_log.Info("[CITY BUILDER]: [HIGHWAYS]");

            m_log.Info("[CITY BUILDER]: [STREETS]");

            m_log.Info("[CITY BUILDER]: [RAILWAYS]");

            m_log.InfoFormat("[CITY BUILDER]: [RESIDENTIAL DENSITY] {0}%", cityDensities[0] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [COMMERCIAL DENSITY] {0}%", cityDensities[1] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [CORPORATE DENSITY] {0}%", cityDensities[2] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [INDUSTRIAL DENISTY] {0}%", cityDensities[3] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [AVERAGE DENSITY] {0}%", avgDensity);

            m_log.Info("[CITY BUILDER]: [BLOCKS]");
            m_log.Info("[CITY BUILDER]: [ALLOTMENT PLOTS]");
            m_log.Info("[CITY BUILDER]: [BUILDINGS]");

            return (true);
        }