aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/LandManagement/LandManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/LandManagement/LandManager.cs')
-rw-r--r--OpenSim/Region/Environment/LandManagement/LandManager.cs1234
1 files changed, 617 insertions, 617 deletions
diff --git a/OpenSim/Region/Environment/LandManagement/LandManager.cs b/OpenSim/Region/Environment/LandManagement/LandManager.cs
index 8c359fc..f759934 100644
--- a/OpenSim/Region/Environment/LandManagement/LandManager.cs
+++ b/OpenSim/Region/Environment/LandManagement/LandManager.cs
@@ -1,617 +1,617 @@
1/* 1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/ 2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using libsecondlife; 30using libsecondlife;
31using libsecondlife.Packets; 31using libsecondlife.Packets;
32using OpenSim.Framework.Interfaces; 32using OpenSim.Framework.Interfaces;
33using OpenSim.Framework.Types; 33using OpenSim.Framework.Types;
34using OpenSim.Region.Environment.Scenes; 34using OpenSim.Region.Environment.Scenes;
35 35
36namespace OpenSim.Region.Environment.LandManagement 36namespace OpenSim.Region.Environment.LandManagement
37{ 37{
38 38
39 39
40 #region LandManager Class 40 #region LandManager Class
41 /// <summary> 41 /// <summary>
42 /// Handles Land objects and operations requiring information from other Land objects (divide, join, etc) 42 /// Handles Land objects and operations requiring information from other Land objects (divide, join, etc)
43 /// </summary> 43 /// </summary>
44 public class LandManager : ILocalStorageLandObjectReceiver 44 public class LandManager : ILocalStorageLandObjectReceiver
45 { 45 {
46 46
47 #region Constants 47 #region Constants
48 //Land types set with flags in ParcelOverlay. 48 //Land types set with flags in ParcelOverlay.
49 //Only one of these can be used. 49 //Only one of these can be used.
50 public const byte LAND_TYPE_PUBLIC = (byte)0; //Equals 00000000 50 public const byte LAND_TYPE_PUBLIC = (byte)0; //Equals 00000000
51 public const byte LAND_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001 51 public const byte LAND_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001
52 public const byte LAND_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010 52 public const byte LAND_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010
53 public const byte LAND_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011 53 public const byte LAND_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011
54 public const byte LAND_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100 54 public const byte LAND_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100
55 public const byte LAND_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101 55 public const byte LAND_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101
56 56
57 57
58 //Flags that when set, a border on the given side will be placed 58 //Flags that when set, a border on the given side will be placed
59 //NOTE: North and East is assumable by the west and south sides (if land to east has a west border, then I have an east border; etc) 59 //NOTE: North and East is assumable by the west and south sides (if land to east has a west border, then I have an east border; etc)
60 //This took forever to figure out -- jeesh. /blame LL for even having to send these 60 //This took forever to figure out -- jeesh. /blame LL for even having to send these
61 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000 61 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000
62 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000 62 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000
63 63
64 //RequestResults (I think these are right, they seem to work): 64 //RequestResults (I think these are right, they seem to work):
65 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land 65 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
66 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land 66 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
67 67
68 //ParcelSelectObjects 68 //ParcelSelectObjects
69 public const int LAND_SELECT_OBJECTS_OWNER = 2; 69 public const int LAND_SELECT_OBJECTS_OWNER = 2;
70 public const int LAND_SELECT_OBJECTS_GROUP = 4; 70 public const int LAND_SELECT_OBJECTS_GROUP = 4;
71 public const int LAND_SELECT_OBJECTS_OTHER = 8; 71 public const int LAND_SELECT_OBJECTS_OTHER = 8;
72 72
73 73
74 //These are other constants. Yay! 74 //These are other constants. Yay!
75 public const int START_LAND_LOCAL_ID = 1; 75 public const int START_LAND_LOCAL_ID = 1;
76 #endregion 76 #endregion
77 77
78 #region Member Variables 78 #region Member Variables
79 public Dictionary<int, Land> landList = new Dictionary<int, Land>(); 79 public Dictionary<int, Land> landList = new Dictionary<int, Land>();
80 private int lastLandLocalID = START_LAND_LOCAL_ID - 1; 80 private int lastLandLocalID = START_LAND_LOCAL_ID - 1;
81 private int[,] landIDList = new int[64, 64]; 81 private int[,] landIDList = new int[64, 64];
82 82
83 /// <summary> 83 /// <summary>
84 /// Set to true when a prim is moved, created, added. Performs a prim count update 84 /// Set to true when a prim is moved, created, added. Performs a prim count update
85 /// </summary> 85 /// </summary>
86 public bool landPrimCountTainted = false; 86 public bool landPrimCountTainted = false;
87 87
88 private Scene m_scene; 88 private Scene m_scene;
89 private RegionInfo m_regInfo; 89 private RegionInfo m_regInfo;
90 90
91 #endregion 91 #endregion
92 92
93 #region Constructors 93 #region Constructors
94 public LandManager(Scene scene, RegionInfo reginfo) 94 public LandManager(Scene scene, RegionInfo reginfo)
95 { 95 {
96 96
97 m_scene = scene; 97 m_scene = scene;
98 m_regInfo = reginfo; 98 m_regInfo = reginfo;
99 landIDList.Initialize(); 99 landIDList.Initialize();
100 100
101 } 101 }
102 #endregion 102 #endregion
103 103
104 #region Member Functions 104 #region Member Functions
105 105
106 #region Parcel From Storage Functions 106 #region Parcel From Storage Functions
107 public void LandFromStorage(LandData data) 107 public void LandFromStorage(LandData data)
108 { 108 {
109 Land new_land = new Land(data.ownerID, data.isGroupOwned, m_scene); 109 Land new_land = new Land(data.ownerID, data.isGroupOwned, m_scene);
110 new_land.landData = data.Copy(); 110 new_land.landData = data.Copy();
111 new_land.setLandBitmapFromByteArray(); 111 new_land.setLandBitmapFromByteArray();
112 addLandObject(new_land); 112 addLandObject(new_land);
113 113
114 } 114 }
115 115
116 public void NoLandDataFromStorage() 116 public void NoLandDataFromStorage()
117 { 117 {
118 resetSimLandObjects(); 118 resetSimLandObjects();
119 } 119 }
120 #endregion 120 #endregion
121 121
122 #region Parcel Add/Remove/Get/Create 122 #region Parcel Add/Remove/Get/Create
123 /// <summary> 123 /// <summary>
124 /// Creates a basic Parcel object without an owner (a zeroed key) 124 /// Creates a basic Parcel object without an owner (a zeroed key)
125 /// </summary> 125 /// </summary>
126 /// <returns></returns> 126 /// <returns></returns>
127 public Land createBaseLand() 127 public Land createBaseLand()
128 { 128 {
129 return new Land(new LLUUID(), false, m_scene); 129 return new Land(new LLUUID(), false, m_scene);
130 } 130 }
131 131
132 /// <summary> 132 /// <summary>
133 /// Adds a land object to the stored list and adds them to the landIDList to what they own 133 /// Adds a land object to the stored list and adds them to the landIDList to what they own
134 /// </summary> 134 /// </summary>
135 /// <param name="new_land">The land object being added</param> 135 /// <param name="new_land">The land object being added</param>
136 public Land addLandObject(Land new_land) 136 public Land addLandObject(Land new_land)
137 { 137 {
138 lastLandLocalID++; 138 lastLandLocalID++;
139 new_land.landData.localID = lastLandLocalID; 139 new_land.landData.localID = lastLandLocalID;
140 landList.Add(lastLandLocalID, new_land.Copy()); 140 landList.Add(lastLandLocalID, new_land.Copy());
141 141
142 142
143 bool[,] landBitmap = new_land.getLandBitmap(); 143 bool[,] landBitmap = new_land.getLandBitmap();
144 int x, y; 144 int x, y;
145 for (x = 0; x < 64; x++) 145 for (x = 0; x < 64; x++)
146 { 146 {
147 for (y = 0; y < 64; y++) 147 for (y = 0; y < 64; y++)
148 { 148 {
149 if (landBitmap[x, y]) 149 if (landBitmap[x, y])
150 { 150 {
151 landIDList[x, y] = lastLandLocalID; 151 landIDList[x, y] = lastLandLocalID;
152 } 152 }
153 } 153 }
154 } 154 }
155 landList[lastLandLocalID].forceUpdateLandInfo(); 155 landList[lastLandLocalID].forceUpdateLandInfo();
156 156
157 return new_land; 157 return new_land;
158 158
159 } 159 }
160 /// <summary> 160 /// <summary>
161 /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList 161 /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
162 /// </summary> 162 /// </summary>
163 /// <param name="local_id">Land.localID of the peice of land to remove.</param> 163 /// <param name="local_id">Land.localID of the peice of land to remove.</param>
164 public void removeLandObject(int local_id) 164 public void removeLandObject(int local_id)
165 { 165 {
166 int x, y; 166 int x, y;
167 for (x = 0; x < 64; x++) 167 for (x = 0; x < 64; x++)
168 { 168 {
169 for (y = 0; y < 64; y++) 169 for (y = 0; y < 64; y++)
170 { 170 {
171 if (landIDList[x, y] == local_id) 171 if (landIDList[x, y] == local_id)
172 { 172 {
173 throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); 173 throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
174 } 174 }
175 } 175 }
176 } 176 }
177 // TODO: Put event here for storage manager to bind to. 177 // TODO: Put event here for storage manager to bind to.
178 landList.Remove(local_id); 178 landList.Remove(local_id);
179 } 179 }
180 180
181 private void performFinalLandJoin(Land master, Land slave) 181 private void performFinalLandJoin(Land master, Land slave)
182 { 182 {
183 int x, y; 183 int x, y;
184 bool[,] landBitmapSlave = slave.getLandBitmap(); 184 bool[,] landBitmapSlave = slave.getLandBitmap();
185 for (x = 0; x < 64; x++) 185 for (x = 0; x < 64; x++)
186 { 186 {
187 for (y = 0; y < 64; y++) 187 for (y = 0; y < 64; y++)
188 { 188 {
189 if (landBitmapSlave[x, y]) 189 if (landBitmapSlave[x, y])
190 { 190 {
191 landIDList[x, y] = master.landData.localID; 191 landIDList[x, y] = master.landData.localID;
192 } 192 }
193 } 193 }
194 } 194 }
195 removeLandObject(slave.landData.localID); 195 removeLandObject(slave.landData.localID);
196 } 196 }
197 /// <summary> 197 /// <summary>
198 /// Get the land object at the specified point 198 /// Get the land object at the specified point
199 /// </summary> 199 /// </summary>
200 /// <param name="x">Value between 0 - 256 on the x axis of the point</param> 200 /// <param name="x">Value between 0 - 256 on the x axis of the point</param>
201 /// <param name="y">Value between 0 - 256 on the y axis of the point</param> 201 /// <param name="y">Value between 0 - 256 on the y axis of the point</param>
202 /// <returns>Land object at the point supplied</returns> 202 /// <returns>Land object at the point supplied</returns>
203 public Land getLandObject(float x_float, float y_float) 203 public Land getLandObject(float x_float, float y_float)
204 { 204 {
205 int x = Convert.ToInt32(Math.Floor(Convert.ToDecimal(x_float) / Convert.ToDecimal(4.0))); 205 int x = Convert.ToInt32(Math.Floor(Convert.ToDecimal(x_float) / Convert.ToDecimal(4.0)));
206 int y = Convert.ToInt32(Math.Floor(Convert.ToDecimal(y_float) / Convert.ToDecimal(4.0))); 206 int y = Convert.ToInt32(Math.Floor(Convert.ToDecimal(y_float) / Convert.ToDecimal(4.0)));
207 207
208 if (x > 63 || y > 63 || x < 0 || y < 0) 208 if (x > 63 || y > 63 || x < 0 || y < 0)
209 { 209 {
210 throw new Exception("Error: Parcel not found at point " + x + ", " + y); 210 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
211 } 211 }
212 else 212 else
213 { 213 {
214 // Console.WriteLine("Point (" + x + ", " + y + ") determined from point (" + x_float + ", " + y_float + ")"); 214 // Console.WriteLine("Point (" + x + ", " + y + ") determined from point (" + x_float + ", " + y_float + ")");
215 return landList[landIDList[x, y]]; 215 return landList[landIDList[x, y]];
216 } 216 }
217 } 217 }
218 218
219 public Land getLandObject(int x, int y) 219 public Land getLandObject(int x, int y)
220 { 220 {
221 if (x > 256 || y > 256 || x < 0 || y < 0) 221 if (x > 256 || y > 256 || x < 0 || y < 0)
222 { 222 {
223 throw new Exception("Error: Parcel not found at point " + x + ", " + y); 223 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
224 } 224 }
225 else 225 else
226 { 226 {
227 return landList[landIDList[x / 4, y / 4]]; 227 return landList[landIDList[x / 4, y / 4]];
228 } 228 }
229 } 229 }
230 #endregion 230 #endregion
231 231
232 #region Parcel Modification 232 #region Parcel Modification
233 /// <summary> 233 /// <summary>
234 /// Subdivides a piece of land 234 /// Subdivides a piece of land
235 /// </summary> 235 /// </summary>
236 /// <param name="start_x">West Point</param> 236 /// <param name="start_x">West Point</param>
237 /// <param name="start_y">South Point</param> 237 /// <param name="start_y">South Point</param>
238 /// <param name="end_x">East Point</param> 238 /// <param name="end_x">East Point</param>
239 /// <param name="end_y">North Point</param> 239 /// <param name="end_y">North Point</param>
240 /// <param name="attempting_user_id">LLUUID of user who is trying to subdivide</param> 240 /// <param name="attempting_user_id">LLUUID of user who is trying to subdivide</param>
241 /// <returns>Returns true if successful</returns> 241 /// <returns>Returns true if successful</returns>
242 private bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) 242 private bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
243 { 243 {
244 244
245 //First, lets loop through the points and make sure they are all in the same peice of land 245 //First, lets loop through the points and make sure they are all in the same peice of land
246 //Get the land object at start 246 //Get the land object at start
247 Land startLandObject = getLandObject(start_x, start_y); 247 Land startLandObject = getLandObject(start_x, start_y);
248 if (startLandObject == null) return false; //No such land object at the beginning 248 if (startLandObject == null) return false; //No such land object at the beginning
249 249
250 //Loop through the points 250 //Loop through the points
251 try 251 try
252 { 252 {
253 int totalX = end_x - start_x; 253 int totalX = end_x - start_x;
254 int totalY = end_y - start_y; 254 int totalY = end_y - start_y;
255 int x, y; 255 int x, y;
256 for (y = 0; y < totalY; y++) 256 for (y = 0; y < totalY; y++)
257 { 257 {
258 for (x = 0; x < totalX; x++) 258 for (x = 0; x < totalX; x++)
259 { 259 {
260 Land tempLandObject = getLandObject(start_x + x, start_y + y); 260 Land tempLandObject = getLandObject(start_x + x, start_y + y);
261 if (tempLandObject == null) return false; //No such land object at that point 261 if (tempLandObject == null) return false; //No such land object at that point
262 if (tempLandObject != startLandObject) return false; //Subdividing over 2 land objects; no-no 262 if (tempLandObject != startLandObject) return false; //Subdividing over 2 land objects; no-no
263 } 263 }
264 } 264 }
265 } 265 }
266 catch (Exception) 266 catch (Exception)
267 { 267 {
268 return false; //Exception. For now, lets skip subdivision 268 return false; //Exception. For now, lets skip subdivision
269 } 269 }
270 270
271 //If we are still here, then they are subdividing within one piece of land 271 //If we are still here, then they are subdividing within one piece of land
272 //Check owner 272 //Check owner
273 if (startLandObject.landData.ownerID != attempting_user_id) 273 if (startLandObject.landData.ownerID != attempting_user_id)
274 { 274 {
275 return false; //They cant do this! 275 return false; //They cant do this!
276 } 276 }
277 277
278 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) 278 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
279 Land newLand = startLandObject.Copy(); 279 Land newLand = startLandObject.Copy();
280 newLand.landData.landName = "Subdivision of " + newLand.landData.landName; 280 newLand.landData.landName = "Subdivision of " + newLand.landData.landName;
281 newLand.landData.globalID = LLUUID.Random(); 281 newLand.landData.globalID = LLUUID.Random();
282 282
283 newLand.setLandBitmap(Land.getSquareLandBitmap(start_x, start_y, end_x, end_y)); 283 newLand.setLandBitmap(Land.getSquareLandBitmap(start_x, start_y, end_x, end_y));
284 284
285 //Now, lets set the subdivision area of the original to false 285 //Now, lets set the subdivision area of the original to false
286 int startLandObjectIndex = startLandObject.landData.localID; 286 int startLandObjectIndex = startLandObject.landData.localID;
287 landList[startLandObjectIndex].setLandBitmap(Land.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false)); 287 landList[startLandObjectIndex].setLandBitmap(Land.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false));
288 landList[startLandObjectIndex].forceUpdateLandInfo(); 288 landList[startLandObjectIndex].forceUpdateLandInfo();
289 289
290 290
291 this.setPrimsTainted(); 291 this.setPrimsTainted();
292 292
293 //Now add the new land object 293 //Now add the new land object
294 Land result = addLandObject(newLand); 294 Land result = addLandObject(newLand);
295 result.sendLandUpdateToAvatarsOverMe(); 295 result.sendLandUpdateToAvatarsOverMe();
296 296
297 297
298 298
299 299
300 return true; 300 return true;
301 } 301 }
302 /// <summary> 302 /// <summary>
303 /// Join 2 land objects together 303 /// Join 2 land objects together
304 /// </summary> 304 /// </summary>
305 /// <param name="start_x">x value in first piece of land</param> 305 /// <param name="start_x">x value in first piece of land</param>
306 /// <param name="start_y">y value in first piece of land</param> 306 /// <param name="start_y">y value in first piece of land</param>
307 /// <param name="end_x">x value in second peice of land</param> 307 /// <param name="end_x">x value in second peice of land</param>
308 /// <param name="end_y">y value in second peice of land</param> 308 /// <param name="end_y">y value in second peice of land</param>
309 /// <param name="attempting_user_id">LLUUID of the avatar trying to join the land objects</param> 309 /// <param name="attempting_user_id">LLUUID of the avatar trying to join the land objects</param>
310 /// <returns>Returns true if successful</returns> 310 /// <returns>Returns true if successful</returns>
311 private bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) 311 private bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
312 { 312 {
313 end_x -= 4; 313 end_x -= 4;
314 end_y -= 4; 314 end_y -= 4;
315 315
316 List<Land> selectedLandObjects = new List<Land>(); 316 List<Land> selectedLandObjects = new List<Land>();
317 int stepXSelected = 0; 317 int stepXSelected = 0;
318 int stepYSelected = 0; 318 int stepYSelected = 0;
319 for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) 319 for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
320 { 320 {
321 for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) 321 for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
322 { 322 {
323 Land p = getLandObject(stepXSelected,stepYSelected); 323 Land p = getLandObject(stepXSelected,stepYSelected);
324 if (!selectedLandObjects.Contains(p)) 324 if (!selectedLandObjects.Contains(p))
325 { 325 {
326 selectedLandObjects.Add(p); 326 selectedLandObjects.Add(p);
327 } 327 }
328 } 328 }
329 } 329 }
330 Land masterLandObject = selectedLandObjects[0]; 330 Land masterLandObject = selectedLandObjects[0];
331 selectedLandObjects.RemoveAt(0); 331 selectedLandObjects.RemoveAt(0);
332 332
333 333
334 if (selectedLandObjects.Count < 1) 334 if (selectedLandObjects.Count < 1)
335 { 335 {
336 return false; //Only one piece of land selected 336 return false; //Only one piece of land selected
337 } 337 }
338 if (masterLandObject.landData.ownerID != attempting_user_id) 338 if (masterLandObject.landData.ownerID != attempting_user_id)
339 { 339 {
340 return false; //Not the same owner 340 return false; //Not the same owner
341 } 341 }
342 foreach (Land p in selectedLandObjects) 342 foreach (Land p in selectedLandObjects)
343 { 343 {
344 if (p.landData.ownerID != masterLandObject.landData.ownerID) 344 if (p.landData.ownerID != masterLandObject.landData.ownerID)
345 { 345 {
346 return false; //Over multiple users. TODO: make this just ignore this piece of land? 346 return false; //Over multiple users. TODO: make this just ignore this piece of land?
347 } 347 }
348 } 348 }
349 foreach (Land slaveLandObject in selectedLandObjects) 349 foreach (Land slaveLandObject in selectedLandObjects)
350 { 350 {
351 landList[masterLandObject.landData.localID].setLandBitmap(Land.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap())); 351 landList[masterLandObject.landData.localID].setLandBitmap(Land.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap()));
352 performFinalLandJoin(masterLandObject, slaveLandObject); 352 performFinalLandJoin(masterLandObject, slaveLandObject);
353 } 353 }
354 354
355 355
356 this.setPrimsTainted(); 356 this.setPrimsTainted();
357 357
358 masterLandObject.sendLandUpdateToAvatarsOverMe(); 358 masterLandObject.sendLandUpdateToAvatarsOverMe();
359 359
360 return true; 360 return true;
361 361
362 362
363 363
364 } 364 }
365 #endregion 365 #endregion
366 366
367 #region Parcel Updating 367 #region Parcel Updating
368 /// <summary> 368 /// <summary>
369 /// Where we send the ParcelOverlay packet to the client 369 /// Where we send the ParcelOverlay packet to the client
370 /// </summary> 370 /// </summary>
371 /// <param name="remote_client">The object representing the client</param> 371 /// <param name="remote_client">The object representing the client</param>
372 public void sendParcelOverlay(IClientAPI remote_client) 372 public void sendParcelOverlay(IClientAPI remote_client)
373 { 373 {
374 const int LAND_BLOCKS_PER_PACKET = 1024; 374 const int LAND_BLOCKS_PER_PACKET = 1024;
375 int x, y = 0; 375 int x, y = 0;
376 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 376 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
377 int byteArrayCount = 0; 377 int byteArrayCount = 0;
378 int sequenceID = 0; 378 int sequenceID = 0;
379 ParcelOverlayPacket packet; 379 ParcelOverlayPacket packet;
380 380
381 for (y = 0; y < 64; y++) 381 for (y = 0; y < 64; y++)
382 { 382 {
383 for (x = 0; x < 64; x++) 383 for (x = 0; x < 64; x++)
384 { 384 {
385 byte tempByte = (byte)0; //This represents the byte for the current 4x4 385 byte tempByte = (byte)0; //This represents the byte for the current 4x4
386 Land currentParcelBlock = getLandObject(x * 4, y * 4); 386 Land currentParcelBlock = getLandObject(x * 4, y * 4);
387 387
388 if (currentParcelBlock.landData.ownerID == remote_client.AgentId) 388 if (currentParcelBlock.landData.ownerID == remote_client.AgentId)
389 { 389 {
390 //Owner Flag 390 //Owner Flag
391 tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_REQUESTER); 391 tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_REQUESTER);
392 } 392 }
393 else if (currentParcelBlock.landData.salePrice > 0 && (currentParcelBlock.landData.authBuyerID == LLUUID.Zero || currentParcelBlock.landData.authBuyerID == remote_client.AgentId)) 393 else if (currentParcelBlock.landData.salePrice > 0 && (currentParcelBlock.landData.authBuyerID == LLUUID.Zero || currentParcelBlock.landData.authBuyerID == remote_client.AgentId))
394 { 394 {
395 //Sale Flag 395 //Sale Flag
396 tempByte = Convert.ToByte(tempByte | LAND_TYPE_IS_FOR_SALE); 396 tempByte = Convert.ToByte(tempByte | LAND_TYPE_IS_FOR_SALE);
397 } 397 }
398 else if (currentParcelBlock.landData.ownerID == LLUUID.Zero) 398 else if (currentParcelBlock.landData.ownerID == LLUUID.Zero)
399 { 399 {
400 //Public Flag 400 //Public Flag
401 tempByte = Convert.ToByte(tempByte | LAND_TYPE_PUBLIC); 401 tempByte = Convert.ToByte(tempByte | LAND_TYPE_PUBLIC);
402 } 402 }
403 else 403 else
404 { 404 {
405 //Other Flag 405 //Other Flag
406 tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_OTHER); 406 tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_OTHER);
407 } 407 }
408 408
409 409
410 //Now for border control 410 //Now for border control
411 if (x == 0) 411 if (x == 0)
412 { 412 {
413 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST); 413 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST);
414 } 414 }
415 else if (getLandObject((x - 1) * 4, y * 4) != currentParcelBlock) 415 else if (getLandObject((x - 1) * 4, y * 4) != currentParcelBlock)
416 { 416 {
417 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST); 417 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST);
418 } 418 }
419 419
420 if (y == 0) 420 if (y == 0)
421 { 421 {
422 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH); 422 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH);
423 } 423 }
424 else if (getLandObject(x * 4, (y - 1) * 4) != currentParcelBlock) 424 else if (getLandObject(x * 4, (y - 1) * 4) != currentParcelBlock)
425 { 425 {
426 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH); 426 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH);
427 } 427 }
428 428
429 byteArray[byteArrayCount] = tempByte; 429 byteArray[byteArrayCount] = tempByte;
430 byteArrayCount++; 430 byteArrayCount++;
431 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) 431 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
432 { 432 {
433 byteArrayCount = 0; 433 byteArrayCount = 0;
434 packet = new ParcelOverlayPacket(); 434 packet = new ParcelOverlayPacket();
435 packet.ParcelData.Data = byteArray; 435 packet.ParcelData.Data = byteArray;
436 packet.ParcelData.SequenceID = sequenceID; 436 packet.ParcelData.SequenceID = sequenceID;
437 remote_client.OutPacket((Packet)packet); 437 remote_client.OutPacket((Packet)packet);
438 sequenceID++; 438 sequenceID++;
439 byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 439 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
440 } 440 }
441 } 441 }
442 } 442 }
443 443
444 444
445 } 445 }
446 446
447 public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, IClientAPI remote_client) 447 public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, IClientAPI remote_client)
448 { 448 {
449 //Get the land objects within the bounds 449 //Get the land objects within the bounds
450 List<Land> temp = new List<Land>(); 450 List<Land> temp = new List<Land>();
451 int x, y, i; 451 int x, y, i;
452 int inc_x = end_x - start_x; 452 int inc_x = end_x - start_x;
453 int inc_y = end_y - start_y; 453 int inc_y = end_y - start_y;
454 for (x = 0; x < inc_x; x++) 454 for (x = 0; x < inc_x; x++)
455 { 455 {
456 for (y = 0; y < inc_y; y++) 456 for (y = 0; y < inc_y; y++)
457 { 457 {
458 Land currentParcel = getLandObject(start_x + x, start_y + y); 458 Land currentParcel = getLandObject(start_x + x, start_y + y);
459 if (!temp.Contains(currentParcel)) 459 if (!temp.Contains(currentParcel))
460 { 460 {
461 currentParcel.forceUpdateLandInfo(); 461 currentParcel.forceUpdateLandInfo();
462 temp.Add(currentParcel); 462 temp.Add(currentParcel);
463 } 463 }
464 } 464 }
465 } 465 }
466 466
467 int requestResult = LAND_RESULT_SINGLE; 467 int requestResult = LAND_RESULT_SINGLE;
468 if (temp.Count > 1) 468 if (temp.Count > 1)
469 { 469 {
470 requestResult = LAND_RESULT_MULTIPLE; 470 requestResult = LAND_RESULT_MULTIPLE;
471 } 471 }
472 472
473 for (i = 0; i < temp.Count; i++) 473 for (i = 0; i < temp.Count; i++)
474 { 474 {
475 temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 475 temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
476 } 476 }
477 477
478 478
479 sendParcelOverlay(remote_client); 479 sendParcelOverlay(remote_client);
480 } 480 }
481 481
482 public void handleParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client) 482 public void handleParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client)
483 { 483 {
484 if (landList.ContainsKey(packet.ParcelData.LocalID)) 484 if (landList.ContainsKey(packet.ParcelData.LocalID))
485 { 485 {
486 landList[packet.ParcelData.LocalID].updateLandProperties(packet, remote_client); 486 landList[packet.ParcelData.LocalID].updateLandProperties(packet, remote_client);
487 } 487 }
488 } 488 }
489 public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) 489 public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
490 { 490 {
491 subdivide(west, south, east, north, remote_client.AgentId); 491 subdivide(west, south, east, north, remote_client.AgentId);
492 } 492 }
493 public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) 493 public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
494 { 494 {
495 join(west, south, east, north, remote_client.AgentId); 495 join(west, south, east, north, remote_client.AgentId);
496 496
497 } 497 }
498 498
499 public void handleParcelSelectObjectsRequest(int local_id, int request_type, IClientAPI remote_client) 499 public void handleParcelSelectObjectsRequest(int local_id, int request_type, IClientAPI remote_client)
500 { 500 {
501 landList[local_id].sendForceObjectSelect(local_id, request_type, remote_client); 501 landList[local_id].sendForceObjectSelect(local_id, request_type, remote_client);
502 } 502 }
503 503
504 public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client) 504 public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client)
505 { 505 {
506 landList[local_id].sendLandObjectOwners(remote_client); 506 landList[local_id].sendLandObjectOwners(remote_client);
507 } 507 }
508 #endregion 508 #endregion
509 509
510 /// <summary> 510 /// <summary>
511 /// Resets the sim to the default land object (full sim piece of land owned by the default user) 511 /// Resets the sim to the default land object (full sim piece of land owned by the default user)
512 /// </summary> 512 /// </summary>
513 public void resetSimLandObjects() 513 public void resetSimLandObjects()
514 { 514 {
515 //Remove all the land objects in the sim and add a blank, full sim land object set to public 515 //Remove all the land objects in the sim and add a blank, full sim land object set to public
516 landList.Clear(); 516 landList.Clear();
517 lastLandLocalID = START_LAND_LOCAL_ID - 1; 517 lastLandLocalID = START_LAND_LOCAL_ID - 1;
518 landIDList.Initialize(); 518 landIDList.Initialize();
519 519
520 Land fullSimParcel = new Land(LLUUID.Zero, false, m_scene); 520 Land fullSimParcel = new Land(LLUUID.Zero, false, m_scene);
521 521
522 fullSimParcel.setLandBitmap(Land.getSquareLandBitmap(0, 0, 256, 256)); 522 fullSimParcel.setLandBitmap(Land.getSquareLandBitmap(0, 0, 256, 256));
523 fullSimParcel.landData.ownerID = m_regInfo.MasterAvatarAssignedUUID; 523 fullSimParcel.landData.ownerID = m_regInfo.MasterAvatarAssignedUUID;
524 524
525 addLandObject(fullSimParcel); 525 addLandObject(fullSimParcel);
526 526
527 } 527 }
528 528
529 529
530 public void handleSignificantClientMovement(IClientAPI remote_client) 530 public void handleSignificantClientMovement(IClientAPI remote_client)
531 { 531 {
532 ScenePresence clientAvatar = m_scene.RequestAvatar(remote_client.AgentId); 532 ScenePresence clientAvatar = m_scene.RequestAvatar(remote_client.AgentId);
533 if (clientAvatar != null) 533 if (clientAvatar != null)
534 { 534 {
535 Land over = getLandObject(clientAvatar.Pos.X,clientAvatar.Pos.Y); 535 Land over = getLandObject(clientAvatar.Pos.X,clientAvatar.Pos.Y);
536 if (over != null) 536 if (over != null)
537 { 537 {
538 over.sendLandProperties(0, false, 0, remote_client); 538 over.sendLandProperties(0, false, 0, remote_client);
539 } 539 }
540 } 540 }
541 } 541 }
542 542
543 public void resetAllLandPrimCounts() 543 public void resetAllLandPrimCounts()
544 { 544 {
545 foreach (Land p in landList.Values) 545 foreach (Land p in landList.Values)
546 { 546 {
547 p.resetLandPrimCounts(); 547 p.resetLandPrimCounts();
548 } 548 }
549 } 549 }
550 public void setPrimsTainted() 550 public void setPrimsTainted()
551 { 551 {
552 this.landPrimCountTainted = true; 552 this.landPrimCountTainted = true;
553 } 553 }
554 554
555 public void addPrimToLandPrimCounts(SceneObject obj) 555 public void addPrimToLandPrimCounts(SceneObject obj)
556 { 556 {
557 LLVector3 position = obj.Pos; 557 LLVector3 position = obj.Pos;
558 Land landUnderPrim = getLandObject(position.X, position.Y); 558 Land landUnderPrim = getLandObject(position.X, position.Y);
559 if (landUnderPrim != null) 559 if (landUnderPrim != null)
560 { 560 {
561 landUnderPrim.addPrimToCount(obj); 561 landUnderPrim.addPrimToCount(obj);
562 } 562 }
563 } 563 }
564 564
565 public void removePrimFromLandPrimCounts(SceneObject obj) 565 public void removePrimFromLandPrimCounts(SceneObject obj)
566 { 566 {
567 foreach (Land p in landList.Values) 567 foreach (Land p in landList.Values)
568 { 568 {
569 p.removePrimFromCount(obj); 569 p.removePrimFromCount(obj);
570 } 570 }
571 } 571 }
572 572
573 public void finalizeLandPrimCountUpdate() 573 public void finalizeLandPrimCountUpdate()
574 { 574 {
575 //Get Simwide prim count for owner 575 //Get Simwide prim count for owner
576 Dictionary<LLUUID, List<Land>> landOwnersAndParcels = new Dictionary<LLUUID,List<Land>>(); 576 Dictionary<LLUUID, List<Land>> landOwnersAndParcels = new Dictionary<LLUUID,List<Land>>();
577 foreach (Land p in landList.Values) 577 foreach (Land p in landList.Values)
578 { 578 {
579 if(!landOwnersAndParcels.ContainsKey(p.landData.ownerID)) 579 if(!landOwnersAndParcels.ContainsKey(p.landData.ownerID))
580 { 580 {
581 List<Land> tempList = new List<Land>(); 581 List<Land> tempList = new List<Land>();
582 tempList.Add(p); 582 tempList.Add(p);
583 landOwnersAndParcels.Add(p.landData.ownerID,tempList); 583 landOwnersAndParcels.Add(p.landData.ownerID,tempList);
584 } 584 }
585 else 585 else
586 { 586 {
587 landOwnersAndParcels[p.landData.ownerID].Add(p); 587 landOwnersAndParcels[p.landData.ownerID].Add(p);
588 } 588 }
589 } 589 }
590 590
591 foreach (LLUUID owner in landOwnersAndParcels.Keys) 591 foreach (LLUUID owner in landOwnersAndParcels.Keys)
592 { 592 {
593 int simArea = 0; 593 int simArea = 0;
594 int simPrims = 0; 594 int simPrims = 0;
595 foreach (Land p in landOwnersAndParcels[owner]) 595 foreach (Land p in landOwnersAndParcels[owner])
596 { 596 {
597 simArea += p.landData.area; 597 simArea += p.landData.area;
598 simPrims += p.landData.ownerPrims + p.landData.otherPrims + p.landData.groupPrims + p.landData.selectedPrims; 598 simPrims += p.landData.ownerPrims + p.landData.otherPrims + p.landData.groupPrims + p.landData.selectedPrims;
599 } 599 }
600 600
601 foreach (Land p in landOwnersAndParcels[owner]) 601 foreach (Land p in landOwnersAndParcels[owner])
602 { 602 {
603 p.landData.simwideArea = simArea; 603 p.landData.simwideArea = simArea;
604 p.landData.simwidePrims = simPrims; 604 p.landData.simwidePrims = simPrims;
605 } 605 }
606 } 606 }
607 607
608 } 608 }
609 #endregion 609 #endregion
610 } 610 }
611 #endregion 611 #endregion
612 612
613 613
614 614
615 615
616 616
617} 617}