diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 13485bf3e1..25e14547c8 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -98,11 +98,17 @@ namespace OpenSim.Region.CoreModules.World.Land // caches ExtendedLandData private Cache parcelInfoCache; + /// /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. /// private Dictionary forcedPosition = new Dictionary(); + // Enables limiting parcel layer info transmission when doing simple updates + private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } + // "View distance" for sending parcel layer info if asked for from a view point in the region + private int parcelLayerViewDistance { get; set; } + #region INonSharedRegionModule Members public Type ReplaceableInterface @@ -112,6 +118,14 @@ namespace OpenSim.Region.CoreModules.World.Land public void Initialise(IConfigSource source) { + shouldLimitParcelLayerInfoToViewDistance = true; + parcelLayerViewDistance = 128; + IConfig landManagementConfig = source.Configs["LandManagement"]; + if (landManagementConfig != null) + { + shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); + parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); + } } public void AddRegion(Scene scene) @@ -1129,11 +1143,26 @@ namespace OpenSim.Region.CoreModules.World.Land #region Parcel Updating + // Send parcel layer info for the whole region + public void SendParcelOverlay(IClientAPI remote_client) + { + SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize); + } + /// - /// Where we send the ParcelOverlay packet to the client + /// Send the parcel overlay blocks to the client. We send the overlay packets + /// around a location and limited by the 'parcelLayerViewDistance'. This number + /// is usually 128 and the code is arranged so it sends all the parcel overlay + /// information for a whole region if the region is legacy sized (256x256). If + /// the region is larger, only the parcel layer information is sent around + /// the point specified. This reduces the problem of parcel layer information + /// blocks increasing exponentially as region size increases. /// /// The object representing the client - public void SendParcelOverlay(IClientAPI remote_client) + /// X position in the region to send surrounding parcel layer info + /// y position in the region to send surrounding parcel layer info + /// Distance from x,y position to send parcel layer info + private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance) { const int LAND_BLOCKS_PER_PACKET = 1024; @@ -1141,15 +1170,58 @@ namespace OpenSim.Region.CoreModules.World.Land int byteArrayCount = 0; int sequenceID = 0; - // Layer data is in landUnit (4m) chunks - for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) + int xLow = 0; + int xHigh = (int)m_scene.RegionInfo.RegionSizeX; + int yLow = 0; + int yHigh = (int)m_scene.RegionInfo.RegionSizeY; + + if (shouldLimitParcelLayerInfoToViewDistance) { - for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) + // Compute view distance around the given point + int txLow = xPlace - layerViewDistance; + int txHigh = xPlace + layerViewDistance; + // If the distance is outside the region area, move the view distance to ba all in the region + if (txLow < xLow) + { + txLow = xLow; + txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh); + } + if (txHigh > xHigh) + { + txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); + txHigh = xHigh; + } + xLow = txLow; + xHigh = txHigh; + + int tyLow = yPlace - layerViewDistance; + int tyHigh = yPlace + layerViewDistance; + if (tyLow < yLow) + { + tyLow = yLow; + tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh); + } + if (tyHigh > yHigh) + { + tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2)); + tyHigh = yHigh; + } + yLow = tyLow; + yHigh = tyHigh; + } + // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>", + // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh); + + // Layer data is in landUnit (4m) chunks + for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) + { + for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) { byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client); byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { + // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; @@ -1162,6 +1234,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (byteArrayCount != 0) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); + // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); } } @@ -1265,7 +1338,8 @@ namespace OpenSim.Region.CoreModules.World.Land temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); } - SendParcelOverlay(remote_client); + // Also send the layer data around the point of interest + SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); } public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 55ca32f977..a5d7f1dffd 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1940,6 +1940,18 @@ ; the avatar outward. SendTerrainUpdatesByViewDistance = True +[LandManagement] + ; When editing terrain or objects, parcel layer info is updated in the viewer. + ; This can be expensive for large regions. If this variable is 'true', only the + ; parcel layer data around the area of interest is sent. The parcel layer info + ; is sent for 'ParcelLayerViewDistance' around the interest point. + ; If 'ParcelLayerViewDistance' is >= 128, the operation for legacy sized regions + ; will be what it has always been (send the whole region's parcel layer info). + ; Other parcel updates (login, changing parcel ownership, ...) will still send + ; whole region. + LimitParcelLayerUpdateDistance = true + ParcelLayerViewDistance = 128 + ;; ;; If you are using a simian grid frontend you can enable ;; this module to upload tile images for the mapping fn