From 6869633d76b2a6664743a608e4284b8dd7df85a6 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 28 Dec 2013 06:58:15 -0800 Subject: [PATCH] Add serialization/deserialization of region size to RegionInfo, GridRegion, and RegionData. This does not modify interfaces or handling of variable sized regions. This only enables the loading and storing of the region size and the reporting of the region size in grid service responses. The database tables already have the code to load and store the region size. --- OpenSim/Framework/Constants.cs | 6 + OpenSim/Framework/RegionInfo.cs | 189 ++++++++++++++++---- OpenSim/Services/GridService/GridService.cs | 14 +- OpenSim/Services/Interfaces/IGridService.cs | 25 +++ 4 files changed, 195 insertions(+), 39 deletions(-) diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs index a2eb5ee18e..3468ceac85 100644 --- a/OpenSim/Framework/Constants.cs +++ b/OpenSim/Framework/Constants.cs @@ -30,8 +30,14 @@ namespace OpenSim.Framework { public class Constants { + // 'RegionSize' is the legacy region size. + // DO NOT USE THIS FOR ANY NEW CODE. Use Scene.RegionInfo.RegionSize[XYZ] as a region might not + // be the legacy region size. public const uint RegionSize = 256; public const uint RegionHeight = 4096; + // This could be a parameters but, really, a region of greater than this is pretty unmanageable + public const uint MaximumRegionSize = 8192; + public const byte TerrainPatchSize = 16; public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 24b9c89344..857c151506 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -99,6 +99,7 @@ namespace OpenSim.Framework public class RegionInfo { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly string LogHeader = "[REGION INFO]"; public bool commFailTF = false; public ConfigurationMember configMember; @@ -137,16 +138,20 @@ namespace OpenSim.Framework public bool m_allow_alternate_ports; protected string m_externalHostName; protected IPEndPoint m_internalEndPoint; - protected uint? m_regionLocX; - protected uint? m_regionLocY; protected uint m_remotingPort; public UUID RegionID = UUID.Zero; public string RemotingAddress; public UUID ScopeID = UUID.Zero; private UUID m_maptileStaticUUID = UUID.Zero; - private Dictionary m_otherSettings = new Dictionary(); + public uint WorldLocX = 0; + public uint WorldLocY = 0; + public uint WorldLocZ = 0; + public uint RegionSizeX = Constants.RegionSize; + public uint RegionSizeY = Constants.RegionSize; + public uint RegionSizeZ = Constants.RegionHeight; + private Dictionary m_otherSettings = new Dictionary(); // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. @@ -229,11 +234,10 @@ namespace OpenSim.Framework m_serverURI = string.Empty; } - public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) + public RegionInfo(uint legacyRegionLocX, uint legacyRegionLocY, IPEndPoint internalEndPoint, string externalUri) { - m_regionLocX = regionLocX; - m_regionLocY = regionLocY; - + RegionLocX = legacyRegionLocX; + RegionLocY = legacyRegionLocY; m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; m_serverURI = string.Empty; @@ -447,25 +451,42 @@ namespace OpenSim.Framework /// /// The x co-ordinate of this region in map tiles (e.g. 1000). + /// Coordinate is scaled as world coordinates divided by the legacy region size + /// and is thus is the number of legacy regions. /// public uint RegionLocX { - get { return m_regionLocX.Value; } - set { m_regionLocX = value; } + get { return WorldLocX / Constants.RegionSize; } + set { WorldLocX = value * Constants.RegionSize; } } /// /// The y co-ordinate of this region in map tiles (e.g. 1000). + /// Coordinate is scaled as world coordinates divided by the legacy region size + /// and is thus is the number of legacy regions. /// public uint RegionLocY { - get { return m_regionLocY.Value; } - set { m_regionLocY = value; } + get { return WorldLocY / Constants.RegionSize; } + set { WorldLocY = value * Constants.RegionSize; } } + public void SetDefaultRegionSize() + { + WorldLocX = 0; + WorldLocY = 0; + WorldLocZ = 0; + RegionSizeX = Constants.RegionSize; + RegionSizeY = Constants.RegionSize; + RegionSizeZ = Constants.RegionHeight; + } + + // A unique region handle is created from the region's world coordinates. + // This cannot be changed because some code expects to receive the region handle and then + // compute the region coordinates from it. public ulong RegionHandle { - get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); } + get { return Util.UIntsToLong(WorldLocX, WorldLocY); } } public void SetEndPoint(string ipaddr, int port) @@ -572,8 +593,25 @@ namespace OpenSim.Framework string[] locationElements = location.Split(new char[] {','}); - m_regionLocX = Convert.ToUInt32(locationElements[0]); - m_regionLocY = Convert.ToUInt32(locationElements[1]); + RegionLocX = Convert.ToUInt32(locationElements[0]); + RegionLocY = Convert.ToUInt32(locationElements[1]); + + // Region size + // Default to legacy region size if not specified. + allKeys.Remove("SizeX"); + string configSizeX = config.GetString("SizeX", Constants.RegionSize.ToString()); + config.Set("SizeX", configSizeX); + RegionSizeX = Convert.ToUInt32(configSizeX); + allKeys.Remove("SizeY"); + string configSizeY = config.GetString("SizeY", Constants.RegionSize.ToString()); + config.Set("SizeY", configSizeX); + RegionSizeY = Convert.ToUInt32(configSizeY); + allKeys.Remove("SizeZ"); + string configSizeZ = config.GetString("SizeZ", Constants.RegionHeight.ToString()); + config.Set("SizeZ", configSizeX); + RegionSizeZ = Convert.ToUInt32(configSizeZ); + + DoRegionSizeSanityChecks(); // InternalAddress // @@ -693,6 +731,57 @@ namespace OpenSim.Framework } } + // Make sure user specified region sizes are sane. + // Must be multiples of legacy region size (256). + private void DoRegionSizeSanityChecks() + { + if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize) + { + // Doing non-legacy region sizes. + // Enforce region size to be multiples of the legacy region size (256) + uint partial = RegionSizeX % Constants.RegionSize; + if (partial != 0) + { + RegionSizeX -= partial; + if (RegionSizeX == 0) + RegionSizeX = Constants.RegionSize; + m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeX={3} instead of specified {4}", + LogHeader, Constants.RegionSize, m_regionName, RegionSizeX, RegionSizeX + partial); + } + partial = RegionSizeY % Constants.RegionSize; + if (partial != 0) + { + RegionSizeY -= partial; + if (RegionSizeY == 0) + RegionSizeY = Constants.RegionSize; + m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeY={3} instead of specified {4}", + LogHeader, Constants.RegionSize, m_regionName, RegionSizeY, RegionSizeY + partial); + } + + // Because of things in the viewer, regions MUST be square. + // Remove this check when viewers have been updated. + if (RegionSizeX != RegionSizeY) + { + uint minSize = Math.Min(RegionSizeX, RegionSizeY); + RegionSizeX = minSize; + RegionSizeY = minSize; + m_log.ErrorFormat("{0} Regions must be square until viewers are updated. Forcing region {1} size to <{2},{3}>", + LogHeader, m_regionName, RegionSizeX, RegionSizeY); + } + + // There is a practical limit to region size. + if (RegionSizeX > Constants.MaximumRegionSize || RegionSizeY > Constants.MaximumRegionSize) + { + RegionSizeX = Util.Clamp(RegionSizeX, Constants.RegionSize, Constants.MaximumRegionSize); + RegionSizeY = Util.Clamp(RegionSizeY, Constants.RegionSize, Constants.MaximumRegionSize); + m_log.ErrorFormat("{0} Region dimensions must be less than {1}. Clamping {2}'s size to <{3},{4}>", + LogHeader, Constants.MaximumRegionSize, m_regionName, RegionSizeX, RegionSizeY); + } + + m_log.InfoFormat("{0} Region {1} size set to <{2},{3}>", LogHeader, m_regionName, RegionSizeX, RegionSizeY); + } + } + private void WriteNiniConfig(IConfigSource source) { IConfig config = source.Configs[RegionName]; @@ -704,9 +793,16 @@ namespace OpenSim.Framework config.Set("RegionUUID", RegionID.ToString()); - string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY); + string location = String.Format("{0},{1}", RegionLocX, RegionLocY); config.Set("Location", location); + if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize) + { + config.Set("SizeX", RegionSizeX); + config.Set("SizeY", RegionSizeY); + config.Set("SizeZ", RegionSizeZ); + } + config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); config.Set("InternalPort", m_internalEndPoint.Port); @@ -789,10 +885,18 @@ namespace OpenSim.Framework RegionID.ToString(), true); configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Region Name", RegionName, true); + configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, - "Grid Location (X Axis)", m_regionLocX.ToString(), true); + "Grid Location (X Axis)", RegionLocX.ToString(), true); configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, - "Grid Location (Y Axis)", m_regionLocY.ToString(), true); + "Grid Location (Y Axis)", RegionLocY.ToString(), true); + configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Size of region in X dimension", RegionSizeX.ToString(), true); + configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Size of region in Y dimension", RegionSizeY.ToString(), true); + configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Size of region in Z dimension", RegionSizeZ.ToString(), true); + //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); configMember.addConfigurationOption("internal_ip_address", ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, @@ -855,10 +959,18 @@ namespace OpenSim.Framework UUID.Random().ToString(), true); configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Region Name", "OpenSim Test", false); + configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, "Grid Location (X Axis)", "1000", false); configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, "Grid Location (Y Axis)", "1000", false); + configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Size of region in X dimension", Constants.RegionSize.ToString(), false); + configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Size of region in Y dimension", Constants.RegionSize.ToString(), false); + configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Size of region in Z dimension", Constants.RegionHeight.ToString(), false); + //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); configMember.addConfigurationOption("internal_ip_address", ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, @@ -916,10 +1028,19 @@ namespace OpenSim.Framework RegionName = (string) configuration_result; break; case "sim_location_x": - m_regionLocX = (uint) configuration_result; + RegionLocX = (uint) configuration_result; break; case "sim_location_y": - m_regionLocY = (uint) configuration_result; + RegionLocY = (uint) configuration_result; + break; + case "sim_size_x": + RegionSizeX = (uint) configuration_result; + break; + case "sim_size_y": + RegionSizeY = (uint) configuration_result; + break; + case "sim_size_z": + RegionSizeZ = (uint) configuration_result; break; case "internal_ip_address": IPAddress address = (IPAddress) configuration_result; @@ -1000,8 +1121,13 @@ namespace OpenSim.Framework args["external_host_name"] = OSD.FromString(ExternalHostName); args["http_port"] = OSD.FromString(HttpPort.ToString()); args["server_uri"] = OSD.FromString(ServerURI); + args["region_xloc"] = OSD.FromString(RegionLocX.ToString()); args["region_yloc"] = OSD.FromString(RegionLocY.ToString()); + args["region_size_x"] = OSD.FromString(RegionSizeX.ToString()); + args["region_size_y"] = OSD.FromString(RegionSizeY.ToString()); + args["region_size_z"] = OSD.FromString(RegionSizeZ.ToString()); + args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString()); args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString()); if ((RemotingAddress != null) && !RemotingAddress.Equals("")) @@ -1040,6 +1166,13 @@ namespace OpenSim.Framework UInt32.TryParse(args["region_yloc"].AsString(), out locy); RegionLocY = locy; } + if (args.ContainsKey("region_size_x")) + RegionSizeX = (uint)args["region_size_x"].AsInteger(); + if (args.ContainsKey("region_size_y")) + RegionSizeY = (uint)args["region_size_y"].AsInteger(); + if (args.ContainsKey("region_size_z")) + RegionSizeZ = (uint)args["region_size_z"].AsInteger(); + IPAddress ip_addr = null; if (args["internal_ep_address"] != null) { @@ -1076,23 +1209,5 @@ namespace OpenSim.Framework regionInfo.ServerURI = serverURI; return regionInfo; } - - public Dictionary ToKeyValuePairs() - { - Dictionary kvp = new Dictionary(); - kvp["uuid"] = RegionID.ToString(); - kvp["locX"] = RegionLocX.ToString(); - kvp["locY"] = RegionLocY.ToString(); - kvp["external_ip_address"] = ExternalEndPoint.Address.ToString(); - kvp["external_port"] = ExternalEndPoint.Port.ToString(); - kvp["external_host_name"] = ExternalHostName; - kvp["http_port"] = HttpPort.ToString(); - kvp["internal_ip_address"] = InternalEndPoint.Address.ToString(); - kvp["internal_port"] = InternalEndPoint.Port.ToString(); - kvp["alternate_ports"] = m_allow_alternate_ports.ToString(); - kvp["server_uri"] = ServerURI; - - return kvp; - } } } diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index e72b7f98e9..137ce04ead 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -313,8 +313,9 @@ namespace OpenSim.Services.GridService if (region != null) { // Not really? Maybe? - List rdatas = m_Database.Get(region.posX - (int)Constants.RegionSize - 1, region.posY - (int)Constants.RegionSize - 1, - region.posX + (int)Constants.RegionSize + 1, region.posY + (int)Constants.RegionSize + 1, scopeID); + List rdatas = m_Database.Get( + region.posX - region.sizeX - 1, region.posY - region.sizeY - 1, + region.posX + region.sizeX + 1, region.posY + region.sizeY + 1, scopeID); foreach (RegionData rdata in rdatas) { @@ -347,6 +348,11 @@ namespace OpenSim.Services.GridService return null; } + // Get a region given its base coordinates. + // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST + // be the base coordinate of the region. + // The snapping is technically unnecessary but is harmless because regions are always + // multiples of the legacy region size (256). public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) { int snapX = (int)(x / Constants.RegionSize) * (int)Constants.RegionSize; @@ -441,6 +447,8 @@ namespace OpenSim.Services.GridService RegionData rdata = new RegionData(); rdata.posX = (int)rinfo.RegionLocX; rdata.posY = (int)rinfo.RegionLocY; + rdata.sizeX = rinfo.RegionSizeX; + rdata.sizeY = rinfo.RegionSizeY; rdata.RegionID = rinfo.RegionID; rdata.RegionName = rinfo.RegionName; rdata.Data = rinfo.ToKeyValuePairs(); @@ -454,6 +462,8 @@ namespace OpenSim.Services.GridService GridRegion rinfo = new GridRegion(rdata.Data); rinfo.RegionLocX = rdata.posX; rinfo.RegionLocY = rdata.posY; + rinfo.RegionSizeX = rdata.sizeX; + rinfo.RegionSizeY = rdata.sizeY; rinfo.RegionID = rdata.RegionID; rinfo.RegionName = rdata.RegionName; rinfo.ScopeID = rdata.ScopeID; diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 88ac5b3653..651bd976a5 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -177,6 +177,7 @@ namespace OpenSim.Services.Interfaces /// /// The location of this region in meters. + /// DANGER DANGER! Note that this name means something different in RegionInfo. /// public int RegionLocX { @@ -185,8 +186,12 @@ namespace OpenSim.Services.Interfaces } protected int m_regionLocX; + public int RegionSizeX { get; set; } + public int RegionSizeY { get; set; } + /// /// The location of this region in meters. + /// DANGER DANGER! Note that this name means something different in RegionInfo. /// public int RegionLocY { @@ -218,10 +223,13 @@ namespace OpenSim.Services.Interfaces m_serverURI = string.Empty; } + /* public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) { m_regionLocX = regionLocX; m_regionLocY = regionLocY; + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; @@ -231,16 +239,21 @@ namespace OpenSim.Services.Interfaces { m_regionLocX = regionLocX; m_regionLocY = regionLocY; + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; m_externalHostName = externalUri; m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)port); } + */ public GridRegion(uint xcell, uint ycell) { m_regionLocX = (int)(xcell * Constants.RegionSize); m_regionLocY = (int)(ycell * Constants.RegionSize); + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; } public GridRegion(RegionInfo ConvertFrom) @@ -248,6 +261,8 @@ namespace OpenSim.Services.Interfaces m_regionName = ConvertFrom.RegionName; m_regionLocX = (int)(ConvertFrom.RegionLocX * Constants.RegionSize); m_regionLocY = (int)(ConvertFrom.RegionLocY * Constants.RegionSize); + RegionSizeX = (int)ConvertFrom.RegionSizeX; + RegionSizeY = (int)ConvertFrom.RegionSizeY; m_internalEndPoint = ConvertFrom.InternalEndPoint; m_externalHostName = ConvertFrom.ExternalHostName; m_httpPort = ConvertFrom.HttpPort; @@ -266,6 +281,8 @@ namespace OpenSim.Services.Interfaces m_regionName = ConvertFrom.RegionName; m_regionLocX = ConvertFrom.RegionLocX; m_regionLocY = ConvertFrom.RegionLocY; + RegionSizeX = ConvertFrom.RegionSizeX; + RegionSizeY = ConvertFrom.RegionSizeY; m_internalEndPoint = ConvertFrom.InternalEndPoint; m_externalHostName = ConvertFrom.ExternalHostName; m_httpPort = ConvertFrom.HttpPort; @@ -373,6 +390,8 @@ namespace OpenSim.Services.Interfaces kvp["uuid"] = RegionID.ToString(); kvp["locX"] = RegionLocX.ToString(); kvp["locY"] = RegionLocY.ToString(); + kvp["sizeX"] = RegionSizeX.ToString(); + kvp["sizeY"] = RegionSizeY.ToString(); kvp["regionName"] = RegionName; kvp["serverIP"] = ExternalHostName; //ExternalEndPoint.Address.ToString(); kvp["serverHttpPort"] = HttpPort.ToString(); @@ -399,6 +418,12 @@ namespace OpenSim.Services.Interfaces if (kvp.ContainsKey("locY")) RegionLocY = Convert.ToInt32((string)kvp["locY"]); + if (kvp.ContainsKey("sizeX")) + RegionSizeX = Convert.ToInt32((string)kvp["sizeX"]); + + if (kvp.ContainsKey("sizeY")) + RegionSizeY = Convert.ToInt32((string)kvp["sizeY"]); + if (kvp.ContainsKey("regionName")) RegionName = (string)kvp["regionName"];