diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 92790664ce..4aee6a52c8 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -64,6 +64,12 @@ 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]"; + + /// + /// Minimum land unit size in region co-ordinates. + /// + public const int landUnit = 4; private static readonly string remoteParcelRequestPath = "0009/"; @@ -74,15 +80,10 @@ 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; /// /// Land objects keyed by local id @@ -123,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void AddRegion(Scene scene) { m_scene = scene; - m_landIDList.Initialize(); + m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; landChannel = new LandChannel(scene, this); parcelInfoCache = new Cache(); @@ -235,7 +236,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void UpdateLandObject(int local_id, LandData data) { LandData newData = data.Copy(); - newData.LocalID = local_id; + newData.LocalID = local_id; ILandObject land; lock (m_landList) @@ -264,7 +265,7 @@ namespace OpenSim.Region.CoreModules.World.Land { m_landList.Clear(); m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; - m_landIDList.Initialize(); + m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; } } @@ -274,11 +275,11 @@ namespace OpenSim.Region.CoreModules.World.Land /// The parcel created. protected ILandObject CreateDefaultParcel() { - m_log.DebugFormat( - "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); + m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, 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(); @@ -569,9 +570,9 @@ namespace OpenSim.Region.CoreModules.World.Land new_land.LandData.LocalID = newLandLocalID; bool[,] landBitmap = new_land.GetLandBitmap(); - for (int x = 0; x < landArrayMax; x++) + for (int x = 0; x < landBitmap.GetLength(0); x++) { - for (int y = 0; y < landArrayMax; y++) + for (int y = 0; y < landBitmap.GetLength(1); y++) { if (landBitmap[x, y]) { @@ -601,9 +602,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) { @@ -656,9 +657,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]) { @@ -695,20 +696,23 @@ namespace OpenSim.Region.CoreModules.World.Land 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; } @@ -740,20 +744,20 @@ namespace OpenSim.Region.CoreModules.World.Land int avx = (int)x; if (avx < 0) avx = 0; - else if (avx >= (int)Constants.RegionSize) + else if (avx >= m_scene.RegionInfo.RegionSizeX) avx = (int)Constants.RegionSize - 1; int avy = (int)y; if (avy < 0) avy = 0; - else if (avy >= (int)Constants.RegionSize) + else if (avy >= m_scene.RegionInfo.RegionSizeY) avy = (int)Constants.RegionSize - 1; lock (m_landIDList) { try { - return m_landList[m_landIDList[avx / 4, avy / 4]]; + return m_landList[m_landIDList[avx / landUnit, avy / landUnit]]; } catch (IndexOutOfRangeException) { @@ -764,7 +768,7 @@ namespace OpenSim.Region.CoreModules.World.Land public ILandObject GetLandObject(int x, int y) { - if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) + 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 @@ -1057,9 +1061,10 @@ namespace OpenSim.Region.CoreModules.World.Land int byteArrayCount = 0; int sequenceID = 0; - for (int y = 0; y < Constants.RegionSize; y += 4) + // Layer data is in landUnit (4m) chunks + for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += landUnit) { - for (int x = 0; x < Constants.RegionSize; x += 4) + for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += landUnit) { byte tempByte = 0; //This represents the byte for the current 4x4 @@ -1769,7 +1774,7 @@ namespace OpenSim.Region.CoreModules.World.Land { // most likely still cached from building the extLandData entry uint x = 0, y = 0; - Utils.LongToUInts(data.RegionHandle, out x, out y); + Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y); info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); } // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a3cd4a5673..5858d6c9ad 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -45,15 +45,13 @@ 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 readonly int landUnit = 4; private int m_lastSeqId = 0; private int m_expiryCounter = 0; - protected LandData m_landData = new LandData(); protected Scene m_scene; protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); @@ -61,6 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Land protected ExpiringCache m_groupMemberCache = new ExpiringCache(); protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds + private bool[,] m_landBitmap; public bool[,] LandBitmap { get { return m_landBitmap; } @@ -76,6 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Land return free; } + protected LandData m_landData; public LandData LandData { get { return m_landData; } @@ -94,12 +94,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); } } @@ -111,13 +111,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); } } } @@ -128,9 +128,21 @@ namespace OpenSim.Region.CoreModules.World.Land #region Constructors + public LandObject(LandData landData, Scene scene) + { + LandData = landData.Copy(); + m_scene = scene; + } + public LandObject(UUID owner_id, bool is_group_owned, Scene scene) { m_scene = scene; + if (m_scene == null) + LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit]; + else + LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; + + LandData = new LandData(); LandData.OwnerID = owner_id; if (is_group_owned) LandData.GroupID = owner_id; @@ -155,9 +167,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]; } else { @@ -197,10 +209,10 @@ namespace OpenSim.Region.CoreModules.World.Land else { // Normal Calculations - int parcelMax = (int)((long)LandData.Area + int parcelMax = (int)( (long)LandData.Area * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus - / 65536L); + / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) ); //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax); return parcelMax; } @@ -231,8 +243,9 @@ namespace OpenSim.Region.CoreModules.World.Land else { //Normal Calculations - int simMax = (int)((long)LandData.SimwideArea - * (long)m_scene.RegionInfo.ObjectCapacity / 65536L); + int simMax = (int)( (long)LandData.SimwideArea + * (long)m_scene.RegionInfo.ObjectCapacity + / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) ); // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax); return simMax; } @@ -597,8 +610,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) { @@ -752,9 +765,9 @@ namespace OpenSim.Region.CoreModules.World.Land int max_y = Int32.MinValue; 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) { @@ -766,23 +779,25 @@ namespace OpenSim.Region.CoreModules.World.Land 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 * landUnit; + if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) + tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); - int tx = min_x * 4; int htx; - if (tx == ((int)Constants.RegionSize)) - htx = tx - 1; + if (tx >= ((int)m_scene.RegionInfo.RegionSizeX)) + htx = (int)m_scene.RegionInfo.RegionSizeX - 1; else htx = tx; - int ty = min_y * 4; + int ty = min_y * landUnit; int hty; - if (ty == ((int)Constants.RegionSize)) - hty = ty - 1; + if (ty >= ((int)m_scene.RegionInfo.RegionSizeY)) + hty = (int)m_scene.RegionInfo.RegionSizeY - 1; else hty = ty; @@ -791,17 +806,17 @@ namespace OpenSim.Region.CoreModules.World.Land (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0); max_x++; - tx = max_x * 4; - if (tx == ((int)Constants.RegionSize)) - htx = tx - 1; + tx = max_x * landUnit; + if (tx >= ((int)m_scene.RegionInfo.RegionSizeX)) + htx = (int)m_scene.RegionInfo.RegionSizeX - 1; else htx = tx; max_y++; ty = max_y * 4; - if (ty == ((int)Constants.RegionSize)) - hty = ty - 1; + if (ty >= ((int)m_scene.RegionInfo.RegionSizeY)) + hty = (int)m_scene.RegionInfo.RegionSizeY - 1; else hty = ty; @@ -819,20 +834,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(); } /// @@ -846,14 +852,16 @@ 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]; + // Empty bitmap for the whole region + bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; tempBitmap.Initialize(); + // Fill the bitmap square area specified by state and end tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); return tempBitmap; } @@ -871,19 +879,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; } @@ -900,21 +902,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]) { @@ -931,14 +933,14 @@ 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]; int tempByte = 0; - int x, y, i, byteNum = 0; + int i, byteNum = 0; int mask = 1; i = 0; - for (y = 0; y < 64; y++) + for (int y = 0; y < LandBitmap.GetLength(1); y++) { - for (x = 0; x < 64; x++) + for (int x = 0; x < LandBitmap.GetLength(0); x++) { if (LandBitmap[x, y]) tempByte |= mask; @@ -971,25 +973,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) + { + 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; }