aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorRobert Adams2013-11-08 20:51:09 -0800
committerRobert Adams2013-11-08 20:51:09 -0800
commita7a837550e0ef036c5da43b1ec42a523e28b0cc0 (patch)
tree69bbe72ecadc9e46e51fb1f41f6fe0dc71e90149 /OpenSim/Region
parentMerge branch 'master' into varregion (diff)
downloadopensim-SC_OLD-a7a837550e0ef036c5da43b1ec42a523e28b0cc0.zip
opensim-SC_OLD-a7a837550e0ef036c5da43b1ec42a523e28b0cc0.tar.gz
opensim-SC_OLD-a7a837550e0ef036c5da43b1ec42a523e28b0cc0.tar.bz2
opensim-SC_OLD-a7a837550e0ef036c5da43b1ec42a523e28b0cc0.tar.xz
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.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs304
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs174
2 files changed, 295 insertions, 183 deletions
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
65 public class LandManagementModule : INonSharedRegionModule 65 public class LandManagementModule : INonSharedRegionModule
66 { 66 {
67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68 private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
68 69
69 private static readonly string remoteParcelRequestPath = "0009/"; 70 private static readonly string remoteParcelRequestPath = "0009/";
70 71
@@ -76,15 +77,11 @@ namespace OpenSim.Region.CoreModules.World.Land
76 protected IPrimCountModule m_primCountModule; 77 protected IPrimCountModule m_primCountModule;
77 protected IDialogModule m_Dialog; 78 protected IDialogModule m_Dialog;
78 79
79 // Minimum for parcels to work is 64m even if we don't actually use them.
80 #pragma warning disable 0429
81 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
82 #pragma warning restore 0429
83
84 /// <value> 80 /// <value>
85 /// Local land ids at specified region co-ordinates (region size / 4) 81 /// Local land ids at specified region co-ordinates (region size / 4)
86 /// </value> 82 /// </value>
87 private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax]; 83 private int[,] m_landIDList;
84 private const int landUnit = 4;
88 85
89 /// <value> 86 /// <value>
90 /// Land objects keyed by local id 87 /// Land objects keyed by local id
@@ -117,6 +114,8 @@ namespace OpenSim.Region.CoreModules.World.Land
117 public void AddRegion(Scene scene) 114 public void AddRegion(Scene scene)
118 { 115 {
119 m_scene = scene; 116 m_scene = scene;
117 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
118
120 m_landIDList.Initialize(); 119 m_landIDList.Initialize();
121 landChannel = new LandChannel(scene, this); 120 landChannel = new LandChannel(scene, this);
122 121
@@ -326,6 +325,7 @@ namespace OpenSim.Region.CoreModules.World.Land
326 { 325 {
327 m_landList.Clear(); 326 m_landList.Clear();
328 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 327 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
328 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
329 m_landIDList.Initialize(); 329 m_landIDList.Initialize();
330 } 330 }
331 } 331 }
@@ -340,7 +340,8 @@ namespace OpenSim.Region.CoreModules.World.Land
340 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); 340 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
341 341
342 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 342 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
343 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 343 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
344 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
344 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 345 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
345 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 346 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
346 347
@@ -467,8 +468,8 @@ namespace OpenSim.Region.CoreModules.World.Land
467 468
468 public void SendLandUpdate(ScenePresence avatar, bool force) 469 public void SendLandUpdate(ScenePresence avatar, bool force)
469 { 470 {
470 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 471 ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
471 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); 472 (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
472 473
473 if (over != null) 474 if (over != null)
474 { 475 {
@@ -634,17 +635,29 @@ namespace OpenSim.Region.CoreModules.World.Land
634 new_land.LandData.LocalID = newLandLocalID; 635 new_land.LandData.LocalID = newLandLocalID;
635 636
636 bool[,] landBitmap = new_land.GetLandBitmap(); 637 bool[,] landBitmap = new_land.GetLandBitmap();
637 for (int x = 0; x < landArrayMax; x++) 638 m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). bitmap[600/4,600/4]={3}, newLocalID={4}",
639 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), landBitmap[600/4, 600/4], newLandLocalID);
640
641 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
642 {
643 // Going to variable sized regions can cause mismatches
644 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
645 LogHeader, landBitmap.GetLength(0), m_landIDList.GetLength(1), landBitmap.GetLength(0), m_landIDList.GetLength(1) );
646 }
647 else
638 { 648 {
639 for (int y = 0; y < landArrayMax; y++) 649 for (int x = 0; x < landBitmap.GetLength(0); x++)
640 { 650 {
641 if (landBitmap[x, y]) 651 for (int y = 0; y < landBitmap.GetLength(1); y++)
642 { 652 {
643// m_log.DebugFormat( 653 if (landBitmap[x, y])
644// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", 654 {
645// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); 655 // m_log.DebugFormat(
646 656 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
647 m_landIDList[x, y] = newLandLocalID; 657 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
658
659 m_landIDList[x, y] = newLandLocalID;
660 }
648 } 661 }
649 } 662 }
650 } 663 }
@@ -666,9 +679,9 @@ namespace OpenSim.Region.CoreModules.World.Land
666 ILandObject land; 679 ILandObject land;
667 lock (m_landList) 680 lock (m_landList)
668 { 681 {
669 for (int x = 0; x < 64; x++) 682 for (int x = 0; x < m_landIDList.GetLength(0); x++)
670 { 683 {
671 for (int y = 0; y < 64; y++) 684 for (int y = 0; y < m_landIDList.GetLength(1); y++)
672 { 685 {
673 if (m_landIDList[x, y] == local_id) 686 if (m_landIDList[x, y] == local_id)
674 { 687 {
@@ -720,9 +733,9 @@ namespace OpenSim.Region.CoreModules.World.Land
720 bool[,] landBitmapSlave = slave.GetLandBitmap(); 733 bool[,] landBitmapSlave = slave.GetLandBitmap();
721 lock (m_landList) 734 lock (m_landList)
722 { 735 {
723 for (int x = 0; x < 64; x++) 736 for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
724 { 737 {
725 for (int y = 0; y < 64; y++) 738 for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
726 { 739 {
727 if (landBitmapSlave[x, y]) 740 if (landBitmapSlave[x, y])
728 { 741 {
@@ -756,23 +769,28 @@ namespace OpenSim.Region.CoreModules.World.Land
756 /// <returns>Land object at the point supplied</returns> 769 /// <returns>Land object at the point supplied</returns>
757 public ILandObject GetLandObject(float x_float, float y_float) 770 public ILandObject GetLandObject(float x_float, float y_float)
758 { 771 {
772 return GetLandObject((int)x_float, (int)y_float);
773 /*
759 int x; 774 int x;
760 int y; 775 int y;
761 776
762 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 777 if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
763 return null; 778 return null;
764 779
765 try 780 try
766 { 781 {
767 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); 782 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
768 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); 783 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
769 } 784 }
770 catch (OverflowException) 785 catch (OverflowException)
771 { 786 {
772 return null; 787 return null;
773 } 788 }
774 789
775 if (x >= 64 || y >= 64 || x < 0 || y < 0) 790 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
791 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
792 || x < 0
793 || y < 0)
776 { 794 {
777 return null; 795 return null;
778 } 796 }
@@ -788,38 +806,112 @@ namespace OpenSim.Region.CoreModules.World.Land
788// m_log.DebugFormat( 806// m_log.DebugFormat(
789// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", 807// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
790// x, y, m_scene.RegionInfo.RegionName); 808// x, y, m_scene.RegionInfo.RegionName);
791 809
792 if (m_landList.ContainsKey(m_landIDList[x, y])) 810 try
793 return m_landList[m_landIDList[x, y]]; 811 {
812 if (m_landList.ContainsKey(m_landIDList[x, y]))
813 return m_landList[m_landIDList[x, y]];
814 }
815 catch (Exception e)
816 {
817 m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})",
818 LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
819 }
794 820
795 return null; 821 return null;
796 } 822 }
823 */
797 } 824 }
798 825
826 // Given a region position, return the parcel land object for that location
799 public ILandObject GetLandObject(int x, int y) 827 public ILandObject GetLandObject(int x, int y)
800 { 828 {
801 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) 829 ILandObject ret = null;
830
831 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
802 { 832 {
803 // These exceptions here will cause a lot of complaints from the users specifically because 833 // These exceptions here will cause a lot of complaints from the users specifically because
804 // they happen every time at border crossings 834 // they happen every time at border crossings
805 throw new Exception("Error: Parcel not found at point " + x + ", " + y); 835 throw new Exception(
836 String.Format("{0} GetLandObject for non-existant position. Region={1}, pos=<{2},{3}",
837 LogHeader, m_scene.RegionInfo.RegionName, x, y)
838 );
806 } 839 }
807 840
808 lock (m_landIDList) 841 lock (m_landIDList)
809 { 842 {
810 try 843 try
811 { 844 {
812 return m_landList[m_landIDList[x / 4, y / 4]]; 845 int landID = m_landIDList[x / landUnit, y / landUnit];
846 if (landID == 0)
847 {
848 // Zero is the uninitialized value saying there is no parcel for this location.
849 // This sometimes happens when terrain is resized.
850 if (m_landList.Count == 1)
851 {
852 int onlyParcelID = 0;
853 ILandObject onlyLandObject = null;
854 foreach (KeyValuePair<int, ILandObject> kvp in m_landList)
855 {
856 onlyParcelID = kvp.Key;
857 onlyLandObject = kvp.Value;
858 break;
859 }
860
861 // There is only one parcel. Grow it to fill all the unallocated spaces.
862 for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
863 for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
864 if (m_landIDList[xx, yy] == 0)
865 m_landIDList[xx, yy] = onlyParcelID;
866
867 onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID);
868 landID = onlyParcelID;
869 }
870 else
871 {
872 // There are several other parcels so we must create a new one for the unassigned space
873 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
874 // Claim all the unclaimed "0" ids
875 newLand.SetLandBitmap(CreateBitmapForID(0));
876 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
877 newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
878 AddLandObject(newLand);
879 landID = m_lastLandLocalID;
880 }
881 }
882
883 ret = m_landList[landID];
813 } 884 }
814 catch (IndexOutOfRangeException) 885 catch (IndexOutOfRangeException)
815 { 886 {
816// m_log.WarnFormat( 887 m_log.ErrorFormat(
817// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}", 888 "{0} GetLandObject: Tried to retrieve land object from out of bounds co-ordinate ({1},{2}) in {3}. landListSize=({4},{5})",
818// x, y, m_scene.RegionInfo.RegionName); 889 LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
819 890 return null;
891 }
892 catch
893 {
894 m_log.ErrorFormat(
895 "{0} GetLandObject: LandID not in landlist. XY=<{1},{2}> in {3}. landID[x,y]={4}",
896 LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList[x/landUnit, y/landUnit]);
820 return null; 897 return null;
821 } 898 }
822 } 899 }
900 return ret;
901 }
902
903 // Create a 'parcel is here' bitmap for the parcel identified by the passed landID
904 private bool[,] CreateBitmapForID(int landID)
905 {
906 bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)];
907 ret.Initialize();
908
909 for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
910 for (int yy = 0; yy < m_landIDList.GetLength(0); yy++)
911 if (m_landIDList[xx, yy] == landID)
912 ret[xx, yy] = true;
913
914 return ret;
823 } 915 }
824 916
825 #endregion 917 #endregion
@@ -1082,85 +1174,93 @@ namespace OpenSim.Region.CoreModules.World.Land
1082 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1174 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1083 int byteArrayCount = 0; 1175 int byteArrayCount = 0;
1084 int sequenceID = 0; 1176 int sequenceID = 0;
1085 int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize;
1086 1177
1087 1178 // Layer data is in landUnit (4m) chunks
1088 for (int y = 0; y < blockmeters; y++) 1179 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); y++)
1089 { 1180 {
1090 for (int x = 0; x < blockmeters; x++) 1181 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); x++)
1091 { 1182 {
1092 byte tempByte = 0; //This represents the byte for the current 4x4 1183 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * landUnit, y * landUnit), x, y, remote_client);
1184 byteArrayCount++;
1185 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1186 {
1187 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1188 byteArrayCount = 0;
1189 sequenceID++;
1190 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1191 }
1093 1192
1094 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); 1193 }
1194 }
1195 if (byteArrayCount != 0)
1196 {
1197 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1198 }
1199 }
1095 1200
1096 if (currentParcelBlock != null) 1201 private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client)
1097 { 1202 {
1098 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1203 byte tempByte = 0; //This represents the byte for the current 4x4
1099 {
1100 //Owner Flag
1101 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1102 }
1103 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1104 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1105 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1106 {
1107 //Sale Flag
1108 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1109 }
1110 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1111 {
1112 //Public Flag
1113 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1114 }
1115 else
1116 {
1117 //Other Flag
1118 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1119 }
1120 1204
1121 //Now for border control 1205 if (currentParcelBlock != null)
1206 {
1207 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1208 {
1209 //Owner Flag
1210 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1211 }
1212 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1213 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1214 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1215 {
1216 //Sale Flag
1217 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1218 }
1219 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1220 {
1221 //Public Flag
1222 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1223 }
1224 else
1225 {
1226 //Other Flag
1227 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1228 }
1122 1229
1123 ILandObject westParcel = null; 1230 //Now for border control
1124 ILandObject southParcel = null;
1125 if (x > 0)
1126 {
1127 westParcel = GetLandObject((x - 1) * 4, y * 4);
1128 }
1129 if (y > 0)
1130 {
1131 southParcel = GetLandObject(x * 4, (y - 1) * 4);
1132 }
1133 1231
1134 if (x == 0) 1232 ILandObject westParcel = null;
1135 { 1233 ILandObject southParcel = null;
1136 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1234 if (x > 0)
1137 } 1235 {
1138 else if (westParcel != null && westParcel != currentParcelBlock) 1236 westParcel = GetLandObject((x - 1) * landUnit, y * landUnit);
1139 { 1237 }
1140 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1238 if (y > 0)
1141 } 1239 {
1240 southParcel = GetLandObject(x * landUnit, (y - 1) * landUnit);
1241 }
1142 1242
1143 if (y == 0) 1243 if (x == 0)
1144 { 1244 {
1145 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1245 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1146 } 1246 }
1147 else if (southParcel != null && southParcel != currentParcelBlock) 1247 else if (westParcel != null && westParcel != currentParcelBlock)
1148 { 1248 {
1149 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1249 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1150 } 1250 }
1151 1251
1152 byteArray[byteArrayCount] = tempByte; 1252 if (y == 0)
1153 byteArrayCount++; 1253 {
1154 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) 1254 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
1155 { 1255 }
1156 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1256 else if (southParcel != null && southParcel != currentParcelBlock)
1157 byteArrayCount = 0; 1257 {
1158 sequenceID++; 1258 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
1159 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1160 }
1161 }
1162 } 1259 }
1260
1163 } 1261 }
1262
1263 return tempByte;
1164 } 1264 }
1165 1265
1166 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, 1266 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
45 #region Member Variables 45 #region Member Variables
46 46
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 #pragma warning disable 0429 48 private static readonly string LogHeader = "[LAND OBJECT]";
49 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; 49
50 #pragma warning restore 0429 50 private bool[,] m_landBitmap;
51 private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; 51 private readonly int landUnit = 4;
52 52
53 private int m_lastSeqId = 0; 53 private int m_lastSeqId = 0;
54 54
@@ -93,12 +93,12 @@ namespace OpenSim.Region.CoreModules.World.Land
93 { 93 {
94 get 94 get
95 { 95 {
96 for (int y = 0; y < landArrayMax; y++) 96 for (int y = 0; y < LandBitmap.GetLength(1); y++)
97 { 97 {
98 for (int x = 0; x < landArrayMax; x++) 98 for (int x = 0; x < LandBitmap.GetLength(0); x++)
99 { 99 {
100 if (LandBitmap[x, y]) 100 if (LandBitmap[x, y])
101 return new Vector3(x * 4, y * 4, 0); 101 return new Vector3(x * landUnit, y * landUnit, 0);
102 } 102 }
103 } 103 }
104 104
@@ -110,13 +110,13 @@ namespace OpenSim.Region.CoreModules.World.Land
110 { 110 {
111 get 111 get
112 { 112 {
113 for (int y = landArrayMax - 1; y >= 0; y--) 113 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
114 { 114 {
115 for (int x = landArrayMax - 1; x >= 0; x--) 115 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
116 { 116 {
117 if (LandBitmap[x, y]) 117 if (LandBitmap[x, y])
118 { 118 {
119 return new Vector3(x * 4 + 4, y * 4 + 4, 0); 119 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
120 } 120 }
121 } 121 }
122 } 122 }
@@ -130,6 +130,8 @@ namespace OpenSim.Region.CoreModules.World.Land
130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
131 { 131 {
132 m_scene = scene; 132 m_scene = scene;
133 m_landBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
134
133 LandData.OwnerID = owner_id; 135 LandData.OwnerID = owner_id;
134 if (is_group_owned) 136 if (is_group_owned)
135 LandData.GroupID = owner_id; 137 LandData.GroupID = owner_id;
@@ -152,9 +154,9 @@ namespace OpenSim.Region.CoreModules.World.Land
152 /// <returns>Returns true if the piece of land contains the specified point</returns> 154 /// <returns>Returns true if the piece of land contains the specified point</returns>
153 public bool ContainsPoint(int x, int y) 155 public bool ContainsPoint(int x, int y)
154 { 156 {
155 if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize) 157 if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
156 { 158 {
157 return (LandBitmap[x / 4, y / 4] == true); 159 return (LandBitmap[x / landUnit, y / landUnit] == true);
158 } 160 }
159 else 161 else
160 { 162 {
@@ -194,7 +196,7 @@ namespace OpenSim.Region.CoreModules.World.Land
194 else 196 else
195 { 197 {
196 // Normal Calculations 198 // Normal Calculations
197 int parcelMax = (int)(((float)LandData.Area / 65536.0f) 199 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
198 * (float)m_scene.RegionInfo.ObjectCapacity 200 * (float)m_scene.RegionInfo.ObjectCapacity
199 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 201 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
200 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 202 // 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
211 else 213 else
212 { 214 {
213 //Normal Calculations 215 //Normal Calculations
214 int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) 216 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
215 * (float)m_scene.RegionInfo.ObjectCapacity); 217 * (float)m_scene.RegionInfo.ObjectCapacity);
216 return simMax; 218 return simMax;
217 } 219 }
@@ -224,7 +226,12 @@ namespace OpenSim.Region.CoreModules.World.Land
224 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 226 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
225 { 227 {
226 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 228 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
227 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 229 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
230 uint regionFlags = (uint)(RegionFlags.PublicAllowed
231 | RegionFlags.AllowDirectTeleport
232 | RegionFlags.AllowParcelChanges
233 | RegionFlags.AllowVoice );
234
228 if (estateModule != null) 235 if (estateModule != null)
229 regionFlags = estateModule.GetRegionFlags(); 236 regionFlags = estateModule.GetRegionFlags();
230 237
@@ -546,8 +553,8 @@ namespace OpenSim.Region.CoreModules.World.Land
546 try 553 try
547 { 554 {
548 over = 555 over =
549 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), 556 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
550 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); 557 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
551 } 558 }
552 catch (Exception) 559 catch (Exception)
553 { 560 {
@@ -694,15 +701,15 @@ namespace OpenSim.Region.CoreModules.World.Land
694 /// </summary> 701 /// </summary>
695 private void UpdateAABBAndAreaValues() 702 private void UpdateAABBAndAreaValues()
696 { 703 {
697 int min_x = 64; 704 int min_x = 10000;
698 int min_y = 64; 705 int min_y = 10000;
699 int max_x = 0; 706 int max_x = 0;
700 int max_y = 0; 707 int max_y = 0;
701 int tempArea = 0; 708 int tempArea = 0;
702 int x, y; 709 int x, y;
703 for (x = 0; x < 64; x++) 710 for (x = 0; x < LandBitmap.GetLength(0); x++)
704 { 711 {
705 for (y = 0; y < 64; y++) 712 for (y = 0; y < LandBitmap.GetLength(1); y++)
706 { 713 {
707 if (LandBitmap[x, y] == true) 714 if (LandBitmap[x, y] == true)
708 { 715 {
@@ -710,31 +717,31 @@ namespace OpenSim.Region.CoreModules.World.Land
710 if (min_y > y) min_y = y; 717 if (min_y > y) min_y = y;
711 if (max_x < x) max_x = x; 718 if (max_x < x) max_x = x;
712 if (max_y < y) max_y = y; 719 if (max_y < y) max_y = y;
713 tempArea += 16; //16sqm peice of land 720 tempArea += landUnit * landUnit; //16sqm peice of land
714 } 721 }
715 } 722 }
716 } 723 }
717 int tx = min_x * 4; 724 int tx = min_x * landUnit;
718 if (tx > ((int)Constants.RegionSize - 1)) 725 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
719 tx = ((int)Constants.RegionSize - 1); 726 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
720 int ty = min_y * 4; 727 int ty = min_y * landUnit;
721 if (ty > ((int)Constants.RegionSize - 1)) 728 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
722 ty = ((int)Constants.RegionSize - 1); 729 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
723 730
724 LandData.AABBMin = 731 LandData.AABBMin =
725 new Vector3( 732 new Vector3(
726 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 733 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
727 734
728 tx = max_x * 4; 735 tx = max_x * landUnit;
729 if (tx > ((int)Constants.RegionSize - 1)) 736 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
730 tx = ((int)Constants.RegionSize - 1); 737 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
731 ty = max_y * 4; 738 ty = max_y * landUnit;
732 if (ty > ((int)Constants.RegionSize - 1)) 739 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
733 ty = ((int)Constants.RegionSize - 1); 740 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
734 741
735 LandData.AABBMax 742 LandData.AABBMax
736 = new Vector3( 743 = new Vector3(
737 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 744 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
738 745
739 LandData.Area = tempArea; 746 LandData.Area = tempArea;
740 } 747 }
@@ -746,20 +753,11 @@ namespace OpenSim.Region.CoreModules.World.Land
746 /// <summary> 753 /// <summary>
747 /// Sets the land's bitmap manually 754 /// Sets the land's bitmap manually
748 /// </summary> 755 /// </summary>
749 /// <param name="bitmap">64x64 block representing where this land is on a map</param> 756 /// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
750 public void SetLandBitmap(bool[,] bitmap) 757 public void SetLandBitmap(bool[,] bitmap)
751 { 758 {
752 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) 759 LandBitmap = bitmap;
753 { 760 ForceUpdateLandInfo();
754 //Throw an exception - The bitmap is not 64x64
755 //throw new Exception("Error: Invalid Parcel Bitmap");
756 }
757 else
758 {
759 //Valid: Lets set it
760 LandBitmap = bitmap;
761 ForceUpdateLandInfo();
762 }
763 } 761 }
764 762
765 /// <summary> 763 /// <summary>
@@ -773,12 +771,12 @@ namespace OpenSim.Region.CoreModules.World.Land
773 771
774 public bool[,] BasicFullRegionLandBitmap() 772 public bool[,] BasicFullRegionLandBitmap()
775 { 773 {
776 return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); 774 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
777 } 775 }
778 776
779 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 777 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
780 { 778 {
781 bool[,] tempBitmap = new bool[64,64]; 779 bool[,] tempBitmap = new bool[(end_x-start_x)/landUnit,(end_y-start_y)/landUnit];
782 tempBitmap.Initialize(); 780 tempBitmap.Initialize();
783 781
784 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 782 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
@@ -798,19 +796,13 @@ namespace OpenSim.Region.CoreModules.World.Land
798 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, 796 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
799 bool set_value) 797 bool set_value)
800 { 798 {
801 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
802 {
803 //Throw an exception - The bitmap is not 64x64
804 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
805 }
806
807 int x, y; 799 int x, y;
808 for (y = 0; y < 64; y++) 800 for (y = 0; y < land_bitmap.GetLength(1); y++)
809 { 801 {
810 for (x = 0; x < 64; x++) 802 for (x = 0; x < land_bitmap.GetLength(0); x++)
811 { 803 {
812 if (x >= start_x / 4 && x < end_x / 4 804 if (x >= start_x / landUnit && x < end_x / landUnit
813 && y >= start_y / 4 && y < end_y / 4) 805 && y >= start_y / landUnit && y < end_y / landUnit)
814 { 806 {
815 land_bitmap[x, y] = set_value; 807 land_bitmap[x, y] = set_value;
816 } 808 }
@@ -827,21 +819,21 @@ namespace OpenSim.Region.CoreModules.World.Land
827 /// <returns></returns> 819 /// <returns></returns>
828 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) 820 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
829 { 821 {
830 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) 822 if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
823 || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
824 || bitmap_add.Rank != 2
825 || bitmap_base.Rank != 2)
831 { 826 {
832 //Throw an exception - The bitmap is not 64x64 827 throw new Exception(
833 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); 828 String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
834 } 829 LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
835 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) 830 );
836 {
837 //Throw an exception - The bitmap is not 64x64
838 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
839 } 831 }
840 832
841 int x, y; 833 int x, y;
842 for (y = 0; y < 64; y++) 834 for (y = 0; y < bitmap_base.GetLength(1); y++)
843 { 835 {
844 for (x = 0; x < 64; x++) 836 for (x = 0; x < bitmap_add.GetLength(0); x++)
845 { 837 {
846 if (bitmap_add[x, y]) 838 if (bitmap_add[x, y])
847 { 839 {
@@ -858,13 +850,13 @@ namespace OpenSim.Region.CoreModules.World.Land
858 /// <returns></returns> 850 /// <returns></returns>
859 private byte[] ConvertLandBitmapToBytes() 851 private byte[] ConvertLandBitmapToBytes()
860 { 852 {
861 byte[] tempConvertArr = new byte[512]; 853 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
862 byte tempByte = 0; 854 byte tempByte = 0;
863 int x, y, i, byteNum = 0; 855 int byteNum = 0;
864 i = 0; 856 int i = 0;
865 for (y = 0; y < 64; y++) 857 for (int y = 0; y < LandBitmap.GetLength(1); y++)
866 { 858 {
867 for (x = 0; x < 64; x++) 859 for (int x = 0; x < LandBitmap.GetLength(0); x++)
868 { 860 {
869 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 861 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
870 if (i % 8 == 0) 862 if (i % 8 == 0)
@@ -881,25 +873,45 @@ namespace OpenSim.Region.CoreModules.World.Land
881 873
882 private bool[,] ConvertBytesToLandBitmap() 874 private bool[,] ConvertBytesToLandBitmap()
883 { 875 {
884 bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; 876 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
885 tempConvertMap.Initialize(); 877 tempConvertMap.Initialize();
886 byte tempByte = 0; 878 byte tempByte = 0;
887 int x = 0, y = 0, i = 0, bitNum = 0; 879 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
888 for (i = 0; i < 512; i++) 880 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
881 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
882
883 if (bitmapLen == 512)
884 {
885 // Legacy bitmap being passed in. Use the legacy region size
886 // and only set the lower area of the larger region.
887 xLen = (int)(Constants.RegionSize / landUnit);
888 }
889 m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
890
891 int x = 0, y = 0;
892 for (int i = 0; i < bitmapLen; i++)
889 { 893 {
890 tempByte = LandData.Bitmap[i]; 894 tempByte = LandData.Bitmap[i];
891 for (bitNum = 0; bitNum < 8; bitNum++) 895 for (int bitNum = 0; bitNum < 8; bitNum++)
892 { 896 {
893 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); 897 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
894 tempConvertMap[x, y] = bit; 898 try
899 {
900 tempConvertMap[x, y] = bit;
901 }
902 catch (Exception e)
903 {
904 m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
905 }
895 x++; 906 x++;
896 if (x > 63) 907 if (x >= xLen)
897 { 908 {
898 x = 0; 909 x = 0;
899 y++; 910 y++;
900 } 911 }
901 } 912 }
902 } 913 }
914
903 return tempConvertMap; 915 return tempConvertMap;
904 } 916 }
905 917