aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World')
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs63
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs176
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs36
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs36
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs35
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs488
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs32
14 files changed, 614 insertions, 285 deletions
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index 7a844f4..cd95ee9 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -533,7 +533,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
533 if (isMegaregion) 533 if (isMegaregion)
534 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); 534 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
535 else 535 else
536 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); 536 size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
537 537
538 xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); 538 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
539 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 539 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 9279066..4aee6a5 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
64 public class LandManagementModule : INonSharedRegionModule 64 public class LandManagementModule : INonSharedRegionModule
65 { 65 {
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
68
69 /// <summary>
70 /// Minimum land unit size in region co-ordinates.
71 /// </summary>
72 public const int landUnit = 4;
67 73
68 private static readonly string remoteParcelRequestPath = "0009/"; 74 private static readonly string remoteParcelRequestPath = "0009/";
69 75
@@ -74,15 +80,10 @@ namespace OpenSim.Region.CoreModules.World.Land
74 protected IPrimCountModule m_primCountModule; 80 protected IPrimCountModule m_primCountModule;
75 protected IDialogModule m_Dialog; 81 protected IDialogModule m_Dialog;
76 82
77 // Minimum for parcels to work is 64m even if we don't actually use them.
78 #pragma warning disable 0429
79 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
80 #pragma warning restore 0429
81
82 /// <value> 83 /// <value>
83 /// Local land ids at specified region co-ordinates (region size / 4) 84 /// Local land ids at specified region co-ordinates (region size / 4)
84 /// </value> 85 /// </value>
85 private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax]; 86 private int[,] m_landIDList;
86 87
87 /// <value> 88 /// <value>
88 /// Land objects keyed by local id 89 /// Land objects keyed by local id
@@ -123,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Land
123 public void AddRegion(Scene scene) 124 public void AddRegion(Scene scene)
124 { 125 {
125 m_scene = scene; 126 m_scene = scene;
126 m_landIDList.Initialize(); 127 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
127 landChannel = new LandChannel(scene, this); 128 landChannel = new LandChannel(scene, this);
128 129
129 parcelInfoCache = new Cache(); 130 parcelInfoCache = new Cache();
@@ -235,7 +236,7 @@ namespace OpenSim.Region.CoreModules.World.Land
235 public void UpdateLandObject(int local_id, LandData data) 236 public void UpdateLandObject(int local_id, LandData data)
236 { 237 {
237 LandData newData = data.Copy(); 238 LandData newData = data.Copy();
238 newData.LocalID = local_id; 239 newData.LocalID = local_id;
239 240
240 ILandObject land; 241 ILandObject land;
241 lock (m_landList) 242 lock (m_landList)
@@ -264,7 +265,7 @@ namespace OpenSim.Region.CoreModules.World.Land
264 { 265 {
265 m_landList.Clear(); 266 m_landList.Clear();
266 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 267 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
267 m_landIDList.Initialize(); 268 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
268 } 269 }
269 } 270 }
270 271
@@ -274,11 +275,11 @@ namespace OpenSim.Region.CoreModules.World.Land
274 /// <returns>The parcel created.</returns> 275 /// <returns>The parcel created.</returns>
275 protected ILandObject CreateDefaultParcel() 276 protected ILandObject CreateDefaultParcel()
276 { 277 {
277 m_log.DebugFormat( 278 m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName);
278 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
279 279
280 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 280 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
281 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 281 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
282 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
282 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 283 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
283 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 284 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
284 285
@@ -569,9 +570,9 @@ namespace OpenSim.Region.CoreModules.World.Land
569 new_land.LandData.LocalID = newLandLocalID; 570 new_land.LandData.LocalID = newLandLocalID;
570 571
571 bool[,] landBitmap = new_land.GetLandBitmap(); 572 bool[,] landBitmap = new_land.GetLandBitmap();
572 for (int x = 0; x < landArrayMax; x++) 573 for (int x = 0; x < landBitmap.GetLength(0); x++)
573 { 574 {
574 for (int y = 0; y < landArrayMax; y++) 575 for (int y = 0; y < landBitmap.GetLength(1); y++)
575 { 576 {
576 if (landBitmap[x, y]) 577 if (landBitmap[x, y])
577 { 578 {
@@ -601,9 +602,9 @@ namespace OpenSim.Region.CoreModules.World.Land
601 ILandObject land; 602 ILandObject land;
602 lock (m_landList) 603 lock (m_landList)
603 { 604 {
604 for (int x = 0; x < 64; x++) 605 for (int x = 0; x < m_landIDList.GetLength(0); x++)
605 { 606 {
606 for (int y = 0; y < 64; y++) 607 for (int y = 0; y < m_landIDList.GetLength(1); y++)
607 { 608 {
608 if (m_landIDList[x, y] == local_id) 609 if (m_landIDList[x, y] == local_id)
609 { 610 {
@@ -656,9 +657,9 @@ namespace OpenSim.Region.CoreModules.World.Land
656 bool[,] landBitmapSlave = slave.GetLandBitmap(); 657 bool[,] landBitmapSlave = slave.GetLandBitmap();
657 lock (m_landList) 658 lock (m_landList)
658 { 659 {
659 for (int x = 0; x < 64; x++) 660 for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
660 { 661 {
661 for (int y = 0; y < 64; y++) 662 for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
662 { 663 {
663 if (landBitmapSlave[x, y]) 664 if (landBitmapSlave[x, y])
664 { 665 {
@@ -695,20 +696,23 @@ namespace OpenSim.Region.CoreModules.World.Land
695 int x; 696 int x;
696 int y; 697 int y;
697 698
698 if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0) 699 if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
699 return null; 700 return null;
700 701
701 try 702 try
702 { 703 {
703 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); 704 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
704 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); 705 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
705 } 706 }
706 catch (OverflowException) 707 catch (OverflowException)
707 { 708 {
708 return null; 709 return null;
709 } 710 }
710 711
711 if (x >= 64 || y >= 64 || x < 0 || y < 0) 712 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
713 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
714 || x < 0
715 || y < 0)
712 { 716 {
713 return null; 717 return null;
714 } 718 }
@@ -740,20 +744,20 @@ namespace OpenSim.Region.CoreModules.World.Land
740 int avx = (int)x; 744 int avx = (int)x;
741 if (avx < 0) 745 if (avx < 0)
742 avx = 0; 746 avx = 0;
743 else if (avx >= (int)Constants.RegionSize) 747 else if (avx >= m_scene.RegionInfo.RegionSizeX)
744 avx = (int)Constants.RegionSize - 1; 748 avx = (int)Constants.RegionSize - 1;
745 749
746 int avy = (int)y; 750 int avy = (int)y;
747 if (avy < 0) 751 if (avy < 0)
748 avy = 0; 752 avy = 0;
749 else if (avy >= (int)Constants.RegionSize) 753 else if (avy >= m_scene.RegionInfo.RegionSizeY)
750 avy = (int)Constants.RegionSize - 1; 754 avy = (int)Constants.RegionSize - 1;
751 755
752 lock (m_landIDList) 756 lock (m_landIDList)
753 { 757 {
754 try 758 try
755 { 759 {
756 return m_landList[m_landIDList[avx / 4, avy / 4]]; 760 return m_landList[m_landIDList[avx / landUnit, avy / landUnit]];
757 } 761 }
758 catch (IndexOutOfRangeException) 762 catch (IndexOutOfRangeException)
759 { 763 {
@@ -764,7 +768,7 @@ namespace OpenSim.Region.CoreModules.World.Land
764 768
765 public ILandObject GetLandObject(int x, int y) 769 public ILandObject GetLandObject(int x, int y)
766 { 770 {
767 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) 771 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
768 { 772 {
769 // These exceptions here will cause a lot of complaints from the users specifically because 773 // These exceptions here will cause a lot of complaints from the users specifically because
770 // they happen every time at border crossings 774 // they happen every time at border crossings
@@ -1057,9 +1061,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1057 int byteArrayCount = 0; 1061 int byteArrayCount = 0;
1058 int sequenceID = 0; 1062 int sequenceID = 0;
1059 1063
1060 for (int y = 0; y < Constants.RegionSize; y += 4) 1064 // Layer data is in landUnit (4m) chunks
1065 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += landUnit)
1061 { 1066 {
1062 for (int x = 0; x < Constants.RegionSize; x += 4) 1067 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += landUnit)
1063 { 1068 {
1064 byte tempByte = 0; //This represents the byte for the current 4x4 1069 byte tempByte = 0; //This represents the byte for the current 4x4
1065 1070
@@ -1769,7 +1774,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1769 { 1774 {
1770 // most likely still cached from building the extLandData entry 1775 // most likely still cached from building the extLandData entry
1771 uint x = 0, y = 0; 1776 uint x = 0, y = 0;
1772 Utils.LongToUInts(data.RegionHandle, out x, out y); 1777 Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y);
1773 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 1778 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
1774 } 1779 }
1775 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. 1780 // 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 a3cd4a5..5858d6c 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
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 readonly int landUnit = 4;
51 private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
52 51
53 private int m_lastSeqId = 0; 52 private int m_lastSeqId = 0;
54 private int m_expiryCounter = 0; 53 private int m_expiryCounter = 0;
55 54
56 protected LandData m_landData = new LandData();
57 protected Scene m_scene; 55 protected Scene m_scene;
58 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
59 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
@@ -61,6 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Land
61 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>(); 59 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
62 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds 60 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
63 61
62 private bool[,] m_landBitmap;
64 public bool[,] LandBitmap 63 public bool[,] LandBitmap
65 { 64 {
66 get { return m_landBitmap; } 65 get { return m_landBitmap; }
@@ -76,6 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Land
76 return free; 75 return free;
77 } 76 }
78 77
78 protected LandData m_landData;
79 public LandData LandData 79 public LandData LandData
80 { 80 {
81 get { return m_landData; } 81 get { return m_landData; }
@@ -94,12 +94,12 @@ namespace OpenSim.Region.CoreModules.World.Land
94 { 94 {
95 get 95 get
96 { 96 {
97 for (int y = 0; y < landArrayMax; y++) 97 for (int y = 0; y < LandBitmap.GetLength(1); y++)
98 { 98 {
99 for (int x = 0; x < landArrayMax; x++) 99 for (int x = 0; x < LandBitmap.GetLength(0); x++)
100 { 100 {
101 if (LandBitmap[x, y]) 101 if (LandBitmap[x, y])
102 return new Vector3(x * 4, y * 4, 0); 102 return new Vector3(x * landUnit, y * landUnit, 0);
103 } 103 }
104 } 104 }
105 105
@@ -111,13 +111,13 @@ namespace OpenSim.Region.CoreModules.World.Land
111 { 111 {
112 get 112 get
113 { 113 {
114 for (int y = landArrayMax - 1; y >= 0; y--) 114 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
115 { 115 {
116 for (int x = landArrayMax - 1; x >= 0; x--) 116 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
117 { 117 {
118 if (LandBitmap[x, y]) 118 if (LandBitmap[x, y])
119 { 119 {
120 return new Vector3(x * 4 + 4, y * 4 + 4, 0); 120 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
121 } 121 }
122 } 122 }
123 } 123 }
@@ -128,9 +128,21 @@ namespace OpenSim.Region.CoreModules.World.Land
128 128
129 #region Constructors 129 #region Constructors
130 130
131 public LandObject(LandData landData, Scene scene)
132 {
133 LandData = landData.Copy();
134 m_scene = scene;
135 }
136
131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 137 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
132 { 138 {
133 m_scene = scene; 139 m_scene = scene;
140 if (m_scene == null)
141 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
142 else
143 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
144
145 LandData = new LandData();
134 LandData.OwnerID = owner_id; 146 LandData.OwnerID = owner_id;
135 if (is_group_owned) 147 if (is_group_owned)
136 LandData.GroupID = owner_id; 148 LandData.GroupID = owner_id;
@@ -155,9 +167,9 @@ namespace OpenSim.Region.CoreModules.World.Land
155 /// <returns>Returns true if the piece of land contains the specified point</returns> 167 /// <returns>Returns true if the piece of land contains the specified point</returns>
156 public bool ContainsPoint(int x, int y) 168 public bool ContainsPoint(int x, int y)
157 { 169 {
158 if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize) 170 if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
159 { 171 {
160 return (LandBitmap[x / 4, y / 4] == true); 172 return LandBitmap[x / landUnit, y / landUnit];
161 } 173 }
162 else 174 else
163 { 175 {
@@ -197,10 +209,10 @@ namespace OpenSim.Region.CoreModules.World.Land
197 else 209 else
198 { 210 {
199 // Normal Calculations 211 // Normal Calculations
200 int parcelMax = (int)((long)LandData.Area 212 int parcelMax = (int)( (long)LandData.Area
201 * (long)m_scene.RegionInfo.ObjectCapacity 213 * (long)m_scene.RegionInfo.ObjectCapacity
202 * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus 214 * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
203 / 65536L); 215 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
204 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax); 216 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
205 return parcelMax; 217 return parcelMax;
206 } 218 }
@@ -231,8 +243,9 @@ namespace OpenSim.Region.CoreModules.World.Land
231 else 243 else
232 { 244 {
233 //Normal Calculations 245 //Normal Calculations
234 int simMax = (int)((long)LandData.SimwideArea 246 int simMax = (int)( (long)LandData.SimwideArea
235 * (long)m_scene.RegionInfo.ObjectCapacity / 65536L); 247 * (long)m_scene.RegionInfo.ObjectCapacity
248 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
236 // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax); 249 // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
237 return simMax; 250 return simMax;
238 } 251 }
@@ -597,8 +610,8 @@ namespace OpenSim.Region.CoreModules.World.Land
597 try 610 try
598 { 611 {
599 over = 612 over =
600 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), 613 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
601 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); 614 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
602 } 615 }
603 catch (Exception) 616 catch (Exception)
604 { 617 {
@@ -752,9 +765,9 @@ namespace OpenSim.Region.CoreModules.World.Land
752 int max_y = Int32.MinValue; 765 int max_y = Int32.MinValue;
753 int tempArea = 0; 766 int tempArea = 0;
754 int x, y; 767 int x, y;
755 for (x = 0; x < 64; x++) 768 for (x = 0; x < LandBitmap.GetLength(0); x++)
756 { 769 {
757 for (y = 0; y < 64; y++) 770 for (y = 0; y < LandBitmap.GetLength(1); y++)
758 { 771 {
759 if (LandBitmap[x, y] == true) 772 if (LandBitmap[x, y] == true)
760 { 773 {
@@ -766,23 +779,25 @@ namespace OpenSim.Region.CoreModules.World.Land
766 max_x = x; 779 max_x = x;
767 if (max_y < y) 780 if (max_y < y)
768 max_y = y; 781 max_y = y;
769 tempArea += 16; //16sqm peice of land 782 tempArea += landUnit * landUnit; //16sqm peice of land
770 } 783 }
771 } 784 }
772 } 785 }
786 int tx = min_x * landUnit;
787 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
788 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
773 789
774 int tx = min_x * 4;
775 int htx; 790 int htx;
776 if (tx == ((int)Constants.RegionSize)) 791 if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
777 htx = tx - 1; 792 htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
778 else 793 else
779 htx = tx; 794 htx = tx;
780 795
781 int ty = min_y * 4; 796 int ty = min_y * landUnit;
782 int hty; 797 int hty;
783 798
784 if (ty == ((int)Constants.RegionSize)) 799 if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
785 hty = ty - 1; 800 hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
786 else 801 else
787 hty = ty; 802 hty = ty;
788 803
@@ -791,17 +806,17 @@ namespace OpenSim.Region.CoreModules.World.Land
791 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0); 806 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
792 807
793 max_x++; 808 max_x++;
794 tx = max_x * 4; 809 tx = max_x * landUnit;
795 if (tx == ((int)Constants.RegionSize)) 810 if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
796 htx = tx - 1; 811 htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
797 else 812 else
798 htx = tx; 813 htx = tx;
799 814
800 max_y++; 815 max_y++;
801 ty = max_y * 4; 816 ty = max_y * 4;
802 817
803 if (ty == ((int)Constants.RegionSize)) 818 if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
804 hty = ty - 1; 819 hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
805 else 820 else
806 hty = ty; 821 hty = ty;
807 822
@@ -819,20 +834,11 @@ namespace OpenSim.Region.CoreModules.World.Land
819 /// <summary> 834 /// <summary>
820 /// Sets the land's bitmap manually 835 /// Sets the land's bitmap manually
821 /// </summary> 836 /// </summary>
822 /// <param name="bitmap">64x64 block representing where this land is on a map</param> 837 /// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
823 public void SetLandBitmap(bool[,] bitmap) 838 public void SetLandBitmap(bool[,] bitmap)
824 { 839 {
825 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) 840 LandBitmap = bitmap;
826 { 841 ForceUpdateLandInfo();
827 //Throw an exception - The bitmap is not 64x64
828 //throw new Exception("Error: Invalid Parcel Bitmap");
829 }
830 else
831 {
832 //Valid: Lets set it
833 LandBitmap = bitmap;
834 ForceUpdateLandInfo();
835 }
836 } 842 }
837 843
838 /// <summary> 844 /// <summary>
@@ -846,14 +852,16 @@ namespace OpenSim.Region.CoreModules.World.Land
846 852
847 public bool[,] BasicFullRegionLandBitmap() 853 public bool[,] BasicFullRegionLandBitmap()
848 { 854 {
849 return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); 855 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
850 } 856 }
851 857
852 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 858 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
853 { 859 {
854 bool[,] tempBitmap = new bool[64,64]; 860 // Empty bitmap for the whole region
861 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
855 tempBitmap.Initialize(); 862 tempBitmap.Initialize();
856 863
864 // Fill the bitmap square area specified by state and end
857 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 865 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
858 return tempBitmap; 866 return tempBitmap;
859 } 867 }
@@ -871,19 +879,13 @@ namespace OpenSim.Region.CoreModules.World.Land
871 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, 879 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
872 bool set_value) 880 bool set_value)
873 { 881 {
874 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
875 {
876 //Throw an exception - The bitmap is not 64x64
877 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
878 }
879
880 int x, y; 882 int x, y;
881 for (y = 0; y < 64; y++) 883 for (y = 0; y < land_bitmap.GetLength(1); y++)
882 { 884 {
883 for (x = 0; x < 64; x++) 885 for (x = 0; x < land_bitmap.GetLength(0); x++)
884 { 886 {
885 if (x >= start_x / 4 && x < end_x / 4 887 if (x >= start_x / landUnit && x < end_x / landUnit
886 && y >= start_y / 4 && y < end_y / 4) 888 && y >= start_y / landUnit && y < end_y / landUnit)
887 { 889 {
888 land_bitmap[x, y] = set_value; 890 land_bitmap[x, y] = set_value;
889 } 891 }
@@ -900,21 +902,21 @@ namespace OpenSim.Region.CoreModules.World.Land
900 /// <returns></returns> 902 /// <returns></returns>
901 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) 903 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
902 { 904 {
903 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) 905 if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
904 { 906 || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
905 //Throw an exception - The bitmap is not 64x64 907 || bitmap_add.Rank != 2
906 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); 908 || bitmap_base.Rank != 2)
907 }
908 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
909 { 909 {
910 //Throw an exception - The bitmap is not 64x64 910 throw new Exception(
911 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); 911 String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
912 LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
913 );
912 } 914 }
913 915
914 int x, y; 916 int x, y;
915 for (y = 0; y < 64; y++) 917 for (y = 0; y < bitmap_base.GetLength(1); y++)
916 { 918 {
917 for (x = 0; x < 64; x++) 919 for (x = 0; x < bitmap_add.GetLength(0); x++)
918 { 920 {
919 if (bitmap_add[x, y]) 921 if (bitmap_add[x, y])
920 { 922 {
@@ -931,14 +933,14 @@ namespace OpenSim.Region.CoreModules.World.Land
931 /// <returns></returns> 933 /// <returns></returns>
932 private byte[] ConvertLandBitmapToBytes() 934 private byte[] ConvertLandBitmapToBytes()
933 { 935 {
934 byte[] tempConvertArr = new byte[512]; 936 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
935 int tempByte = 0; 937 int tempByte = 0;
936 int x, y, i, byteNum = 0; 938 int i, byteNum = 0;
937 int mask = 1; 939 int mask = 1;
938 i = 0; 940 i = 0;
939 for (y = 0; y < 64; y++) 941 for (int y = 0; y < LandBitmap.GetLength(1); y++)
940 { 942 {
941 for (x = 0; x < 64; x++) 943 for (int x = 0; x < LandBitmap.GetLength(0); x++)
942 { 944 {
943 if (LandBitmap[x, y]) 945 if (LandBitmap[x, y])
944 tempByte |= mask; 946 tempByte |= mask;
@@ -971,25 +973,45 @@ namespace OpenSim.Region.CoreModules.World.Land
971 973
972 private bool[,] ConvertBytesToLandBitmap() 974 private bool[,] ConvertBytesToLandBitmap()
973 { 975 {
974 bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; 976 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
975 tempConvertMap.Initialize(); 977 tempConvertMap.Initialize();
976 byte tempByte = 0; 978 byte tempByte = 0;
977 int x = 0, y = 0, i = 0, bitNum = 0; 979 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
978 for (i = 0; i < 512; i++) 980 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
981 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
982
983 if (bitmapLen == 512)
984 {
985 // Legacy bitmap being passed in. Use the legacy region size
986 // and only set the lower area of the larger region.
987 xLen = (int)(Constants.RegionSize / landUnit);
988 }
989 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
990
991 int x = 0, y = 0;
992 for (int i = 0; i < bitmapLen; i++)
979 { 993 {
980 tempByte = LandData.Bitmap[i]; 994 tempByte = LandData.Bitmap[i];
981 for (bitNum = 0; bitNum < 8; bitNum++) 995 for (int bitNum = 0; bitNum < 8; bitNum++)
982 { 996 {
983 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); 997 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
984 tempConvertMap[x, y] = bit; 998 try
999 {
1000 tempConvertMap[x, y] = bit;
1001 }
1002 catch (Exception)
1003 {
1004 m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
1005 }
985 x++; 1006 x++;
986 if (x > 63) 1007 if (x >= xLen)
987 { 1008 {
988 x = 0; 1009 x = 0;
989 y++; 1010 y++;
990 } 1011 }
991 } 1012 }
992 } 1013 }
1014
993 return tempConvertMap; 1015 return tempConvertMap;
994 } 1016 }
995 1017
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index bc52a43..c7ffeaf 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -102,7 +102,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
102 102
103 terrainRenderer.Initialise(m_scene, m_config); 103 terrainRenderer.Initialise(m_scene, m_config);
104 104
105 mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 105 mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height,
106 System.Drawing.Imaging.PixelFormat.Format24bppRgb);
106 //long t = System.Environment.TickCount; 107 //long t = System.Environment.TickCount;
107 //for (int i = 0; i < 10; ++i) { 108 //for (int i = 0; i < 10; ++i) {
108 terrainRenderer.TerrainToBitmap(mapbmp); 109 terrainRenderer.TerrainToBitmap(mapbmp);
@@ -277,7 +278,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
277 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) 278 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
278 { 279 {
279 int tc = 0; 280 int tc = 0;
280 double[,] hm = whichScene.Heightmap.GetDoubles(); 281 ITerrainChannel hm = whichScene.Heightmap;
281 tc = Environment.TickCount; 282 tc = Environment.TickCount;
282 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); 283 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
283 EntityBase[] objs = whichScene.GetEntities(); 284 EntityBase[] objs = whichScene.GetEntities();
@@ -363,7 +364,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
363 Vector3 pos = part.GetWorldPosition(); 364 Vector3 pos = part.GetWorldPosition();
364 365
365 // skip prim outside of retion 366 // skip prim outside of retion
366 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) 367 if (!m_scene.PositionIsInCurrentRegion(pos))
367 continue; 368 continue;
368 369
369 // skip prim in non-finite position 370 // skip prim in non-finite position
@@ -388,7 +389,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
388 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); 389 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
389 Vector3 scale = new Vector3(); 390 Vector3 scale = new Vector3();
390 Vector3 tScale = new Vector3(); 391 Vector3 tScale = new Vector3();
391 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z); 392 Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
392 393
393 Quaternion llrot = part.GetWorldRotation(); 394 Quaternion llrot = part.GetWorldRotation();
394 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z); 395 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
@@ -406,9 +407,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
406 int mapdrawendY = (int)(pos.Y + scale.Y); 407 int mapdrawendY = (int)(pos.Y + scale.Y);
407 408
408 // If object is beyond the edge of the map, don't draw it to avoid errors 409 // If object is beyond the edge of the map, don't draw it to avoid errors
409 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1) 410 if (mapdrawstartX < 0
410 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0 411 || mapdrawstartX > (hm.Width - 1)
411 || mapdrawendY > ((int)Constants.RegionSize - 1)) 412 || mapdrawendX < 0
413 || mapdrawendX > (hm.Width - 1)
414 || mapdrawstartY < 0
415 || mapdrawstartY > (hm.Height - 1)
416 || mapdrawendY < 0
417 || mapdrawendY > (hm.Height - 1))
412 continue; 418 continue;
413 419
414 #region obb face reconstruction part duex 420 #region obb face reconstruction part duex
@@ -530,11 +536,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
530 for (int i = 0; i < FaceA.Length; i++) 536 for (int i = 0; i < FaceA.Length; i++)
531 { 537 {
532 Point[] working = new Point[5]; 538 Point[] working = new Point[5];
533 working[0] = project(FaceA[i], axPos); 539 working[0] = project(hm, FaceA[i], axPos);
534 working[1] = project(FaceB[i], axPos); 540 working[1] = project(hm, FaceB[i], axPos);
535 working[2] = project(FaceD[i], axPos); 541 working[2] = project(hm, FaceD[i], axPos);
536 working[3] = project(FaceC[i], axPos); 542 working[3] = project(hm, FaceC[i], axPos);
537 working[4] = project(FaceA[i], axPos); 543 working[4] = project(hm, FaceA[i], axPos);
538 544
539 face workingface = new face(); 545 face workingface = new face();
540 workingface.pts = working; 546 workingface.pts = working;
@@ -609,17 +615,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
609 return mapbmp; 615 return mapbmp;
610 } 616 }
611 617
612 private Point project(Vector3 point3d, Vector3 originpos) 618 private Point project(ITerrainChannel hm, Vector3 point3d, Vector3 originpos)
613 { 619 {
614 Point returnpt = new Point(); 620 Point returnpt = new Point();
615 //originpos = point3d; 621 //originpos = point3d;
616 //int d = (int)(256f / 1.5f); 622 //int d = (int)(256f / 1.5f);
617 623
618 //Vector3 topos = new Vector3(0, 0, 0); 624 //Vector3 topos = new Vector3(0, 0, 0);
619 // float z = -point3d.z - topos.z; 625 // float z = -point3d.z - topos.z;
620 626
621 returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d); 627 returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
622 returnpt.Y = (int)(((int)Constants.RegionSize - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d))); 628 returnpt.Y = (int)((hm.Width - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
623 629
624 return returnpt; 630 return returnpt;
625 } 631 }
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index cb06fd4..708286c 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
35 36
36namespace OpenSim.Region.CoreModules.World.LegacyMap 37namespace OpenSim.Region.CoreModules.World.LegacyMap
@@ -39,8 +40,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
39 { 40 {
40 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95); 41 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
41 42
42 private static readonly ILog m_log = 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]";
44 45
45 private Scene m_scene; 46 private Scene m_scene;
46 //private IConfigSource m_config; // not used currently 47 //private IConfigSource m_config; // not used currently
@@ -53,19 +54,26 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
53 54
54 public void TerrainToBitmap(Bitmap mapbmp) 55 public void TerrainToBitmap(Bitmap mapbmp)
55 { 56 {
57 m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
56 int tc = Environment.TickCount; 58 int tc = Environment.TickCount;
57 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
58 59
59 double[,] hm = m_scene.Heightmap.GetDoubles(); 60 ITerrainChannel hm = m_scene.Heightmap;
61
62 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
63 {
64 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
65 LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
66 }
67
60 bool ShadowDebugContinue = true; 68 bool ShadowDebugContinue = true;
61 69
62 bool terraincorruptedwarningsaid = false; 70 bool terraincorruptedwarningsaid = false;
63 71
64 float low = 255; 72 float low = 255;
65 float high = 0; 73 float high = 0;
66 for (int x = 0; x < (int)Constants.RegionSize; x++) 74 for (int x = 0; x < hm.Width; x++)
67 { 75 {
68 for (int y = 0; y < (int)Constants.RegionSize; y++) 76 for (int y = 0; y < hm.Height; y++)
69 { 77 {
70 float hmval = (float)hm[x, y]; 78 float hmval = (float)hm[x, y];
71 if (hmval < low) 79 if (hmval < low)
@@ -77,12 +85,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
77 85
78 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 86 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
79 87
80 for (int x = 0; x < (int)Constants.RegionSize; x++) 88 for (int x = 0; x < hm.Width; x++)
81 { 89 {
82 for (int y = 0; y < (int)Constants.RegionSize; y++) 90 for (int y = 0; y < hm.Height; y++)
83 { 91 {
84 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left 92 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
85 int yr = ((int)Constants.RegionSize - 1) - y; 93 int yr = ((int)hm.Height - 1) - y;
86 94
87 float heightvalue = (float)hm[x, y]; 95 float heightvalue = (float)hm[x, y];
88 96
@@ -109,12 +117,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
109 // . 117 // .
110 // 118 //
111 // Shade the terrain for shadows 119 // Shade the terrain for shadows
112 if (x < ((int)Constants.RegionSize - 1) && yr < ((int)Constants.RegionSize - 1)) 120 if (x < (hm.Width - 1) && yr < (hm.Height - 1))
113 { 121 {
114 float hfvalue = (float)hm[x, y]; 122 float hfvalue = (float)hm[x, y];
115 float hfvaluecompare = 0f; 123 float hfvaluecompare = 0f;
116 124
117 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize)) 125 if ((x + 1 < hm.Width) && (y + 1 < hm.Height))
118 { 126 {
119 hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there 127 hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
120 } 128 }
@@ -179,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
179 187
180 if (ShadowDebugContinue) 188 if (ShadowDebugContinue)
181 { 189 {
182 if ((x - 1 > 0) && (yr + 1 < (int)Constants.RegionSize)) 190 if ((x - 1 > 0) && (yr + 1 < hm.Height))
183 { 191 {
184 color = mapbmp.GetPixel(x - 1, yr + 1); 192 color = mapbmp.GetPixel(x - 1, yr + 1);
185 int r = color.R; 193 int r = color.R;
@@ -233,7 +241,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
233 terraincorruptedwarningsaid = true; 241 terraincorruptedwarningsaid = true;
234 } 242 }
235 Color black = Color.Black; 243 Color black = Color.Black;
236 mapbmp.SetPixel(x, ((int)Constants.RegionSize - y) - 1, black); 244 mapbmp.SetPixel(x, (hm.Width - y) - 1, black);
237 } 245 }
238 } 246 }
239 } 247 }
@@ -242,4 +250,4 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
242 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 250 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
243 } 251 }
244 } 252 }
245} \ No newline at end of file 253}
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index d4e4c25..014c845 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -151,14 +151,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
151 break; 151 break;
152 152
153 case 2: // Sell a copy 153 case 2: // Sell a copy
154 Vector3 inventoryStoredPosition = new Vector3 154 Vector3 inventoryStoredPosition = new Vector3(
155 (((group.AbsolutePosition.X > (int)Constants.RegionSize) 155 Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
156 ? 250 156 Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
157 : group.AbsolutePosition.X)
158 ,
159 (group.AbsolutePosition.X > (int)Constants.RegionSize)
160 ? 250
161 : group.AbsolutePosition.X,
162 group.AbsolutePosition.Z); 157 group.AbsolutePosition.Z);
163 158
164 Vector3 originalPosition = group.AbsolutePosition; 159 Vector3 originalPosition = group.AbsolutePosition;
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 616fe98..928755d 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1571,10 +1571,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1571 float X = position.X; 1571 float X = position.X;
1572 float Y = position.Y; 1572 float Y = position.Y;
1573 1573
1574 if (X > ((int)Constants.RegionSize - 1)) 1574 if (X > ((int)m_scene.RegionInfo.RegionSizeX - 1))
1575 X = ((int)Constants.RegionSize - 1); 1575 X = ((int)m_scene.RegionInfo.RegionSizeX - 1);
1576 if (Y > ((int)Constants.RegionSize - 1)) 1576 if (Y > ((int)m_scene.RegionInfo.RegionSizeY - 1))
1577 Y = ((int)Constants.RegionSize - 1); 1577 Y = ((int)m_scene.RegionInfo.RegionSizeY - 1);
1578 if (X < 0) 1578 if (X < 0)
1579 X = 0; 1579 X = 0;
1580 if (Y < 0) 1580 if (Y < 0)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
index 7186dd7..80396c4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
42 for (y = 0; y < map.Height; y++) 42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10; 44 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
45 double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01; 45 double spherFac = TerrainUtil.SphericalFactor(x, y, map.Width / 2, map.Height / 2, 50) * 0.01;
46 if (map[x, y] < spherFac) 46 if (map[x, y] < spherFac)
47 { 47 {
48 map[x, y] = spherFac; 48 map[x, y] = spherFac;
@@ -53,4 +53,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
53 53
54 #endregion 54 #endregion
55 } 55 }
56} \ No newline at end of file 56}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d78ade5..d5c77ec 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
67 { 67 {
68 using (Bitmap bitmap = new Bitmap(filename)) 68 using (Bitmap bitmap = new Bitmap(filename))
69 { 69 {
70 ITerrainChannel retval = new TerrainChannel(true); 70 ITerrainChannel retval = new TerrainChannel(w, h);
71 71
72 for (int x = 0; x < retval.Width; x++) 72 for (int x = 0; x < retval.Width; x++)
73 { 73 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
index b5c7d33..a7e4d9f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
@@ -154,10 +154,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
154 154
155 public ITerrainChannel LoadStream(Stream s) 155 public ITerrainChannel LoadStream(Stream s)
156 { 156 {
157 157 // Set to default size
158 int w = (int)Constants.RegionSize; 158 int w = (int)Constants.RegionSize;
159 int h = (int)Constants.RegionSize; 159 int h = (int)Constants.RegionSize;
160 160
161 // create a dummy channel (in case data is bad)
161 TerrainChannel retval = new TerrainChannel(w, h); 162 TerrainChannel retval = new TerrainChannel(w, h);
162 163
163 BinaryReader bs = new BinaryReader(s); 164 BinaryReader bs = new BinaryReader(s);
@@ -165,8 +166,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
165 bool eof = false; 166 bool eof = false;
166 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") 167 if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
167 { 168 {
168// int fileWidth = w;
169// int fileHeight = h;
170 169
171 // Terragen file 170 // Terragen file
172 while (eof == false) 171 while (eof == false)
@@ -175,31 +174,29 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
175 switch (tmp) 174 switch (tmp)
176 { 175 {
177 case "SIZE": 176 case "SIZE":
178// int sztmp = bs.ReadInt16() + 1; 177 w = bs.ReadInt16() + 1;
179// fileWidth = sztmp; 178 h = w;
180// fileHeight = sztmp;
181 bs.ReadInt16();
182 bs.ReadInt16(); 179 bs.ReadInt16();
183 break; 180 break;
184 case "XPTS": 181 case "XPTS":
185// fileWidth = bs.ReadInt16(); 182 w = bs.ReadInt16();
186 bs.ReadInt16();
187 bs.ReadInt16(); 183 bs.ReadInt16();
188 break; 184 break;
189 case "YPTS": 185 case "YPTS":
190// fileHeight = bs.ReadInt16(); 186 h = bs.ReadInt16();
191 bs.ReadInt16();
192 bs.ReadInt16(); 187 bs.ReadInt16();
193 break; 188 break;
194 case "ALTW": 189 case "ALTW":
195 eof = true; 190 eof = true;
196 Int16 heightScale = bs.ReadInt16(); 191 // create new channel of proper size (now that we know it)
197 Int16 baseHeight = bs.ReadInt16(); 192 retval = new TerrainChannel(w, h);
193 double heightScale = (double)bs.ReadInt16() / 65536.0;
194 double baseHeight = (double)bs.ReadInt16();
198 for (int y = 0; y < h; y++) 195 for (int y = 0; y < h; y++)
199 { 196 {
200 for (int x = 0; x < w; x++) 197 for (int x = 0; x < w; x++)
201 { 198 {
202 retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0; 199 retval[x, y] = baseHeight + (double)bs.ReadInt16() * heightScale;
203 } 200 }
204 } 201 }
205 break; 202 break;
@@ -257,17 +254,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
257 bs.Write(enc.GetBytes("TERRAGENTERRAIN ")); 254 bs.Write(enc.GetBytes("TERRAGENTERRAIN "));
258 255
259 bs.Write(enc.GetBytes("SIZE")); 256 bs.Write(enc.GetBytes("SIZE"));
260 bs.Write(Convert.ToInt16(Constants.RegionSize)); 257 bs.Write(Convert.ToInt16(map.Width));
261 bs.Write(Convert.ToInt16(0)); // necessary padding 258 bs.Write(Convert.ToInt16(0)); // necessary padding
262 259
263 //The XPTS and YPTS chunks are not needed for square regions 260 //The XPTS and YPTS chunks are not needed for square regions
264 //but L3DT won't load the terrain file properly without them. 261 //but L3DT won't load the terrain file properly without them.
265 bs.Write(enc.GetBytes("XPTS")); 262 bs.Write(enc.GetBytes("XPTS"));
266 bs.Write(Convert.ToInt16(Constants.RegionSize)); 263 bs.Write(Convert.ToInt16(map.Width));
267 bs.Write(Convert.ToInt16(0)); // necessary padding 264 bs.Write(Convert.ToInt16(0)); // necessary padding
268 265
269 bs.Write(enc.GetBytes("YPTS")); 266 bs.Write(enc.GetBytes("YPTS"));
270 bs.Write(Convert.ToInt16(Constants.RegionSize)); 267 bs.Write(Convert.ToInt16(map.Height));
271 bs.Write(Convert.ToInt16(0)); // necessary padding 268 bs.Write(Convert.ToInt16(0)); // necessary padding
272 269
273 bs.Write(enc.GetBytes("SCAL")); 270 bs.Write(enc.GetBytes("SCAL"));
@@ -283,11 +280,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
283 bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min 280 bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min
284 bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point 281 bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point
285 282
283 double factor = 65536.0 / horizontalScale; // avoid computing this on each iteration
284
286 for (int y = 0; y < map.Height; y++) 285 for (int y = 0; y < map.Height; y++)
287 { 286 {
288 for (int x = 0; x < map.Width; x++) 287 for (int x = 0; x < map.Width; x++)
289 { 288 {
290 float elevation = (float)((map[x,y] - baseHeight) * 65536 ) / (float)horizontalScale; // see LoadStream for inverse 289 float elevation = (float)((map[x,y] - baseHeight) * factor); // see LoadStream for inverse
291 290
292 // clamp rounding issues 291 // clamp rounding issues
293 if (elevation > Int16.MaxValue) 292 if (elevation > Int16.MaxValue)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
index 630473e..d3e2533 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
45 { 45 {
46 if (fillArea[x, y]) 46 if (fillArea[x, y])
47 { 47 {
48 double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0); 48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
49 49
50 map[x, y] += noise * strength; 50 map[x, y] += noise * strength;
51 } 51 }
@@ -55,4 +55,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 55
56 #endregion 56 #endregion
57 } 57 }
58} \ No newline at end of file 58}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
index 989b7d8..e7df3f8 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
53 z *= z; 53 z *= z;
54 z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry)); 54 z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
55 55
56 double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0); 56 double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0);
57 57
58 if (z > 0.0) 58 if (z > 0.0)
59 map[x, y] += noise * z * duration; 59 map[x, y] += noise * z * duration;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 4d738a5..9a88804 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -71,6 +71,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
71 71
72 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 72 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
73 73
74#pragma warning disable 414
75 private static readonly string LogHeader = "[TERRAIN MODULE]";
76#pragma warning restore 414
77
74 private readonly Commander m_commander = new Commander("terrain"); 78 private readonly Commander m_commander = new Commander("terrain");
75 79
76 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = 80 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
@@ -81,8 +85,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
81 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 85 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
82 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 86 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
83 87
84 private ITerrainChannel m_channel;
85 private Dictionary<string, ITerrainEffect> m_plugineffects; 88 private Dictionary<string, ITerrainEffect> m_plugineffects;
89 private ITerrainChannel m_channel;
86 private ITerrainChannel m_revert; 90 private ITerrainChannel m_revert;
87 private Scene m_scene; 91 private Scene m_scene;
88 private volatile bool m_tainted; 92 private volatile bool m_tainted;
@@ -90,6 +94,85 @@ namespace OpenSim.Region.CoreModules.World.Terrain
90 94
91 private String m_InitialTerrain = "pinhead-island"; 95 private String m_InitialTerrain = "pinhead-island";
92 96
97 // If true, send terrain patch updates to clients based on their view distance
98 private bool m_sendTerrainUpdatesByViewDistance = true;
99
100 // Class to keep the per client collection of terrain patches that must be sent.
101 // A patch is set to 'true' meaning it should be sent to the client. Once the
102 // patch packet is queued to the client, the bit for that patch is set to 'false'.
103 private class PatchUpdates
104 {
105 private bool[,] updated; // for each patch, whether it needs to be sent to this client
106 private int updateCount; // number of patches that need to be sent
107 public ScenePresence Presence; // a reference to the client to send to
108 public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
109 {
110 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
111 updateCount = 0;
112 Presence = pPresence;
113 // Initially, send all patches to the client
114 SetAll(true);
115 }
116 // Returns 'true' if there are any patches marked for sending
117 public bool HasUpdates()
118 {
119 return (updateCount > 0);
120 }
121 public void SetByXY(int x, int y, bool state)
122 {
123 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
124 }
125 public bool GetByPatch(int patchX, int patchY)
126 {
127 return updated[patchX, patchY];
128 }
129 public void SetByPatch(int patchX, int patchY, bool state)
130 {
131 bool prevState = updated[patchX, patchY];
132 if (!prevState && state)
133 updateCount++;
134 if (prevState && !state)
135 updateCount--;
136 updated[patchX, patchY] = state;
137 }
138 public void SetAll(bool state)
139 {
140 updateCount = 0;
141 for (int xx = 0; xx < updated.GetLength(0); xx++)
142 for (int yy = 0; yy < updated.GetLength(1); yy++)
143 updated[xx, yy] = state;
144 if (state)
145 updateCount = updated.GetLength(0) * updated.GetLength(1);
146 }
147 // Logically OR's the terrain data's patch taint map into this client's update map.
148 public void SetAll(TerrainData terrData)
149 {
150 if (updated.GetLength(0) != (terrData.SizeX / Constants.TerrainPatchSize)
151 || updated.GetLength(1) != (terrData.SizeY / Constants.TerrainPatchSize))
152 {
153 throw new Exception(
154 String.Format("{0} PatchUpdates.SetAll: patch array not same size as terrain. arr=<{1},{2}>, terr=<{3},{4}>",
155 LogHeader, updated.GetLength(0), updated.GetLength(1),
156 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
157 );
158 }
159 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
160 {
161 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
162 {
163 // Only set tainted. The patch bit may be set if the patch was to be sent later.
164 if (terrData.IsTaintedAt(xx, yy, false))
165 {
166 this.SetByXY(xx, yy, true);
167 }
168 }
169 }
170 }
171 }
172
173 // The flags of which terrain patches to send for each of the ScenePresence's
174 private Dictionary<UUID, PatchUpdates> m_perClientPatchUpdates = new Dictionary<UUID, PatchUpdates>();
175
93 /// <summary> 176 /// <summary>
94 /// Human readable list of terrain file extensions that are supported. 177 /// Human readable list of terrain file extensions that are supported.
95 /// </summary> 178 /// </summary>
@@ -118,7 +201,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
118 { 201 {
119 IConfig terrainConfig = config.Configs["Terrain"]; 202 IConfig terrainConfig = config.Configs["Terrain"];
120 if (terrainConfig != null) 203 if (terrainConfig != null)
204 {
121 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 205 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
206 m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance);
207 }
122 } 208 }
123 209
124 public void AddRegion(Scene scene) 210 public void AddRegion(Scene scene)
@@ -130,22 +216,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain
130 { 216 {
131 if (m_scene.Heightmap == null) 217 if (m_scene.Heightmap == null)
132 { 218 {
133 m_channel = new TerrainChannel(m_InitialTerrain); 219 m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX,
220 (int)m_scene.RegionInfo.RegionSizeY,
221 (int)m_scene.RegionInfo.RegionSizeZ);
134 m_scene.Heightmap = m_channel; 222 m_scene.Heightmap = m_channel;
135 m_revert = new TerrainChannel();
136 UpdateRevertMap(); 223 UpdateRevertMap();
137 } 224 }
138 else 225 else
139 { 226 {
140 m_channel = m_scene.Heightmap; 227 m_channel = m_scene.Heightmap;
141 m_revert = new TerrainChannel();
142 UpdateRevertMap(); 228 UpdateRevertMap();
143 } 229 }
144 230
145 m_scene.RegisterModuleInterface<ITerrainModule>(this); 231 m_scene.RegisterModuleInterface<ITerrainModule>(this);
146 m_scene.EventManager.OnNewClient += EventManager_OnNewClient; 232 m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
233 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
147 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 234 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
148 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; 235 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
236 m_scene.EventManager.OnFrame += EventManager_OnFrame;
149 } 237 }
150 238
151 InstallDefaultEffects(); 239 InstallDefaultEffects();
@@ -184,8 +272,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
184 // remove the commands 272 // remove the commands
185 m_scene.UnregisterModuleCommander(m_commander.Name); 273 m_scene.UnregisterModuleCommander(m_commander.Name);
186 // remove the event-handlers 274 // remove the event-handlers
275 m_scene.EventManager.OnFrame -= EventManager_OnFrame;
187 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; 276 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
188 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; 277 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
278 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
189 m_scene.EventManager.OnNewClient -= EventManager_OnNewClient; 279 m_scene.EventManager.OnNewClient -= EventManager_OnNewClient;
190 // remove the interface 280 // remove the interface
191 m_scene.UnregisterModuleInterface<ITerrainModule>(this); 281 m_scene.UnregisterModuleInterface<ITerrainModule>(this);
@@ -230,11 +320,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
230 try 320 try
231 { 321 {
232 ITerrainChannel channel = loader.Value.LoadFile(filename); 322 ITerrainChannel channel = loader.Value.LoadFile(filename);
233 if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize) 323 if (channel.Width != m_scene.RegionInfo.RegionSizeX || channel.Height != m_scene.RegionInfo.RegionSizeY)
234 { 324 {
235 // TerrainChannel expects a RegionSize x RegionSize map, currently 325 // TerrainChannel expects a RegionSize x RegionSize map, currently
236 throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}", 326 throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}",
237 Constants.RegionSize, Constants.RegionSize)); 327 m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY));
238 } 328 }
239 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); 329 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
240 m_scene.Heightmap = channel; 330 m_scene.Heightmap = channel;
@@ -261,7 +351,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
261 String.Format("Unable to load heightmap: {0}", e.Message)); 351 String.Format("Unable to load heightmap: {0}", e.Message));
262 } 352 }
263 } 353 }
264 CheckForTerrainUpdates();
265 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); 354 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
266 return; 355 return;
267 } 356 }
@@ -309,12 +398,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
309 LoadFromStream(filename, URIFetch(pathToTerrainHeightmap)); 398 LoadFromStream(filename, URIFetch(pathToTerrainHeightmap));
310 } 399 }
311 400
401 public void LoadFromStream(string filename, Stream stream)
402 {
403 LoadFromStream(filename, Vector3.Zero, 0f, Vector2.Zero, stream);
404 }
405
312 /// <summary> 406 /// <summary>
313 /// Loads a terrain file from a stream and installs it in the scene. 407 /// Loads a terrain file from a stream and installs it in the scene.
314 /// </summary> 408 /// </summary>
315 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> 409 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
316 /// <param name="stream"></param> 410 /// <param name="stream"></param>
317 public void LoadFromStream(string filename, Stream stream) 411 public void LoadFromStream(string filename, Vector3 displacement,
412 float radianRotation, Vector2 rotationDisplacement, Stream stream)
318 { 413 {
319 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 414 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
320 { 415 {
@@ -325,8 +420,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
325 try 420 try
326 { 421 {
327 ITerrainChannel channel = loader.Value.LoadStream(stream); 422 ITerrainChannel channel = loader.Value.LoadStream(stream);
328 m_scene.Heightmap = channel; 423 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
329 m_channel = channel;
330 UpdateRevertMap(); 424 UpdateRevertMap();
331 } 425 }
332 catch (NotImplementedException) 426 catch (NotImplementedException)
@@ -337,7 +431,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
337 } 431 }
338 } 432 }
339 433
340 CheckForTerrainUpdates();
341 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); 434 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
342 return; 435 return;
343 } 436 }
@@ -406,9 +499,46 @@ namespace OpenSim.Region.CoreModules.World.Terrain
406 } 499 }
407 } 500 }
408 501
502 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
503 // ITerrainModule.TaintTerrain()
409 public void TaintTerrain () 504 public void TaintTerrain ()
410 { 505 {
411 CheckForTerrainUpdates(); 506 lock (m_perClientPatchUpdates)
507 {
508 // Set the flags for all clients so the tainted patches will be sent out
509 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
510 {
511 pups.SetAll(m_scene.Heightmap.GetTerrainData());
512 }
513 }
514 }
515
516 // ITerrainModule.PushTerrain()
517 public void PushTerrain(IClientAPI pClient)
518 {
519 if (m_sendTerrainUpdatesByViewDistance)
520 {
521 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
522 if (presence != null)
523 {
524 lock (m_perClientPatchUpdates)
525 {
526 PatchUpdates pups;
527 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
528 {
529 // There is a ScenePresence without a send patch map. Create one.
530 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
531 m_perClientPatchUpdates.Add(presence.UUID, pups);
532 }
533 pups.SetAll(true);
534 }
535 }
536 }
537 else
538 {
539 // The traditional way is to call into the protocol stack to send them all.
540 pClient.SendLayerData(new float[10]);
541 }
412 } 542 }
413 543
414 #region Plugin Loading Methods 544 #region Plugin Loading Methods
@@ -532,6 +662,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
532 /// </summary> 662 /// </summary>
533 public void UpdateRevertMap() 663 public void UpdateRevertMap()
534 { 664 {
665 /*
535 int x; 666 int x;
536 for (x = 0; x < m_channel.Width; x++) 667 for (x = 0; x < m_channel.Width; x++)
537 { 668 {
@@ -541,6 +672,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
541 m_revert[x, y] = m_channel[x, y]; 672 m_revert[x, y] = m_channel[x, y];
542 } 673 }
543 } 674 }
675 */
676 m_revert = m_channel.MakeCopy();
544 } 677 }
545 678
546 /// <summary> 679 /// <summary>
@@ -567,8 +700,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
567 { 700 {
568 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 701 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
569 fileWidth, fileHeight, 702 fileWidth, fileHeight,
570 (int) Constants.RegionSize, 703 (int) m_scene.RegionInfo.RegionSizeX,
571 (int) Constants.RegionSize); 704 (int) m_scene.RegionInfo.RegionSizeY);
572 m_scene.Heightmap = channel; 705 m_scene.Heightmap = channel;
573 m_channel = channel; 706 m_channel = channel;
574 UpdateRevertMap(); 707 UpdateRevertMap();
@@ -615,8 +748,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
615 { 748 {
616 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, 749 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
617 fileWidth, fileHeight, 750 fileWidth, fileHeight,
618 (int)Constants.RegionSize, 751 (int)m_scene.RegionInfo.RegionSizeX,
619 (int)Constants.RegionSize); 752 (int)m_scene.RegionInfo.RegionSizeY);
620 753
621 MainConsole.Instance.OutputFormat( 754 MainConsole.Instance.OutputFormat(
622 "Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}", 755 "Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}",
@@ -634,7 +767,44 @@ namespace OpenSim.Region.CoreModules.World.Terrain
634 } 767 }
635 768
636 /// <summary> 769 /// <summary>
770 /// Called before processing of every simulation frame.
771 /// This is used to check to see of any of the terrain is tainted and, if so, schedule
772 /// updates for all the presences.
773 /// This also checks to see if there are updates that need to be sent for each presence.
774 /// This is where the logic is to send terrain updates to clients.
775 /// </summary>
776 private void EventManager_OnFrame()
777 {
778 TerrainData terrData = m_channel.GetTerrainData();
779
780 bool shouldTaint = false;
781 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
782 {
783 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
784 {
785 if (terrData.IsTaintedAt(x, y))
786 {
787 // Found a patch that was modified. Push this flag into the clients.
788 SendToClients(terrData, x, y);
789 shouldTaint = true;
790 }
791 }
792 }
793
794 // This event also causes changes to be sent to the clients
795 CheckSendingPatchesToClients();
796
797 // If things changes, generate some events
798 if (shouldTaint)
799 {
800 m_scene.EventManager.TriggerTerrainTainted();
801 m_tainted = true;
802 }
803 }
804
805 /// <summary>
637 /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections 806 /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
807 /// Called infrequently (like every 5 seconds or so). Best used for storing terrain.
638 /// </summary> 808 /// </summary>
639 private void EventManager_OnTerrainTick() 809 private void EventManager_OnTerrainTick()
640 { 810 {
@@ -644,8 +814,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
644 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); 814 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
645 m_scene.SaveTerrain(); 815 m_scene.SaveTerrain();
646 816
647 m_scene.EventManager.TriggerTerrainUpdate();
648
649 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. 817 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
650 //m_scene.CreateTerrainTexture(true); 818 //m_scene.CreateTerrainTexture(true);
651 } 819 }
@@ -687,54 +855,48 @@ namespace OpenSim.Region.CoreModules.World.Terrain
687 } 855 }
688 856
689 /// <summary> 857 /// <summary>
690 /// Checks to see if the terrain has been modified since last check 858 /// Installs terrain brush hook to IClientAPI
691 /// but won't attempt to limit those changes to the limits specified in the estate settings
692 /// currently invoked by the command line operations in the region server only
693 /// </summary> 859 /// </summary>
694 private void CheckForTerrainUpdates() 860 /// <param name="client"></param>
861 private void EventManager_OnClientClosed(UUID client, Scene scene)
695 { 862 {
696 CheckForTerrainUpdates(false); 863 ScenePresence presence = scene.GetScenePresence(client);
697 } 864 if (presence != null)
865 {
866 presence.ControllingClient.OnModifyTerrain -= client_OnModifyTerrain;
867 presence.ControllingClient.OnBakeTerrain -= client_OnBakeTerrain;
868 presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
869 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
870 }
698 871
872 lock (m_perClientPatchUpdates)
873 m_perClientPatchUpdates.Remove(client);
874 }
875
699 /// <summary> 876 /// <summary>
700 /// Checks to see if the terrain has been modified since last check. 877 /// Scan over changes in the terrain and limit height changes. This enforces the
701 /// If it has been modified, every all the terrain patches are sent to the client. 878 /// non-estate owner limits on rate of terrain editting.
702 /// If the call is asked to respect the estate settings for terrain_raise_limit and 879 /// Returns 'true' if any heights were limited.
703 /// terrain_lower_limit, it will clamp terrain updates between these values
704 /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
705 /// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
706 /// </summary> 880 /// </summary>
707 private void CheckForTerrainUpdates(bool respectEstateSettings) 881 private bool EnforceEstateLimits()
708 { 882 {
709 bool shouldTaint = false; 883 TerrainData terrData = m_channel.GetTerrainData();
710 float[] serialised = m_channel.GetFloatsSerialised(); 884
711 int x; 885 bool wasLimited = false;
712 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) 886 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
713 { 887 {
714 int y; 888 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
715 for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
716 { 889 {
717 if (m_channel.Tainted(x, y)) 890 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
718 { 891 {
719 // if we should respect the estate settings then 892 // If we should respect the estate settings then
720 // fixup and height deltas that don't respect them 893 // fixup and height deltas that don't respect them.
721 if (respectEstateSettings && LimitChannelChanges(x, y)) 894 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
722 { 895 wasLimited |= LimitChannelChanges(terrData, x, y);
723 // this has been vetoed, so update
724 // what we are going to send to the client
725 serialised = m_channel.GetFloatsSerialised();
726 }
727
728 SendToClients(serialised, x, y);
729 shouldTaint = true;
730 } 896 }
731 } 897 }
732 } 898 }
733 if (shouldTaint) 899 return wasLimited;
734 {
735 m_scene.EventManager.TriggerTerrainTainted();
736 m_tainted = true;
737 }
738 } 900 }
739 901
740 /// <summary> 902 /// <summary>
@@ -742,11 +904,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
742 /// are all within the current estate limits 904 /// are all within the current estate limits
743 /// <returns>true if changes were limited, false otherwise</returns> 905 /// <returns>true if changes were limited, false otherwise</returns>
744 /// </summary> 906 /// </summary>
745 private bool LimitChannelChanges(int xStart, int yStart) 907 private bool LimitChannelChanges(TerrainData terrData, int xStart, int yStart)
746 { 908 {
747 bool changesLimited = false; 909 bool changesLimited = false;
748 double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; 910 float minDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
749 double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; 911 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
750 912
751 // loop through the height map for this patch and compare it against 913 // loop through the height map for this patch and compare it against
752 // the revert map 914 // the revert map
@@ -754,19 +916,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
754 { 916 {
755 for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 917 for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
756 { 918 {
757 919 float requestedHeight = terrData[x, y];
758 double requestedHeight = m_channel[x, y]; 920 float bakedHeight = (float)m_revert[x, y];
759 double bakedHeight = m_revert[x, y]; 921 float requestedDelta = requestedHeight - bakedHeight;
760 double requestedDelta = requestedHeight - bakedHeight;
761 922
762 if (requestedDelta > maxDelta) 923 if (requestedDelta > maxDelta)
763 { 924 {
764 m_channel[x, y] = bakedHeight + maxDelta; 925 terrData[x, y] = bakedHeight + maxDelta;
765 changesLimited = true; 926 changesLimited = true;
766 } 927 }
767 else if (requestedDelta < minDelta) 928 else if (requestedDelta < minDelta)
768 { 929 {
769 m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta 930 terrData[x, y] = bakedHeight + minDelta; //as lower is a -ve delta
770 changesLimited = true; 931 changesLimited = true;
771 } 932 }
772 } 933 }
@@ -794,14 +955,154 @@ namespace OpenSim.Region.CoreModules.World.Terrain
794 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> 955 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
795 /// <param name="x">The patch corner to send</param> 956 /// <param name="x">The patch corner to send</param>
796 /// <param name="y">The patch corner to send</param> 957 /// <param name="y">The patch corner to send</param>
797 private void SendToClients(float[] serialised, int x, int y) 958 private void SendToClients(TerrainData terrData, int x, int y)
959 {
960 if (m_sendTerrainUpdatesByViewDistance)
961 {
962 // Add that this patch needs to be sent to the accounting for each client.
963 lock (m_perClientPatchUpdates)
964 {
965 m_scene.ForEachScenePresence(presence =>
966 {
967 PatchUpdates thisClientUpdates;
968 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
969 {
970 // There is a ScenePresence without a send patch map. Create one.
971 thisClientUpdates = new PatchUpdates(terrData, presence);
972 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
973 }
974 thisClientUpdates.SetByXY(x, y, true);
975 }
976 );
977 }
978 }
979 else
980 {
981 // Legacy update sending where the update is sent out as soon as noticed
982 // We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI.
983 //float[] heightMap = terrData.GetFloatsSerialized();
984 float[] heightMap = new float[10];
985 m_scene.ForEachClient(
986 delegate(IClientAPI controller)
987 {
988 controller.SendLayerData(x / Constants.TerrainPatchSize,
989 y / Constants.TerrainPatchSize,
990 heightMap);
991 }
992 );
993 }
994 }
995
996 private class PatchesToSend : IComparable<PatchesToSend>
798 { 997 {
799 m_scene.ForEachClient( 998 public int PatchX;
800 delegate(IClientAPI controller) 999 public int PatchY;
801 { controller.SendLayerData( 1000 public float Dist;
802 x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised); 1001 public PatchesToSend(int pX, int pY, float pDist)
1002 {
1003 PatchX = pX;
1004 PatchY = pY;
1005 Dist = pDist;
1006 }
1007 public int CompareTo(PatchesToSend other)
1008 {
1009 return Dist.CompareTo(other.Dist);
1010 }
1011 }
1012
1013 // Called each frame time to see if there are any patches to send to any of the
1014 // ScenePresences.
1015 // Loop through all the per-client info and send any patches necessary.
1016 private void CheckSendingPatchesToClients()
1017 {
1018 lock (m_perClientPatchUpdates)
1019 {
1020 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
1021 {
1022 if (pups.HasUpdates())
1023 {
1024 // There is something that could be sent to this client.
1025 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1026 if (toSend.Count > 0)
1027 {
1028 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1029 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1030 // Sort the patches to send by the distance from the presence
1031 toSend.Sort();
1032 /*
1033 foreach (PatchesToSend pts in toSend)
1034 {
1035 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1036 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1037 }
1038 */
1039
1040 int[] xPieces = new int[toSend.Count];
1041 int[] yPieces = new int[toSend.Count];
1042 float[] patchPieces = new float[toSend.Count * 2];
1043 int pieceIndex = 0;
1044 foreach (PatchesToSend pts in toSend)
1045 {
1046 patchPieces[pieceIndex++] = pts.PatchX;
1047 patchPieces[pieceIndex++] = pts.PatchY;
1048 }
1049 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
1050 }
1051 }
1052 }
1053 }
1054 }
1055
1056 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
1057 {
1058 List<PatchesToSend> ret = new List<PatchesToSend>();
1059
1060 ScenePresence presence = pups.Presence;
1061 if (presence == null)
1062 return ret;
1063
1064 // Compute the area of patches within our draw distance
1065 int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
1066 startX = Math.Max(startX, 0);
1067 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
1068 int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
1069 startY = Math.Max(startY, 0);
1070 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
1071 int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
1072 endX = Math.Max(endX, 0);
1073 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
1074 int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
1075 endY = Math.Max(endY, 0);
1076 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
1077 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
1078 // LogHeader, m_scene.RegionInfo.RegionName,
1079 // presence.DrawDistance, presence.AbsolutePosition,
1080 // startX, startY, endX, endY);
1081 for (int x = startX; x < endX; x++)
1082 {
1083 for (int y = startY; y < endY; y++)
1084 {
1085 //Need to make sure we don't send the same ones over and over
1086 Vector3 presencePos = presence.AbsolutePosition;
1087 Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
1088 if (pups.GetByPatch(x, y))
1089 {
1090 //Check which has less distance, camera or avatar position, both have to be done.
1091 //Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off
1092 if (Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50)
1093 || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
1094 {
1095 //They can see it, send it to them
1096 pups.SetByPatch(x, y, false);
1097 float dist = Vector3.DistanceSquared(presencePos, patchPos);
1098 ret.Add(new PatchesToSend(x, y, dist));
1099 //Wait and send them all at once
1100 // pups.client.SendLayerData(x, y, null);
1101 }
803 } 1102 }
804 ); 1103 }
1104 }
1105 return ret;
805 } 1106 }
806 1107
807 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action, 1108 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
@@ -846,7 +1147,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
846 m_painteffects[(StandardTerrainEffects) action].PaintEffect( 1147 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
847 m_channel, allowMask, west, south, height, size, seconds); 1148 m_channel, allowMask, west, south, height, size, seconds);
848 1149
849 CheckForTerrainUpdates(!god); //revert changes outside estate limits 1150 //revert changes outside estate limits
1151 if (!god)
1152 EnforceEstateLimits();
850 } 1153 }
851 } 1154 }
852 else 1155 else
@@ -884,10 +1187,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
884 if (allowed) 1187 if (allowed)
885 { 1188 {
886 StoreUndoState(); 1189 StoreUndoState();
887 m_floodeffects[(StandardTerrainEffects) action].FloodEffect( 1190 m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size);
888 m_channel, fillArea, size);
889 1191
890 CheckForTerrainUpdates(!god); //revert changes outside estate limits 1192 //revert changes outside estate limits
1193 if (!god)
1194 EnforceEstateLimits();
891 } 1195 }
892 } 1196 }
893 else 1197 else
@@ -911,7 +1215,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
911 protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY) 1215 protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY)
912 { 1216 {
913 //m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY); 1217 //m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY);
914 client.SendLayerData(patchX, patchY, m_scene.Heightmap.GetFloatsSerialised()); 1218 // SendLayerData does not use the heightmap parameter. This kludge is so as to not change IClientAPI.
1219 float[] heightMap = new float[10];
1220 client.SendLayerData(patchX, patchY, heightMap);
915 } 1221 }
916 1222
917 private void StoreUndoState() 1223 private void StoreUndoState()
@@ -938,7 +1244,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
938 private void InterfaceLoadFile(Object[] args) 1244 private void InterfaceLoadFile(Object[] args)
939 { 1245 {
940 LoadFromFile((string) args[0]); 1246 LoadFromFile((string) args[0]);
941 CheckForTerrainUpdates();
942 } 1247 }
943 1248
944 private void InterfaceLoadTileFile(Object[] args) 1249 private void InterfaceLoadTileFile(Object[] args)
@@ -948,7 +1253,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
948 (int) args[2], 1253 (int) args[2],
949 (int) args[3], 1254 (int) args[3],
950 (int) args[4]); 1255 (int) args[4]);
951 CheckForTerrainUpdates();
952 } 1256 }
953 1257
954 private void InterfaceSaveFile(Object[] args) 1258 private void InterfaceSaveFile(Object[] args)
@@ -977,7 +1281,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
977 for (y = 0; y < m_channel.Height; y++) 1281 for (y = 0; y < m_channel.Height; y++)
978 m_channel[x, y] = m_revert[x, y]; 1282 m_channel[x, y] = m_revert[x, y];
979 1283
980 CheckForTerrainUpdates();
981 } 1284 }
982 1285
983 private void InterfaceFlipTerrain(Object[] args) 1286 private void InterfaceFlipTerrain(Object[] args)
@@ -986,28 +1289,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
986 1289
987 if (direction.ToLower().StartsWith("y")) 1290 if (direction.ToLower().StartsWith("y"))
988 { 1291 {
989 for (int x = 0; x < Constants.RegionSize; x++) 1292 for (int x = 0; x < m_channel.Width; x++)
990 { 1293 {
991 for (int y = 0; y < Constants.RegionSize / 2; y++) 1294 for (int y = 0; y < m_channel.Height / 2; y++)
992 { 1295 {
993 double height = m_channel[x, y]; 1296 double height = m_channel[x, y];
994 double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y]; 1297 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
995 m_channel[x, y] = flippedHeight; 1298 m_channel[x, y] = flippedHeight;
996 m_channel[x, (int)Constants.RegionSize - 1 - y] = height; 1299 m_channel[x, (int)m_channel.Height - 1 - y] = height;
997 1300
998 } 1301 }
999 } 1302 }
1000 } 1303 }
1001 else if (direction.ToLower().StartsWith("x")) 1304 else if (direction.ToLower().StartsWith("x"))
1002 { 1305 {
1003 for (int y = 0; y < Constants.RegionSize; y++) 1306 for (int y = 0; y < m_channel.Height; y++)
1004 { 1307 {
1005 for (int x = 0; x < Constants.RegionSize / 2; x++) 1308 for (int x = 0; x < m_channel.Width / 2; x++)
1006 { 1309 {
1007 double height = m_channel[x, y]; 1310 double height = m_channel[x, y];
1008 double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y]; 1311 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
1009 m_channel[x, y] = flippedHeight; 1312 m_channel[x, y] = flippedHeight;
1010 m_channel[(int)Constants.RegionSize - 1 - x, y] = height; 1313 m_channel[(int)m_channel.Width - 1 - x, y] = height;
1011 1314
1012 } 1315 }
1013 } 1316 }
@@ -1016,9 +1319,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1016 { 1319 {
1017 m_log.Error("Unrecognised direction - need x or y"); 1320 m_log.Error("Unrecognised direction - need x or y");
1018 } 1321 }
1019
1020
1021 CheckForTerrainUpdates();
1022 } 1322 }
1023 1323
1024 private void InterfaceRescaleTerrain(Object[] args) 1324 private void InterfaceRescaleTerrain(Object[] args)
@@ -1076,7 +1376,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1076 } 1376 }
1077 } 1377 }
1078 1378
1079 CheckForTerrainUpdates();
1080 } 1379 }
1081 1380
1082 } 1381 }
@@ -1087,7 +1386,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1087 for (x = 0; x < m_channel.Width; x++) 1386 for (x = 0; x < m_channel.Width; x++)
1088 for (y = 0; y < m_channel.Height; y++) 1387 for (y = 0; y < m_channel.Height; y++)
1089 m_channel[x, y] += (double) args[0]; 1388 m_channel[x, y] += (double) args[0];
1090 CheckForTerrainUpdates();
1091 } 1389 }
1092 1390
1093 private void InterfaceMultiplyTerrain(Object[] args) 1391 private void InterfaceMultiplyTerrain(Object[] args)
@@ -1096,7 +1394,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1096 for (x = 0; x < m_channel.Width; x++) 1394 for (x = 0; x < m_channel.Width; x++)
1097 for (y = 0; y < m_channel.Height; y++) 1395 for (y = 0; y < m_channel.Height; y++)
1098 m_channel[x, y] *= (double) args[0]; 1396 m_channel[x, y] *= (double) args[0];
1099 CheckForTerrainUpdates();
1100 } 1397 }
1101 1398
1102 private void InterfaceLowerTerrain(Object[] args) 1399 private void InterfaceLowerTerrain(Object[] args)
@@ -1105,17 +1402,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1105 for (x = 0; x < m_channel.Width; x++) 1402 for (x = 0; x < m_channel.Width; x++)
1106 for (y = 0; y < m_channel.Height; y++) 1403 for (y = 0; y < m_channel.Height; y++)
1107 m_channel[x, y] -= (double) args[0]; 1404 m_channel[x, y] -= (double) args[0];
1108 CheckForTerrainUpdates();
1109 } 1405 }
1110 1406
1111 private void InterfaceFillTerrain(Object[] args) 1407 public void InterfaceFillTerrain(Object[] args)
1112 { 1408 {
1113 int x, y; 1409 int x, y;
1114 1410
1115 for (x = 0; x < m_channel.Width; x++) 1411 for (x = 0; x < m_channel.Width; x++)
1116 for (y = 0; y < m_channel.Height; y++) 1412 for (y = 0; y < m_channel.Height; y++)
1117 m_channel[x, y] = (double) args[0]; 1413 m_channel[x, y] = (double) args[0];
1118 CheckForTerrainUpdates();
1119 } 1414 }
1120 1415
1121 private void InterfaceMinTerrain(Object[] args) 1416 private void InterfaceMinTerrain(Object[] args)
@@ -1128,7 +1423,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1128 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1423 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
1129 } 1424 }
1130 } 1425 }
1131 CheckForTerrainUpdates();
1132 } 1426 }
1133 1427
1134 private void InterfaceMaxTerrain(Object[] args) 1428 private void InterfaceMaxTerrain(Object[] args)
@@ -1141,7 +1435,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1141 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1435 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
1142 } 1436 }
1143 } 1437 }
1144 CheckForTerrainUpdates();
1145 } 1438 }
1146 1439
1147 private void InterfaceShowDebugStats(Object[] args) 1440 private void InterfaceShowDebugStats(Object[] args)
@@ -1204,7 +1497,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1204 if (m_plugineffects.ContainsKey(firstArg)) 1497 if (m_plugineffects.ContainsKey(firstArg))
1205 { 1498 {
1206 m_plugineffects[firstArg].RunEffect(m_channel); 1499 m_plugineffects[firstArg].RunEffect(m_channel);
1207 CheckForTerrainUpdates();
1208 } 1500 }
1209 else 1501 else
1210 { 1502 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index be719ea..062d7ff 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -40,10 +40,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
40 [Test] 40 [Test]
41 public void BrushTest() 41 public void BrushTest()
42 { 42 {
43 int midRegion = (int)Constants.RegionSize / 2;
44
45 // Create a mask that covers only the left half of the region
43 bool[,] allowMask = new bool[(int)Constants.RegionSize, 256]; 46 bool[,] allowMask = new bool[(int)Constants.RegionSize, 256];
44 int x; 47 int x;
45 int y; 48 int y;
46 for (x = 0; x < (int)((int)Constants.RegionSize * 0.5f); x++) 49 for (x = 0; x < midRegion; x++)
47 { 50 {
48 for (y = 0; y < (int)Constants.RegionSize; y++) 51 for (y = 0; y < (int)Constants.RegionSize; y++)
49 { 52 {
@@ -57,13 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
57 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); 60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
58 ITerrainPaintableEffect effect = new RaiseSphere(); 61 ITerrainPaintableEffect effect = new RaiseSphere();
59 62
60 effect.PaintEffect(map, allowMask, (int)Constants.RegionSize * 0.5f, (int)Constants.RegionSize * 0.5f, -1.0, 2, 0.1); 63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
61 Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (127,128)."); 64 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
62 Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (124,128)."); 65 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
63 Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (123,128)."); 66 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
64 Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (128,128)."); 67 Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
65 Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (0,128)."); 68 Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
66
67 // 69 //
68 // Test LowerSphere 70 // Test LowerSphere
69 // 71 //
@@ -77,13 +79,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
77 } 79 }
78 effect = new LowerSphere(); 80 effect = new LowerSphere();
79 81
80 effect.PaintEffect(map, allowMask, ((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), -1.0, 2, 6.0); 82 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
81 Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); 83 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
82 Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); 84 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
83 Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] < 1.0, "Lower brush should lowering value at this point (124,128)."); 85 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
84 Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (123,128)."); 86 Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
85 Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (128,128)."); 87 Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
86 Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (0,128)."); 88 Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
87 } 89 }
88 90
89 [Test] 91 [Test]