From a7a837550e0ef036c5da43b1ec42a523e28b0cc0 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 8 Nov 2013 20:51:09 -0800 Subject: varregion: Massive work to LandManagementModule and LandObject to handle variable sized regions. Many changes for both the region and parcels. Most of the constant "4" (for the 4x4 parcel units) have been replaced with symbols and math. --- .../CoreModules/World/Land/LandManagementModule.cs | 304 ++++++++++++++------- .../Region/CoreModules/World/Land/LandObject.cs | 174 ++++++------ 2 files changed, 295 insertions(+), 183 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 51ed83f..3f21f85 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.CoreModules.World.Land public class LandManagementModule : INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]"; private static readonly string remoteParcelRequestPath = "0009/"; @@ -76,15 +77,11 @@ namespace OpenSim.Region.CoreModules.World.Land protected IPrimCountModule m_primCountModule; protected IDialogModule m_Dialog; - // Minimum for parcels to work is 64m even if we don't actually use them. - #pragma warning disable 0429 - private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; - #pragma warning restore 0429 - /// /// Local land ids at specified region co-ordinates (region size / 4) /// - private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax]; + private int[,] m_landIDList; + private const int landUnit = 4; /// /// Land objects keyed by local id @@ -117,6 +114,8 @@ namespace OpenSim.Region.CoreModules.World.Land public void AddRegion(Scene scene) { m_scene = scene; + m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; + m_landIDList.Initialize(); landChannel = new LandChannel(scene, this); @@ -326,6 +325,7 @@ namespace OpenSim.Region.CoreModules.World.Land { m_landList.Clear(); m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; + m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; m_landIDList.Initialize(); } } @@ -340,7 +340,8 @@ namespace OpenSim.Region.CoreModules.World.Land "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); - fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); + fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, + (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); @@ -467,8 +468,8 @@ namespace OpenSim.Region.CoreModules.World.Land public void SendLandUpdate(ScenePresence avatar, bool force) { - ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), - (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); + ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), + (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); if (over != null) { @@ -634,17 +635,29 @@ namespace OpenSim.Region.CoreModules.World.Land new_land.LandData.LocalID = newLandLocalID; bool[,] landBitmap = new_land.GetLandBitmap(); - for (int x = 0; x < landArrayMax; x++) + m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). bitmap[600/4,600/4]={3}, newLocalID={4}", + LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), landBitmap[600/4, 600/4], newLandLocalID); + + if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1)) + { + // Going to variable sized regions can cause mismatches + m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})", + LogHeader, landBitmap.GetLength(0), m_landIDList.GetLength(1), landBitmap.GetLength(0), m_landIDList.GetLength(1) ); + } + else { - for (int y = 0; y < landArrayMax; y++) + for (int x = 0; x < landBitmap.GetLength(0); x++) { - if (landBitmap[x, y]) + for (int y = 0; y < landBitmap.GetLength(1); y++) { -// m_log.DebugFormat( -// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", -// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); - - m_landIDList[x, y] = newLandLocalID; + if (landBitmap[x, y]) + { + // m_log.DebugFormat( + // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", + // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); + + m_landIDList[x, y] = newLandLocalID; + } } } } @@ -666,9 +679,9 @@ namespace OpenSim.Region.CoreModules.World.Land ILandObject land; lock (m_landList) { - for (int x = 0; x < 64; x++) + for (int x = 0; x < m_landIDList.GetLength(0); x++) { - for (int y = 0; y < 64; y++) + for (int y = 0; y < m_landIDList.GetLength(1); y++) { if (m_landIDList[x, y] == local_id) { @@ -720,9 +733,9 @@ namespace OpenSim.Region.CoreModules.World.Land bool[,] landBitmapSlave = slave.GetLandBitmap(); lock (m_landList) { - for (int x = 0; x < 64; x++) + for (int x = 0; x < landBitmapSlave.GetLength(0); x++) { - for (int y = 0; y < 64; y++) + for (int y = 0; y < landBitmapSlave.GetLength(1); y++) { if (landBitmapSlave[x, y]) { @@ -756,23 +769,28 @@ namespace OpenSim.Region.CoreModules.World.Land /// Land object at the point supplied public ILandObject GetLandObject(float x_float, float y_float) { + return GetLandObject((int)x_float, (int)y_float); + /* int x; int y; - if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) + if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0) return null; try { - x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); - y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); + x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); + y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); } catch (OverflowException) { return null; } - if (x >= 64 || y >= 64 || x < 0 || y < 0) + if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) + || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) + || x < 0 + || y < 0) { return null; } @@ -788,38 +806,112 @@ namespace OpenSim.Region.CoreModules.World.Land // m_log.DebugFormat( // "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", // x, y, m_scene.RegionInfo.RegionName); - - if (m_landList.ContainsKey(m_landIDList[x, y])) - return m_landList[m_landIDList[x, y]]; + + try + { + if (m_landList.ContainsKey(m_landIDList[x, y])) + return m_landList[m_landIDList[x, y]]; + } + catch (Exception e) + { + m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})", + LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1)); + } return null; } + */ } + // Given a region position, return the parcel land object for that location public ILandObject GetLandObject(int x, int y) { - if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) + ILandObject ret = null; + + if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) { // These exceptions here will cause a lot of complaints from the users specifically because // they happen every time at border crossings - throw new Exception("Error: Parcel not found at point " + x + ", " + y); + throw new Exception( + String.Format("{0} GetLandObject for non-existant position. Region={1}, pos=<{2},{3}", + LogHeader, m_scene.RegionInfo.RegionName, x, y) + ); } lock (m_landIDList) { try { - return m_landList[m_landIDList[x / 4, y / 4]]; + int landID = m_landIDList[x / landUnit, y / landUnit]; + if (landID == 0) + { + // Zero is the uninitialized value saying there is no parcel for this location. + // This sometimes happens when terrain is resized. + if (m_landList.Count == 1) + { + int onlyParcelID = 0; + ILandObject onlyLandObject = null; + foreach (KeyValuePair kvp in m_landList) + { + onlyParcelID = kvp.Key; + onlyLandObject = kvp.Value; + break; + } + + // There is only one parcel. Grow it to fill all the unallocated spaces. + for (int xx = 0; xx < m_landIDList.GetLength(0); xx++) + for (int yy = 0; yy < m_landIDList.GetLength(1); yy++) + if (m_landIDList[xx, yy] == 0) + m_landIDList[xx, yy] = onlyParcelID; + + onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID); + landID = onlyParcelID; + } + else + { + // There are several other parcels so we must create a new one for the unassigned space + ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); + // Claim all the unclaimed "0" ids + newLand.SetLandBitmap(CreateBitmapForID(0)); + newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); + AddLandObject(newLand); + landID = m_lastLandLocalID; + } + } + + ret = m_landList[landID]; } catch (IndexOutOfRangeException) { -// m_log.WarnFormat( -// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}", -// x, y, m_scene.RegionInfo.RegionName); - + m_log.ErrorFormat( + "{0} GetLandObject: Tried to retrieve land object from out of bounds co-ordinate ({1},{2}) in {3}. landListSize=({4},{5})", + LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList.GetLength(0), m_landIDList.GetLength(1)); + return null; + } + catch + { + m_log.ErrorFormat( + "{0} GetLandObject: LandID not in landlist. XY=<{1},{2}> in {3}. landID[x,y]={4}", + LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList[x/landUnit, y/landUnit]); return null; } } + return ret; + } + + // Create a 'parcel is here' bitmap for the parcel identified by the passed landID + private bool[,] CreateBitmapForID(int landID) + { + bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)]; + ret.Initialize(); + + for (int xx = 0; xx < m_landIDList.GetLength(0); xx++) + for (int yy = 0; yy < m_landIDList.GetLength(0); yy++) + if (m_landIDList[xx, yy] == landID) + ret[xx, yy] = true; + + return ret; } #endregion @@ -1082,85 +1174,93 @@ namespace OpenSim.Region.CoreModules.World.Land byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; - int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize; - - for (int y = 0; y < blockmeters; y++) + // Layer data is in landUnit (4m) chunks + for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); y++) { - for (int x = 0; x < blockmeters; x++) + for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); x++) { - byte tempByte = 0; //This represents the byte for the current 4x4 + byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * landUnit, y * landUnit), x, y, remote_client); + byteArrayCount++; + if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) + { + remote_client.SendLandParcelOverlay(byteArray, sequenceID); + byteArrayCount = 0; + sequenceID++; + byteArray = new byte[LAND_BLOCKS_PER_PACKET]; + } - ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); + } + } + if (byteArrayCount != 0) + { + remote_client.SendLandParcelOverlay(byteArray, sequenceID); + } + } - if (currentParcelBlock != null) - { - if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) - { - //Owner Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); - } - else if (currentParcelBlock.LandData.SalePrice > 0 && - (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || - currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) - { - //Sale Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); - } - else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) - { - //Public Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); - } - else - { - //Other Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); - } + private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client) + { + byte tempByte = 0; //This represents the byte for the current 4x4 - //Now for border control + if (currentParcelBlock != null) + { + if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) + { + //Owner Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); + } + else if (currentParcelBlock.LandData.SalePrice > 0 && + (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || + currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) + { + //Sale Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); + } + else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) + { + //Public Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); + } + else + { + //Other Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); + } - ILandObject westParcel = null; - ILandObject southParcel = null; - if (x > 0) - { - westParcel = GetLandObject((x - 1) * 4, y * 4); - } - if (y > 0) - { - southParcel = GetLandObject(x * 4, (y - 1) * 4); - } + //Now for border control - if (x == 0) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); - } - else if (westParcel != null && westParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); - } + ILandObject westParcel = null; + ILandObject southParcel = null; + if (x > 0) + { + westParcel = GetLandObject((x - 1) * landUnit, y * landUnit); + } + if (y > 0) + { + southParcel = GetLandObject(x * landUnit, (y - 1) * landUnit); + } - if (y == 0) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); - } - else if (southParcel != null && southParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); - } + if (x == 0) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); + } + else if (westParcel != null && westParcel != currentParcelBlock) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); + } - byteArray[byteArrayCount] = tempByte; - byteArrayCount++; - if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) - { - remote_client.SendLandParcelOverlay(byteArray, sequenceID); - byteArrayCount = 0; - sequenceID++; - byteArray = new byte[LAND_BLOCKS_PER_PACKET]; - } - } + if (y == 0) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); + } + else if (southParcel != null && southParcel != currentParcelBlock) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); } + } + + return tempByte; } public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index e55c9ed..0bde877 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -45,10 +45,10 @@ namespace OpenSim.Region.CoreModules.World.Land #region Member Variables private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - #pragma warning disable 0429 - private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; - #pragma warning restore 0429 - private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; + private static readonly string LogHeader = "[LAND OBJECT]"; + + private bool[,] m_landBitmap; + private readonly int landUnit = 4; private int m_lastSeqId = 0; @@ -93,12 +93,12 @@ namespace OpenSim.Region.CoreModules.World.Land { get { - for (int y = 0; y < landArrayMax; y++) + for (int y = 0; y < LandBitmap.GetLength(1); y++) { - for (int x = 0; x < landArrayMax; x++) + for (int x = 0; x < LandBitmap.GetLength(0); x++) { if (LandBitmap[x, y]) - return new Vector3(x * 4, y * 4, 0); + return new Vector3(x * landUnit, y * landUnit, 0); } } @@ -110,13 +110,13 @@ namespace OpenSim.Region.CoreModules.World.Land { get { - for (int y = landArrayMax - 1; y >= 0; y--) + for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--) { - for (int x = landArrayMax - 1; x >= 0; x--) + for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--) { if (LandBitmap[x, y]) { - return new Vector3(x * 4 + 4, y * 4 + 4, 0); + return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0); } } } @@ -130,6 +130,8 @@ namespace OpenSim.Region.CoreModules.World.Land public LandObject(UUID owner_id, bool is_group_owned, Scene scene) { m_scene = scene; + m_landBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; + LandData.OwnerID = owner_id; if (is_group_owned) LandData.GroupID = owner_id; @@ -152,9 +154,9 @@ namespace OpenSim.Region.CoreModules.World.Land /// Returns true if the piece of land contains the specified point public bool ContainsPoint(int x, int y) { - if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize) + if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY) { - return (LandBitmap[x / 4, y / 4] == true); + return (LandBitmap[x / landUnit, y / landUnit] == true); } else { @@ -194,7 +196,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { // Normal Calculations - int parcelMax = (int)(((float)LandData.Area / 65536.0f) + int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! @@ -211,7 +213,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { //Normal Calculations - int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) + int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) * (float)m_scene.RegionInfo.ObjectCapacity); return simMax; } @@ -224,7 +226,12 @@ namespace OpenSim.Region.CoreModules.World.Land public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) { IEstateModule estateModule = m_scene.RequestModuleInterface(); - uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); + // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); + uint regionFlags = (uint)(RegionFlags.PublicAllowed + | RegionFlags.AllowDirectTeleport + | RegionFlags.AllowParcelChanges + | RegionFlags.AllowVoice ); + if (estateModule != null) regionFlags = estateModule.GetRegionFlags(); @@ -546,8 +553,8 @@ namespace OpenSim.Region.CoreModules.World.Land try { over = - m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), - Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); + m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)), + Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1))); } catch (Exception) { @@ -694,15 +701,15 @@ namespace OpenSim.Region.CoreModules.World.Land /// private void UpdateAABBAndAreaValues() { - int min_x = 64; - int min_y = 64; + int min_x = 10000; + int min_y = 10000; int max_x = 0; int max_y = 0; int tempArea = 0; int x, y; - for (x = 0; x < 64; x++) + for (x = 0; x < LandBitmap.GetLength(0); x++) { - for (y = 0; y < 64; y++) + for (y = 0; y < LandBitmap.GetLength(1); y++) { if (LandBitmap[x, y] == true) { @@ -710,31 +717,31 @@ namespace OpenSim.Region.CoreModules.World.Land if (min_y > y) min_y = y; if (max_x < x) max_x = x; if (max_y < y) max_y = y; - tempArea += 16; //16sqm peice of land + tempArea += landUnit * landUnit; //16sqm peice of land } } } - int tx = min_x * 4; - if (tx > ((int)Constants.RegionSize - 1)) - tx = ((int)Constants.RegionSize - 1); - int ty = min_y * 4; - if (ty > ((int)Constants.RegionSize - 1)) - ty = ((int)Constants.RegionSize - 1); + int tx = min_x * landUnit; + if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) + tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); + int ty = min_y * landUnit; + if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) + ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); LandData.AABBMin = new Vector3( - (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); + (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); - tx = max_x * 4; - if (tx > ((int)Constants.RegionSize - 1)) - tx = ((int)Constants.RegionSize - 1); - ty = max_y * 4; - if (ty > ((int)Constants.RegionSize - 1)) - ty = ((int)Constants.RegionSize - 1); + tx = max_x * landUnit; + if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) + tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); + ty = max_y * landUnit; + if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) + ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); LandData.AABBMax = new Vector3( - (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); + (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); LandData.Area = tempArea; } @@ -746,20 +753,11 @@ namespace OpenSim.Region.CoreModules.World.Land /// /// Sets the land's bitmap manually /// - /// 64x64 block representing where this land is on a map + /// block representing where this land is on a map mapped in a 4x4 meter grid public void SetLandBitmap(bool[,] bitmap) { - if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap"); - } - else - { - //Valid: Lets set it - LandBitmap = bitmap; - ForceUpdateLandInfo(); - } + LandBitmap = bitmap; + ForceUpdateLandInfo(); } /// @@ -773,12 +771,12 @@ namespace OpenSim.Region.CoreModules.World.Land public bool[,] BasicFullRegionLandBitmap() { - return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); + return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY); } public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) { - bool[,] tempBitmap = new bool[64,64]; + bool[,] tempBitmap = new bool[(end_x-start_x)/landUnit,(end_y-start_y)/landUnit]; tempBitmap.Initialize(); tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); @@ -798,19 +796,13 @@ namespace OpenSim.Region.CoreModules.World.Land public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, bool set_value) { - if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); - } - int x, y; - for (y = 0; y < 64; y++) + for (y = 0; y < land_bitmap.GetLength(1); y++) { - for (x = 0; x < 64; x++) + for (x = 0; x < land_bitmap.GetLength(0); x++) { - if (x >= start_x / 4 && x < end_x / 4 - && y >= start_y / 4 && y < end_y / 4) + if (x >= start_x / landUnit && x < end_x / landUnit + && y >= start_y / landUnit && y < end_y / landUnit) { land_bitmap[x, y] = set_value; } @@ -827,21 +819,21 @@ namespace OpenSim.Region.CoreModules.World.Land /// public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) { - if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) + if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0) + || bitmap_base.GetLength(1) != bitmap_add.GetLength(1) + || bitmap_add.Rank != 2 + || bitmap_base.Rank != 2) { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); - } - if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); + throw new Exception( + String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>", + LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1)) + ); } int x, y; - for (y = 0; y < 64; y++) + for (y = 0; y < bitmap_base.GetLength(1); y++) { - for (x = 0; x < 64; x++) + for (x = 0; x < bitmap_add.GetLength(0); x++) { if (bitmap_add[x, y]) { @@ -858,13 +850,13 @@ namespace OpenSim.Region.CoreModules.World.Land /// private byte[] ConvertLandBitmapToBytes() { - byte[] tempConvertArr = new byte[512]; + byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8]; byte tempByte = 0; - int x, y, i, byteNum = 0; - i = 0; - for (y = 0; y < 64; y++) + int byteNum = 0; + int i = 0; + for (int y = 0; y < LandBitmap.GetLength(1); y++) { - for (x = 0; x < 64; x++) + for (int x = 0; x < LandBitmap.GetLength(0); x++) { tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); if (i % 8 == 0) @@ -881,25 +873,45 @@ namespace OpenSim.Region.CoreModules.World.Land private bool[,] ConvertBytesToLandBitmap() { - bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; + bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; tempConvertMap.Initialize(); byte tempByte = 0; - int x = 0, y = 0, i = 0, bitNum = 0; - for (i = 0; i < 512; i++) + // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap. + int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8); + int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit); + + if (bitmapLen == 512) + { + // Legacy bitmap being passed in. Use the legacy region size + // and only set the lower area of the larger region. + xLen = (int)(Constants.RegionSize / landUnit); + } + m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen); + + int x = 0, y = 0; + for (int i = 0; i < bitmapLen; i++) { tempByte = LandData.Bitmap[i]; - for (bitNum = 0; bitNum < 8; bitNum++) + for (int bitNum = 0; bitNum < 8; bitNum++) { bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); - tempConvertMap[x, y] = bit; + try + { + tempConvertMap[x, y] = bit; + } + catch (Exception e) + { + m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y); + } x++; - if (x > 63) + if (x >= xLen) { x = 0; y++; } } } + return tempConvertMap; } -- cgit v1.1