aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Land/LandObject.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Land/LandObject.cs')
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs886
1 files changed, 755 insertions, 131 deletions
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index a0c1b9d..4471432 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -50,15 +50,22 @@ namespace OpenSim.Region.CoreModules.World.Land
50 private readonly int landUnit = 4; 50 private readonly int landUnit = 4;
51 51
52 private int m_lastSeqId = 0; 52 private int m_lastSeqId = 0;
53 53 private int m_expiryCounter = 0;
54
54 protected Scene m_scene; 55 protected Scene m_scene;
55 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
56 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
57 58
58 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>(); 59 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
59 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
61 IDwellModule m_dwellModule;
60 62
61 public bool[,] LandBitmap { get; set; } 63 private bool[,] m_landBitmap;
64 public bool[,] LandBitmap
65 {
66 get { return m_landBitmap; }
67 set { m_landBitmap = value; }
68 }
62 69
63 #endregion 70 #endregion
64 71
@@ -69,7 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Land
69 return free; 76 return free;
70 } 77 }
71 78
72 public LandData LandData { get; set; } 79 protected LandData m_landData;
80 public LandData LandData
81 {
82 get { return m_landData; }
83
84 set { m_landData = value; }
85 }
73 86
74 public IPrimCounts PrimCounts { get; set; } 87 public IPrimCounts PrimCounts { get; set; }
75 88
@@ -78,77 +91,230 @@ namespace OpenSim.Region.CoreModules.World.Land
78 get { return m_scene.RegionInfo.RegionID; } 91 get { return m_scene.RegionInfo.RegionID; }
79 } 92 }
80 93
81 public Vector3 StartPoint 94 private Vector2 m_startPoint = Vector2.Zero;
95 private Vector2 m_endPoint = Vector2.Zero;
96 private Vector2 m_centerPoint = Vector2.Zero;
97 private Vector2 m_AABBmin = Vector2.Zero;
98 private Vector2 m_AABBmax = Vector2.Zero;
99
100 public Vector2 StartPoint
82 { 101 {
83 get 102 get
84 { 103 {
85 for (int y = 0; y < LandBitmap.GetLength(1); y++) 104 return m_startPoint;
86 { 105 }
87 for (int x = 0; x < LandBitmap.GetLength(0); x++) 106 }
88 {
89 if (LandBitmap[x, y])
90 return new Vector3(x * landUnit, y * landUnit, 0);
91 }
92 }
93 107
94 m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>", 108 public Vector2 EndPoint
95 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 109 {
96 return new Vector3(-1, -1, -1); 110 get
111 {
112 return m_endPoint;
97 } 113 }
98 } 114 }
99 115
100 public Vector3 EndPoint 116 //estimate a center point of a parcel
117 public Vector2 CenterPoint
101 { 118 {
102 get 119 get
103 { 120 {
104 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--) 121 return m_centerPoint;
122 }
123 }
124
125 public Vector2? GetNearestPoint(Vector3 pos)
126 {
127 Vector3 direction = new Vector3(m_centerPoint.X - pos.X, m_centerPoint.Y - pos.Y, 0f );
128 return GetNearestPointAlongDirection(pos, direction);
129 }
130
131 public Vector2? GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection)
132 {
133 Vector2 testpos;
134 Vector2 direction;
135
136 testpos.X = pos.X / landUnit;
137 testpos.Y = pos.Y / landUnit;
138
139 if(LandBitmap[(int)testpos.X, (int)testpos.Y])
140 return new Vector2(pos.X, pos.Y); // we are already here
141
142 direction.X = pdirection.X;
143 direction.Y = pdirection.Y;
144
145 if(direction.X == 0f && direction.Y == 0f)
146 return null; // we can't look anywhere
147
148 direction.Normalize();
149
150 int minx = (int)(m_AABBmin.X / landUnit);
151 int maxx = (int)(m_AABBmax.X / landUnit);
152
153 // check against AABB
154 if(direction.X > 0f)
155 {
156 if(testpos.X >= maxx)
157 return null; // will never get there
158 if(testpos.X < minx)
159 testpos.X = minx;
160 }
161 else if(direction.X < 0f)
162 {
163 if(testpos.X < minx)
164 return null; // will never get there
165 if(testpos.X >= maxx)
166 testpos.X = maxx - 1;
167 }
168 else
169 {
170 if(testpos.X < minx)
171 return null; // will never get there
172 else if(testpos.X >= maxx)
173 return null; // will never get there
174 }
175
176 int miny = (int)(m_AABBmin.Y / landUnit);
177 int maxy = (int)(m_AABBmax.Y / landUnit);
178
179 if(direction.Y > 0f)
180 {
181 if(testpos.Y >= maxy)
182 return null; // will never get there
183 if(testpos.Y < miny)
184 testpos.Y = miny;
185 }
186 else if(direction.Y < 0f)
187 {
188 if(testpos.Y < miny)
189 return null; // will never get there
190 if(testpos.Y >= maxy)
191 testpos.Y = maxy - 1;
192 }
193 else
194 {
195 if(testpos.Y < miny)
196 return null; // will never get there
197 else if(testpos.Y >= maxy)
198 return null; // will never get there
199 }
200
201 while(!LandBitmap[(int)testpos.X, (int)testpos.Y])
202 {
203 testpos += direction;
204
205 if(testpos.X < minx)
206 return null;
207 if (testpos.X >= maxx)
208 return null;
209 if(testpos.Y < miny)
210 return null;
211 if (testpos.Y >= maxy)
212 return null;
213 }
214
215 testpos *= landUnit;
216 float ftmp;
217
218 if(Math.Abs(direction.X) > Math.Abs(direction.Y))
219 {
220 if(direction.X < 0)
221 testpos.X += landUnit - 0.5f;
222 else
223 testpos.X += 0.5f;
224 ftmp = testpos.X - pos.X;
225 ftmp /= direction.X;
226 ftmp = Math.Abs(ftmp);
227 ftmp *= direction.Y;
228 ftmp += pos.Y;
229
230 if(ftmp < testpos.Y + .5f)
231 ftmp = testpos.Y + .5f;
232 else
105 { 233 {
106 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--) 234 testpos.Y += landUnit - 0.5f;
107 { 235 if(ftmp > testpos.Y)
108 if (LandBitmap[x, y]) 236 ftmp = testpos.Y;
109 {
110 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
111 }
112 }
113 } 237 }
114 238 testpos.Y = ftmp;
115 m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>", 239 }
116 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 240 else
117 return new Vector3(-1, -1, -1); 241 {
242 if(direction.Y < 0)
243 testpos.Y += landUnit - 0.5f;
244 else
245 testpos.Y += 0.5f;
246 ftmp = testpos.Y - pos.Y;
247 ftmp /= direction.Y;
248 ftmp = Math.Abs(ftmp);
249 ftmp *= direction.X;
250 ftmp += pos.X;
251
252 if(ftmp < testpos.X + .5f)
253 ftmp = testpos.X + .5f;
254 else
255 {
256 testpos.X += landUnit - 0.5f;
257 if(ftmp > testpos.X)
258 ftmp = testpos.X;
259 }
260 testpos.X = ftmp;
118 } 261 }
262 return testpos;
119 } 263 }
120 264
265
121 #region Constructors 266 #region Constructors
122 267
123 public LandObject(LandData landData, Scene scene) 268 public LandObject(LandData landData, Scene scene)
124 { 269 {
125 LandData = landData.Copy(); 270 LandData = landData.Copy();
126 m_scene = scene; 271 m_scene = scene;
272 m_scene.EventManager.OnFrame += OnFrame;
273 m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
127 } 274 }
128 275
129 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 276 public LandObject(UUID owner_id, bool is_group_owned, Scene scene, LandData data = null)
130 { 277 {
131 m_scene = scene; 278 m_scene = scene;
132 if (m_scene == null) 279 if (m_scene == null)
133 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit]; 280 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
134 else 281 else
282 {
135 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 283 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
284 m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
285 }
286
287 if(data == null)
288 LandData = new LandData();
289 else
290 LandData = data;
136 291
137 LandData = new LandData();
138 LandData.OwnerID = owner_id; 292 LandData.OwnerID = owner_id;
139 if (is_group_owned) 293 if (is_group_owned)
140 LandData.GroupID = owner_id; 294 LandData.GroupID = owner_id;
141 else 295
142 LandData.GroupID = UUID.Zero;
143 LandData.IsGroupOwned = is_group_owned; 296 LandData.IsGroupOwned = is_group_owned;
297
298 if(m_dwellModule == null)
299 LandData.Dwell = 0;
300
301 m_scene.EventManager.OnFrame += OnFrame;
302 }
303
304 public void Clear()
305 {
306 if(m_scene != null)
307 m_scene.EventManager.OnFrame -= OnFrame;
308 LandData = null;
144 } 309 }
145 310
311
146 #endregion 312 #endregion
147 313
148 #region Member Functions 314 #region Member Functions
149 315
150 #region General Functions 316 #region General Functions
151 317
152 /// <summary> 318 /// <summary>
153 /// Checks to see if this land object contains a point 319 /// Checks to see if this land object contains a point
154 /// </summary> 320 /// </summary>
@@ -195,14 +361,22 @@ namespace OpenSim.Region.CoreModules.World.Land
195 else 361 else
196 { 362 {
197 // Normal Calculations 363 // Normal Calculations
198 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 364 int parcelMax = (int)(
199 * (float)m_scene.RegionInfo.ObjectCapacity 365 (double)LandData.Area
200 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 366 * (double)m_scene.RegionInfo.ObjectCapacity
201 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 367 * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
368 / (double)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
369 + 0.5 );
370
371 if(parcelMax > m_scene.RegionInfo.ObjectCapacity)
372 parcelMax = m_scene.RegionInfo.ObjectCapacity;
373
374 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
202 return parcelMax; 375 return parcelMax;
203 } 376 }
204 } 377 }
205 378
379 // the total prims a parcel owner can have on a region
206 public int GetSimulatorMaxPrimCount() 380 public int GetSimulatorMaxPrimCount()
207 { 381 {
208 if (overrideSimulatorMaxPrimCount != null) 382 if (overrideSimulatorMaxPrimCount != null)
@@ -212,18 +386,34 @@ namespace OpenSim.Region.CoreModules.World.Land
212 else 386 else
213 { 387 {
214 //Normal Calculations 388 //Normal Calculations
215 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 389 int simMax = (int)( (double)LandData.SimwideArea
216 * (float)m_scene.RegionInfo.ObjectCapacity); 390 * (double)m_scene.RegionInfo.ObjectCapacity
391 * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
392 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
393 +0.5 );
394 // sanity check
395 if(simMax > m_scene.RegionInfo.ObjectCapacity)
396 simMax = m_scene.RegionInfo.ObjectCapacity;
397 //m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}, SimWidePrims {3}",
398 // LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax, LandData.SimwidePrims);
217 return simMax; 399 return simMax;
218 } 400 }
219 } 401 }
220 402
221 #endregion 403 #endregion
222 404
223 #region Packet Request Handling 405 #region Packet Request Handling
224 406
225 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 407 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
226 { 408 {
409 if(m_scene.RegionInfo.RegionSettings.AllowDamage)
410 remote_client.SceneAgent.Invulnerable = false;
411 else
412 remote_client.SceneAgent.Invulnerable = (m_landData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
413
414 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
415 return;
416
227 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 417 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
228 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 418 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
229 uint regionFlags = (uint)(RegionFlags.PublicAllowed 419 uint regionFlags = (uint)(RegionFlags.PublicAllowed
@@ -252,10 +442,11 @@ namespace OpenSim.Region.CoreModules.World.Land
252 GetSimulatorMaxPrimCount(), regionFlags); 442 GetSimulatorMaxPrimCount(), regionFlags);
253 } 443 }
254 444
255 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 445 public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
256 { 446 {
257 //Needs later group support 447 //Needs later group support
258 bool snap_selection = false; 448 snap_selection = false;
449 needOverlay = false;
259 LandData newData = LandData.Copy(); 450 LandData newData = LandData.Copy();
260 451
261 uint allowedDelta = 0; 452 uint allowedDelta = 0;
@@ -264,7 +455,7 @@ namespace OpenSim.Region.CoreModules.World.Land
264 // ParcelFlags.ForSaleObjects 455 // ParcelFlags.ForSaleObjects
265 // ParcelFlags.LindenHome 456 // ParcelFlags.LindenHome
266 457
267 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 458 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, false))
268 { 459 {
269 allowedDelta |= (uint)(ParcelFlags.AllowLandmark | 460 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
270 ParcelFlags.AllowTerraform | 461 ParcelFlags.AllowTerraform |
@@ -277,9 +468,12 @@ namespace OpenSim.Region.CoreModules.World.Land
277 ParcelFlags.AllowAPrimitiveEntry | 468 ParcelFlags.AllowAPrimitiveEntry |
278 ParcelFlags.AllowGroupObjectEntry | 469 ParcelFlags.AllowGroupObjectEntry |
279 ParcelFlags.AllowFly); 470 ParcelFlags.AllowFly);
471 newData.SeeAVs = args.SeeAVs;
472 newData.AnyAVSounds = args.AnyAVSounds;
473 newData.GroupAVSounds = args.GroupAVSounds;
280 } 474 }
281 475
282 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale)) 476 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
283 { 477 {
284 if (args.AuthBuyerID != newData.AuthBuyerID || 478 if (args.AuthBuyerID != newData.AuthBuyerID ||
285 args.SalePrice != newData.SalePrice) 479 args.SalePrice != newData.SalePrice)
@@ -302,30 +496,30 @@ namespace OpenSim.Region.CoreModules.World.Land
302 allowedDelta |= (uint)ParcelFlags.ForSale; 496 allowedDelta |= (uint)ParcelFlags.ForSale;
303 } 497 }
304 498
305 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces)) 499 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces, false))
306 { 500 {
307 newData.Category = args.Category; 501 newData.Category = args.Category;
308 502
309 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 503 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
310 ParcelFlags.AllowPublish | 504 ParcelFlags.AllowPublish |
311 ParcelFlags.MaturePublish); 505 ParcelFlags.MaturePublish) | (uint)(1 << 23);
312 } 506 }
313 507
314 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 508 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity, false))
315 { 509 {
316 newData.Description = args.Desc; 510 newData.Description = args.Desc;
317 newData.Name = args.Name; 511 newData.Name = args.Name;
318 newData.SnapshotID = args.SnapshotID; 512 newData.SnapshotID = args.SnapshotID;
319 } 513 }
320 514
321 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint)) 515 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint, false))
322 { 516 {
323 newData.LandingType = args.LandingType; 517 newData.LandingType = args.LandingType;
324 newData.UserLocation = args.UserLocation; 518 newData.UserLocation = args.UserLocation;
325 newData.UserLookAt = args.UserLookAt; 519 newData.UserLookAt = args.UserLookAt;
326 } 520 }
327 521
328 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia)) 522 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia, false))
329 { 523 {
330 newData.MediaAutoScale = args.MediaAutoScale; 524 newData.MediaAutoScale = args.MediaAutoScale;
331 newData.MediaID = args.MediaID; 525 newData.MediaID = args.MediaID;
@@ -346,7 +540,8 @@ namespace OpenSim.Region.CoreModules.World.Land
346 ParcelFlags.UseEstateVoiceChan); 540 ParcelFlags.UseEstateVoiceChan);
347 } 541 }
348 542
349 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses)) 543 // don't allow passes on group owned until we can give money to groups
544 if (!newData.IsGroupOwned && m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
350 { 545 {
351 newData.PassHours = args.PassHours; 546 newData.PassHours = args.PassHours;
352 newData.PassPrice = args.PassPrice; 547 newData.PassPrice = args.PassPrice;
@@ -354,13 +549,13 @@ namespace OpenSim.Region.CoreModules.World.Land
354 allowedDelta |= (uint)ParcelFlags.UsePassList; 549 allowedDelta |= (uint)ParcelFlags.UsePassList;
355 } 550 }
356 551
357 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed)) 552 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed, false))
358 { 553 {
359 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup | 554 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
360 ParcelFlags.UseAccessList); 555 ParcelFlags.UseAccessList);
361 } 556 }
362 557
363 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned)) 558 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned, false))
364 { 559 {
365 allowedDelta |= (uint)(ParcelFlags.UseBanList | 560 allowedDelta |= (uint)(ParcelFlags.UseBanList |
366 ParcelFlags.DenyAnonymous | 561 ParcelFlags.DenyAnonymous |
@@ -372,9 +567,16 @@ namespace OpenSim.Region.CoreModules.World.Land
372 uint preserve = LandData.Flags & ~allowedDelta; 567 uint preserve = LandData.Flags & ~allowedDelta;
373 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 568 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
374 569
570 uint curdelta = LandData.Flags ^ newData.Flags;
571 curdelta &= (uint)(ParcelFlags.SoundLocal);
572
573 if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
574 needOverlay = true;
575
375 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 576 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
376 SendLandUpdateToAvatarsOverMe(snap_selection); 577 return true;
377 } 578 }
579 return false;
378 } 580 }
379 581
380 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 582 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -395,7 +597,7 @@ namespace OpenSim.Region.CoreModules.World.Land
395 UUID previousOwner = LandData.OwnerID; 597 UUID previousOwner = LandData.OwnerID;
396 598
397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 599 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
398 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 600// m_scene.EventManager.TriggerParcelPrimCountUpdate();
399 SendLandUpdateToAvatarsOverMe(true); 601 SendLandUpdateToAvatarsOverMe(true);
400 602
401 if (sellObjects) SellLandObjects(previousOwner); 603 if (sellObjects) SellLandObjects(previousOwner);
@@ -431,7 +633,7 @@ namespace OpenSim.Region.CoreModules.World.Land
431 633
432 public bool CanBeOnThisLand(UUID avatar, float posHeight) 634 public bool CanBeOnThisLand(UUID avatar, float posHeight)
433 { 635 {
434 if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar)) 636 if (posHeight < LandChannel.BAN_LINE_SAFETY_HEIGHT && IsBannedFromLand(avatar))
435 { 637 {
436 return false; 638 return false;
437 } 639 }
@@ -530,7 +732,30 @@ namespace OpenSim.Region.CoreModules.World.Land
530 if (HasGroupAccess(avatar)) 732 if (HasGroupAccess(avatar))
531 return false; 733 return false;
532 734
533 return !IsInLandAccessList(avatar); 735 if(IsInLandAccessList(avatar))
736 return false;
737
738 // check for a NPC
739 ScenePresence sp;
740 if (!m_scene.TryGetScenePresence(avatar, out sp))
741 return true;
742
743 if(sp==null || !sp.IsNPC)
744 return true;
745
746 INPC npccli = (INPC)sp.ControllingClient;
747 if(npccli== null)
748 return true;
749
750 UUID owner = npccli.Owner;
751
752 if(owner == UUID.Zero)
753 return true;
754
755 if (owner == LandData.OwnerID)
756 return false;
757
758 return !IsInLandAccessList(owner);
534 } 759 }
535 760
536 public bool IsInLandAccessList(UUID avatar) 761 public bool IsInLandAccessList(UUID avatar)
@@ -568,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land
568 793
569 public void SendLandUpdateToAvatarsOverMe(bool snap_selection) 794 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
570 { 795 {
796 m_scene.EventManager.TriggerParcelPrimCountUpdate();
571 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 797 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
572 { 798 {
573 ILandObject over = null; 799 ILandObject over = null;
@@ -587,13 +813,13 @@ namespace OpenSim.Region.CoreModules.World.Land
587 { 813 {
588 if (over.LandData.LocalID == LandData.LocalID) 814 if (over.LandData.LocalID == LandData.LocalID)
589 { 815 {
590 if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && 816 if(m_scene.RegionInfo.RegionSettings.AllowDamage)
591 m_scene.RegionInfo.RegionSettings.AllowDamage)
592 avatar.Invulnerable = false; 817 avatar.Invulnerable = false;
593 else 818 else
594 avatar.Invulnerable = true; 819 avatar.Invulnerable = (over.LandData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
595 820
596 SendLandUpdateToClient(snap_selection, avatar.ControllingClient); 821 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
822 avatar.currentParcelUUID = LandData.GlobalID;
597 } 823 }
598 } 824 }
599 }); 825 });
@@ -630,13 +856,13 @@ namespace OpenSim.Region.CoreModules.World.Land
630 IClientAPI remote_client) 856 IClientAPI remote_client)
631 { 857 {
632 858
633 if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) 859 if ((flags & (uint) AccessList.Access) != 0)
634 { 860 {
635 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access); 861 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
636 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID); 862 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID);
637 } 863 }
638 864
639 if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) 865 if ((flags & (uint) AccessList.Ban) != 0)
640 { 866 {
641 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban); 867 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
642 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID); 868 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID);
@@ -691,6 +917,17 @@ namespace OpenSim.Region.CoreModules.World.Land
691 newData.ParcelAccessList.Add(temp); 917 newData.ParcelAccessList.Add(temp);
692 } 918 }
693 919
920 // update use lists flags
921 // rights already checked or we wont be here
922 uint parcelflags = newData.Flags;
923
924 if((flags & (uint)AccessList.Access) != 0)
925 parcelflags |= (uint)ParcelFlags.UseAccessList;
926 if((flags & (uint)AccessList.Ban) != 0)
927 parcelflags |= (uint)ParcelFlags.UseBanList;
928
929 newData.Flags = parcelflags;
930
694 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 931 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
695 } 932 }
696 933
@@ -708,7 +945,7 @@ namespace OpenSim.Region.CoreModules.World.Land
708 /// </summary> 945 /// </summary>
709 public void ForceUpdateLandInfo() 946 public void ForceUpdateLandInfo()
710 { 947 {
711 UpdateAABBAndAreaValues(); 948 UpdateGeometryValues();
712 UpdateLandBitmapByteArray(); 949 UpdateLandBitmapByteArray();
713 } 950 }
714 951
@@ -718,52 +955,117 @@ namespace OpenSim.Region.CoreModules.World.Land
718 } 955 }
719 956
720 /// <summary> 957 /// <summary>
721 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object 958 /// Updates geomtric values after area/shape modification of the land object
722 /// </summary> 959 /// </summary>
723 private void UpdateAABBAndAreaValues() 960 private void UpdateGeometryValues()
724 { 961 {
725 int min_x = 10000; 962 int min_x = Int32.MaxValue;
726 int min_y = 10000; 963 int min_y = Int32.MaxValue;
727 int max_x = 0; 964 int max_x = Int32.MinValue;
728 int max_y = 0; 965 int max_y = Int32.MinValue;
729 int tempArea = 0; 966 int tempArea = 0;
730 int x, y; 967 int x, y;
968
969 int lastX = 0;
970 int lastY = 0;
971 float avgx = 0f;
972 float avgy = 0f;
973
974 bool needFirst = true;
975
731 for (x = 0; x < LandBitmap.GetLength(0); x++) 976 for (x = 0; x < LandBitmap.GetLength(0); x++)
732 { 977 {
733 for (y = 0; y < LandBitmap.GetLength(1); y++) 978 for (y = 0; y < LandBitmap.GetLength(1); y++)
734 { 979 {
735 if (LandBitmap[x, y] == true) 980 if (LandBitmap[x, y])
736 { 981 {
737 if (min_x > x) min_x = x; 982 if (min_x > x)
738 if (min_y > y) min_y = y; 983 min_x = x;
739 if (max_x < x) max_x = x; 984 if (min_y > y)
740 if (max_y < y) max_y = y; 985 min_y = y;
741 tempArea += landUnit * landUnit; //16sqm peice of land 986 if (max_x < x)
987 max_x = x;
988 if (max_y < y)
989 max_y = y;
990
991 if(needFirst)
992 {
993 avgx = x;
994 avgy = y;
995 m_startPoint.X = x * landUnit;
996 m_startPoint.Y = y * landUnit;
997 needFirst = false;
998 }
999 else
1000 {
1001 // keeping previus odd average
1002 avgx = (avgx * tempArea + x) / (tempArea + 1);
1003 avgy = (avgy * tempArea + y) / (tempArea + 1);
1004 }
1005
1006 tempArea++;
1007
1008 lastX = x;
1009 lastY = y;
742 } 1010 }
743 } 1011 }
744 } 1012 }
1013
1014 int halfunit = landUnit/2;
1015
1016 m_centerPoint.X = avgx * landUnit + halfunit;
1017 m_centerPoint.Y = avgy * landUnit + halfunit;
1018
1019 m_endPoint.X = lastX * landUnit + landUnit;
1020 m_endPoint.Y = lastY * landUnit + landUnit;
1021
1022 // next tests should not be needed
1023 // if they fail, something is wrong
1024
1025 int regionSizeX = (int)Constants.RegionSize;
1026 int regionSizeY = (int)Constants.RegionSize;
1027
1028 if(m_scene != null)
1029 {
1030 regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
1031 regionSizeY = (int)m_scene.RegionInfo.RegionSizeX;
1032 }
1033
745 int tx = min_x * landUnit; 1034 int tx = min_x * landUnit;
746 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 1035 if (tx >= regionSizeX)
747 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 1036 tx = regionSizeX - 1;
1037
748 int ty = min_y * landUnit; 1038 int ty = min_y * landUnit;
749 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 1039 if (ty >= regionSizeY)
750 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 1040 ty = regionSizeY - 1;
751 1041
752 LandData.AABBMin = 1042 m_AABBmin.X = tx;
753 new Vector3( 1043 m_AABBmin.Y = ty;
754 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 1044
1045 if(m_scene == null || m_scene.Heightmap == null)
1046 LandData.AABBMin = new Vector3(tx, ty, 0f);
1047 else
1048 LandData.AABBMin = new Vector3(tx, ty, (float)m_scene.Heightmap[tx, ty]);
755 1049
1050 max_x++;
756 tx = max_x * landUnit; 1051 tx = max_x * landUnit;
757 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 1052 if (tx > regionSizeX)
758 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 1053 tx = regionSizeX;
1054
1055 max_y++;
759 ty = max_y * landUnit; 1056 ty = max_y * landUnit;
760 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 1057 if (ty > regionSizeY)
761 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 1058 ty = regionSizeY;
1059
1060 m_AABBmax.X = tx;
1061 m_AABBmax.Y = ty;
762 1062
763 LandData.AABBMax 1063 if(m_scene == null || m_scene.Heightmap == null)
764 = new Vector3( 1064 LandData.AABBMax = new Vector3(tx, ty, 0f);
765 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 1065 else
1066 LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]);
766 1067
1068 tempArea *= landUnit * landUnit;
767 LandData.Area = tempArea; 1069 LandData.Area = tempArea;
768 } 1070 }
769 1071
@@ -778,7 +1080,6 @@ namespace OpenSim.Region.CoreModules.World.Land
778 public void SetLandBitmap(bool[,] bitmap) 1080 public void SetLandBitmap(bool[,] bitmap)
779 { 1081 {
780 LandBitmap = bitmap; 1082 LandBitmap = bitmap;
781 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
782 ForceUpdateLandInfo(); 1083 ForceUpdateLandInfo();
783 } 1084 }
784 1085
@@ -793,17 +1094,17 @@ namespace OpenSim.Region.CoreModules.World.Land
793 1094
794 public bool[,] BasicFullRegionLandBitmap() 1095 public bool[,] BasicFullRegionLandBitmap()
795 { 1096 {
796 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY); 1097 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY, true);
797 } 1098 }
798 1099
799 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 1100 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y, bool set_value = true)
800 { 1101 {
801 // Empty bitmap for the whole region 1102 // Empty bitmap for the whole region
802 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 1103 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
803 tempBitmap.Initialize(); 1104 tempBitmap.Initialize();
804 1105
805 // Fill the bitmap square area specified by state and end 1106 // Fill the bitmap square area specified by state and end
806 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 1107 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, set_value);
807 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>", 1108 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
808 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1)); 1109 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
809 return tempBitmap; 1110 return tempBitmap;
@@ -873,51 +1174,288 @@ namespace OpenSim.Region.CoreModules.World.Land
873 } 1174 }
874 1175
875 /// <summary> 1176 /// <summary>
1177 /// Remap a land bitmap. Takes the supplied land bitmap and rotates it, crops it and finally offsets it into
1178 /// a final land bitmap of the target region size.
1179 /// </summary>
1180 /// <param name="bitmap_base">The original parcel bitmap</param>
1181 /// <param name="rotationDegrees"></param>
1182 /// <param name="displacement">&lt;x,y,?&gt;</param>
1183 /// <param name="boundingOrigin">&lt;x,y,?&gt;</param>
1184 /// <param name="boundingSize">&lt;x,y,?&gt;</param>
1185 /// <param name="regionSize">&lt;x,y,?&gt;</param>
1186 /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
1187 /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
1188 /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
1189 /// <returns>New parcel bitmap</returns>
1190 public bool[,] RemapLandBitmap(bool[,] bitmap_base, Vector2 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Vector2 regionSize, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1191 {
1192 // get the size of the incoming bitmap
1193 int baseX = bitmap_base.GetLength(0);
1194 int baseY = bitmap_base.GetLength(1);
1195
1196 // create an intermediate bitmap that is 25% bigger on each side that we can work with to handle rotations
1197 int offsetX = baseX / 4; // the original origin will now be at these coordinates so now we can have imaginary negative coordinates ;)
1198 int offsetY = baseY / 4;
1199 int tmpX = baseX + baseX / 2;
1200 int tmpY = baseY + baseY / 2;
1201 int centreX = tmpX / 2;
1202 int centreY = tmpY / 2;
1203 bool[,] bitmap_tmp = new bool[tmpX, tmpY];
1204
1205 double radianRotation = Math.PI * rotationDegrees / 180f;
1206 double cosR = Math.Cos(radianRotation);
1207 double sinR = Math.Sin(radianRotation);
1208 if (rotationDegrees < 0f) rotationDegrees += 360f; //-90=270 -180=180 -270=90
1209
1210 // So first we apply the rotation to the incoming bitmap, storing the result in bitmap_tmp
1211 // We special case orthogonal rotations for accuracy because even using double precision math, Math.Cos(90 degrees) is never fully 0
1212 // and we can never rotate around a centre pixel because the bitmap size is always even
1213 int x, y, sx, sy;
1214 for (y = 0; y <= tmpY; y++)
1215 {
1216 for (x = 0; x <= tmpX; x++)
1217 {
1218 if (rotationDegrees == 0f)
1219 {
1220 sx = x - offsetX;
1221 sy = y - offsetY;
1222 }
1223 else if (rotationDegrees == 90f)
1224 {
1225 sx = y - offsetX;
1226 sy = tmpY - 1 - x - offsetY;
1227 }
1228 else if (rotationDegrees == 180f)
1229 {
1230 sx = tmpX - 1 - x - offsetX;
1231 sy = tmpY - 1 - y - offsetY;
1232 }
1233 else if (rotationDegrees == 270f)
1234 {
1235 sx = tmpX - 1 - y - offsetX;
1236 sy = x - offsetY;
1237 }
1238 else
1239 {
1240 // arbitary rotation: hmmm should I be using (centreX - 0.5) and (centreY - 0.5) and round cosR and sinR to say only 5 decimal places?
1241 sx = centreX + (int)Math.Round((((double)x - centreX) * cosR) + (((double)y - centreY) * sinR)) - offsetX;
1242 sy = centreY + (int)Math.Round((((double)y - centreY) * cosR) - (((double)x - centreX) * sinR)) - offsetY;
1243 }
1244 if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
1245 {
1246 try
1247 {
1248 if (bitmap_base[sx, sy]) bitmap_tmp[x, y] = true;
1249 }
1250 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
1251 {
1252 m_log.DebugFormat("{0} RemapLandBitmap Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, sx, sy, x, y);
1253 }
1254 }
1255 }
1256 }
1257
1258 // We could also incorporate the next steps, bounding-rectangle and displacement in the loop above, but it's simpler to visualise if done separately
1259 // and will also make it much easier when later I want the option for maybe a circular or oval bounding shape too ;).
1260 // So... our output land bitmap must be the size of the current region but rememeber, parcel landbitmaps are landUnit metres (4x4 metres) per point,
1261 // and region sizes, boundaries and displacements are in metres so we need to scale down
1262
1263 int newX = (int)(regionSize.X / landUnit);
1264 int newY = (int)(regionSize.Y / landUnit);
1265 bool[,] bitmap_new = new bool[newX, newY];
1266 // displacement is relative to <0,0> in the destination region and defines where the origin of the data selected by the bounding-rectangle is placed
1267 int dispX = (int)Math.Floor(displacement.X / landUnit);
1268 int dispY = (int)Math.Floor(displacement.Y / landUnit);
1269
1270 // startX/Y and endX/Y are coordinates in bitmap_tmp
1271 int startX = (int)Math.Floor(boundingOrigin.X / landUnit) + offsetX;
1272 if (startX > tmpX) startX = tmpX;
1273 if (startX < 0) startX = 0;
1274 int startY = (int)Math.Floor(boundingOrigin.Y / landUnit) + offsetY;
1275 if (startY > tmpY) startY = tmpY;
1276 if (startY < 0) startY = 0;
1277
1278 int endX = (int)Math.Floor((boundingOrigin.X + boundingSize.X) / landUnit) + offsetX;
1279 if (endX > tmpX) endX = tmpX;
1280 if (endX < 0) endX = 0;
1281 int endY = (int)Math.Floor((boundingOrigin.Y + boundingSize.Y) / landUnit) + offsetY;
1282 if (endY > tmpY) endY = tmpY;
1283 if (endY < 0) endY = 0;
1284
1285 //m_log.DebugFormat("{0} RemapLandBitmap: inSize=<{1},{2}>, disp=<{3},{4}> rot={5}, offset=<{6},{7}>, boundingStart=<{8},{9}>, boundingEnd=<{10},{11}>, cosR={12}, sinR={13}, outSize=<{14},{15}>", LogHeader,
1286 // baseX, baseY, dispX, dispY, radianRotation, offsetX, offsetY, startX, startY, endX, endY, cosR, sinR, newX, newY);
1287
1288 isEmptyNow = true;
1289 int minX = newX;
1290 int minY = newY;
1291 int maxX = 0;
1292 int maxY = 0;
1293
1294 int dx, dy;
1295 for (y = startY; y < endY; y++)
1296 {
1297 for (x = startX; x < endX; x++)
1298 {
1299 dx = x - startX + dispX;
1300 dy = y - startY + dispY;
1301 if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
1302 {
1303 try
1304 {
1305 if (bitmap_tmp[x, y])
1306 {
1307 bitmap_new[dx, dy] = true;
1308 isEmptyNow = false;
1309 if (dx < minX) minX = dx;
1310 if (dy < minY) minY = dy;
1311 if (dx > maxX) maxX = dx;
1312 if (dy > maxY) maxY = dy;
1313 }
1314 }
1315 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
1316 {
1317 m_log.DebugFormat("{0} RemapLandBitmap - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, x, y, dx, dy);
1318 }
1319 }
1320 }
1321 }
1322 if (isEmptyNow)
1323 {
1324 //m_log.DebugFormat("{0} RemapLandBitmap: Land bitmap is marked as Empty", LogHeader);
1325 minX = 0;
1326 minY = 0;
1327 }
1328
1329 AABBMin = new Vector3(minX * landUnit, minY * landUnit, 0);
1330 AABBMax = new Vector3(maxX * landUnit, maxY * landUnit, 0);
1331 return bitmap_new;
1332 }
1333
1334 /// <summary>
1335 /// Clears any parcel data in bitmap_base where there exists parcel data in bitmap_new. In other words the parcel data
1336 /// in bitmap_new takes over the space of the parcel data in bitmap_base.
1337 /// </summary>
1338 /// <param name="bitmap_base"></param>
1339 /// <param name="bitmap_new"></param>
1340 /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
1341 /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
1342 /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
1343 /// <returns>New parcel bitmap</returns>
1344 public bool[,] RemoveFromLandBitmap(bool[,] bitmap_base, bool[,] bitmap_new, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1345 {
1346 // get the size of the incoming bitmaps
1347 int baseX = bitmap_base.GetLength(0);
1348 int baseY = bitmap_base.GetLength(1);
1349 int newX = bitmap_new.GetLength(0);
1350 int newY = bitmap_new.GetLength(1);
1351
1352 if (baseX != newX || baseY != newY)
1353 {
1354 throw new Exception(
1355 String.Format("{0} RemoveFromLandBitmap: Land bitmaps are not the same size! baseX={1} baseY={2} newX={3} newY={4}", LogHeader, baseX, baseY, newX, newY));
1356 }
1357
1358 isEmptyNow = true;
1359 int minX = baseX;
1360 int minY = baseY;
1361 int maxX = 0;
1362 int maxY = 0;
1363
1364 for (int y = 0; y < baseY; y++)
1365 {
1366 for (int x = 0; x < baseX; x++)
1367 {
1368 if (bitmap_new[x, y]) bitmap_base[x, y] = false;
1369 if (bitmap_base[x, y])
1370 {
1371 isEmptyNow = false;
1372 if (x < minX) minX = x;
1373 if (y < minY) minY = y;
1374 if (x > maxX) maxX = x;
1375 if (y > maxY) maxY = y;
1376 }
1377 }
1378 }
1379 if (isEmptyNow)
1380 {
1381 //m_log.DebugFormat("{0} RemoveFromLandBitmap: Land bitmap is marked as Empty", LogHeader);
1382 minX = 0;
1383 minY = 0;
1384 }
1385 AABBMin = new Vector3(minX * landUnit, minY * landUnit, 0);
1386 AABBMax = new Vector3(maxX * landUnit, maxY * landUnit, 0);
1387 return bitmap_base;
1388 }
1389
1390 /// <summary>
876 /// Converts the land bitmap to a packet friendly byte array 1391 /// Converts the land bitmap to a packet friendly byte array
877 /// </summary> 1392 /// </summary>
878 /// <returns></returns> 1393 /// <returns></returns>
879 private byte[] ConvertLandBitmapToBytes() 1394 public byte[] ConvertLandBitmapToBytes()
880 { 1395 {
881 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8]; 1396 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
882 byte tempByte = 0; 1397
883 int byteNum = 0; 1398 int tempByte = 0;
884 int i = 0; 1399 int i, byteNum = 0;
1400 int mask = 1;
1401 i = 0;
885 for (int y = 0; y < LandBitmap.GetLength(1); y++) 1402 for (int y = 0; y < LandBitmap.GetLength(1); y++)
886 { 1403 {
887 for (int x = 0; x < LandBitmap.GetLength(0); x++) 1404 for (int x = 0; x < LandBitmap.GetLength(0); x++)
888 { 1405 {
889 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 1406 if (LandBitmap[x, y])
890 if (i % 8 == 0) 1407 tempByte |= mask;
1408 mask = mask << 1;
1409 if (mask == 0x100)
891 { 1410 {
892 tempConvertArr[byteNum] = tempByte; 1411 mask = 1;
893 tempByte = (byte) 0; 1412 tempConvertArr[byteNum++] = (byte)tempByte;
894 i = 0; 1413 tempByte = 0;
895 byteNum++;
896 } 1414 }
897 } 1415 }
898 } 1416 }
899 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>", 1417
900 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 1418 if(tempByte != 0 && byteNum < 512)
1419 tempConvertArr[byteNum] = (byte)tempByte;
1420
901 return tempConvertArr; 1421 return tempConvertArr;
902 } 1422 }
903 1423
904 private bool[,] ConvertBytesToLandBitmap() 1424 public bool[,] ConvertBytesToLandBitmap(bool overrideRegionSize = false)
905 { 1425 {
906 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 1426 int bitmapLen;
907 tempConvertMap.Initialize(); 1427 int xLen;
908 byte tempByte = 0; 1428 bool[,] tempConvertMap;
909 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
910 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
911 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
912 1429
913 if (bitmapLen == 512) 1430 if (overrideRegionSize)
1431 {
1432 // Importing land parcel data from an OAR where the source region is a different size to the dest region requires us
1433 // to make a LandBitmap that's not derived from the current region's size. We use the LandData.Bitmap size in bytes
1434 // to figure out what the OAR's region dimensions are. (Is there a better way to get the src region x and y from the OAR?)
1435 // This method assumes we always will have square regions
1436
1437 bitmapLen = LandData.Bitmap.Length;
1438 xLen = (int)Math.Abs(Math.Sqrt(bitmapLen * 8));
1439 tempConvertMap = new bool[xLen, xLen];
1440 tempConvertMap.Initialize();
1441 }
1442 else
914 { 1443 {
915 // Legacy bitmap being passed in. Use the legacy region size 1444 tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
916 // and only set the lower area of the larger region. 1445 tempConvertMap.Initialize();
917 xLen = (int)(Constants.RegionSize / landUnit); 1446 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
1447 bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
1448 xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
1449 if (bitmapLen == 512)
1450 {
1451 // Legacy bitmap being passed in. Use the legacy region size
1452 // and only set the lower area of the larger region.
1453 xLen = (int)(Constants.RegionSize / landUnit);
1454 }
918 } 1455 }
919 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen); 1456 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
920 1457
1458 byte tempByte;
921 int x = 0, y = 0; 1459 int x = 0, y = 0;
922 for (int i = 0; i < bitmapLen; i++) 1460 for (int i = 0; i < bitmapLen; i++)
923 { 1461 {
@@ -945,13 +1483,39 @@ namespace OpenSim.Region.CoreModules.World.Land
945 return tempConvertMap; 1483 return tempConvertMap;
946 } 1484 }
947 1485
1486 public bool IsLandBitmapEmpty(bool[,] landBitmap)
1487 {
1488 for (int y = 0; y < landBitmap.GetLength(1); y++)
1489 {
1490 for (int x = 0; x < landBitmap.GetLength(0); x++)
1491 {
1492 if (landBitmap[x, y]) return false;
1493 }
1494 }
1495 return true;
1496 }
1497
1498 public void DebugLandBitmap(bool[,] landBitmap)
1499 {
1500 m_log.InfoFormat("{0}: Map Key: #=claimed land .=unclaimed land.", LogHeader);
1501 for (int y = landBitmap.GetLength(1) - 1; y >= 0; y--)
1502 {
1503 string row = "";
1504 for (int x = 0; x < landBitmap.GetLength(0); x++)
1505 {
1506 row += landBitmap[x, y] ? "#" : ".";
1507 }
1508 m_log.InfoFormat("{0}: {1}", LogHeader, row);
1509 }
1510 }
1511
948 #endregion 1512 #endregion
949 1513
950 #region Object Select and Object Owner Listing 1514 #region Object Select and Object Owner Listing
951 1515
952 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client) 1516 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
953 { 1517 {
954 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1518 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
955 { 1519 {
956 List<uint> resultLocalIDs = new List<uint>(); 1520 List<uint> resultLocalIDs = new List<uint>();
957 try 1521 try
@@ -1001,7 +1565,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1001 /// </param> 1565 /// </param>
1002 public void SendLandObjectOwners(IClientAPI remote_client) 1566 public void SendLandObjectOwners(IClientAPI remote_client)
1003 { 1567 {
1004 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1568 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
1005 { 1569 {
1006 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>(); 1570 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
1007 List<UUID> groups = new List<UUID>(); 1571 List<UUID> groups = new List<UUID>();
@@ -1009,9 +1573,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1009 lock (primsOverMe) 1573 lock (primsOverMe)
1010 { 1574 {
1011// m_log.DebugFormat( 1575// m_log.DebugFormat(
1012// "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region", 1576// "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
1013// remote_client.Name, primsOverMe.Count); 1577// remote_client.Name, primsOverMe.Count);
1014 1578
1015 try 1579 try
1016 { 1580 {
1017 foreach (SceneObjectGroup obj in primsOverMe) 1581 foreach (SceneObjectGroup obj in primsOverMe)
@@ -1052,7 +1616,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1052 public Dictionary<UUID, int> GetLandObjectOwners() 1616 public Dictionary<UUID, int> GetLandObjectOwners()
1053 { 1617 {
1054 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>(); 1618 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
1055 1619
1056 lock (primsOverMe) 1620 lock (primsOverMe)
1057 { 1621 {
1058 try 1622 try
@@ -1106,8 +1670,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1106 { 1670 {
1107 foreach (SceneObjectGroup obj in primsOverMe) 1671 foreach (SceneObjectGroup obj in primsOverMe)
1108 { 1672 {
1109 if (obj.OwnerID == previousOwner && obj.GroupID == UUID.Zero && 1673 if(m_scene.Permissions.CanSellObject(previousOwner,obj, (byte)SaleType.Original))
1110 (obj.GetEffectivePermissions() & (uint)(OpenSim.Framework.PermissionMask.Transfer)) != 0)
1111 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0); 1674 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0);
1112 } 1675 }
1113 } 1676 }
@@ -1121,14 +1684,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1121 { 1684 {
1122 SceneObjectGroup[] objs = new SceneObjectGroup[1]; 1685 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1123 objs[0] = obj; 1686 objs[0] = obj;
1124 m_scene.returnObjects(objs, obj.OwnerID); 1687 m_scene.returnObjects(objs, null);
1125 } 1688 }
1126 1689
1127 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) 1690 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
1128 { 1691 {
1129// m_log.DebugFormat( 1692// m_log.DebugFormat(
1130// "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name); 1693// "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
1131 1694
1132 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>(); 1695 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
1133 1696
1134 lock (primsOverMe) 1697 lock (primsOverMe)
@@ -1152,6 +1715,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1152 { 1715 {
1153 if (obj.GroupID == LandData.GroupID) 1716 if (obj.GroupID == LandData.GroupID)
1154 { 1717 {
1718 if (obj.OwnerID == LandData.OwnerID)
1719 continue;
1155 if (!returns.ContainsKey(obj.OwnerID)) 1720 if (!returns.ContainsKey(obj.OwnerID))
1156 returns[obj.OwnerID] = 1721 returns[obj.OwnerID] =
1157 new List<SceneObjectGroup>(); 1722 new List<SceneObjectGroup>();
@@ -1193,8 +1758,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1193 1758
1194 foreach (List<SceneObjectGroup> ol in returns.Values) 1759 foreach (List<SceneObjectGroup> ol in returns.Values)
1195 { 1760 {
1196 if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) 1761 if (m_scene.Permissions.CanReturnObjects(this, remote_client, ol))
1197 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); 1762 m_scene.returnObjects(ol.ToArray(), remote_client);
1198 } 1763 }
1199 } 1764 }
1200 1765
@@ -1211,7 +1776,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1211 public void AddPrimOverMe(SceneObjectGroup obj) 1776 public void AddPrimOverMe(SceneObjectGroup obj)
1212 { 1777 {
1213// m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name); 1778// m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
1214 1779
1215 lock (primsOverMe) 1780 lock (primsOverMe)
1216 primsOverMe.Add(obj); 1781 primsOverMe.Add(obj);
1217 } 1782 }
@@ -1219,13 +1784,13 @@ namespace OpenSim.Region.CoreModules.World.Land
1219 public void RemovePrimFromOverMe(SceneObjectGroup obj) 1784 public void RemovePrimFromOverMe(SceneObjectGroup obj)
1220 { 1785 {
1221// m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name); 1786// m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
1222 1787
1223 lock (primsOverMe) 1788 lock (primsOverMe)
1224 primsOverMe.Remove(obj); 1789 primsOverMe.Remove(obj);
1225 } 1790 }
1226 1791
1227 #endregion 1792 #endregion
1228 1793
1229 /// <summary> 1794 /// <summary>
1230 /// Set the media url for this land parcel 1795 /// Set the media url for this land parcel
1231 /// </summary> 1796 /// </summary>
@@ -1233,9 +1798,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1233 public void SetMediaUrl(string url) 1798 public void SetMediaUrl(string url)
1234 { 1799 {
1235 LandData.MediaURL = url; 1800 LandData.MediaURL = url;
1801 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1236 SendLandUpdateToAvatarsOverMe(); 1802 SendLandUpdateToAvatarsOverMe();
1237 } 1803 }
1238 1804
1239 /// <summary> 1805 /// <summary>
1240 /// Set the music url for this land parcel 1806 /// Set the music url for this land parcel
1241 /// </summary> 1807 /// </summary>
@@ -1243,6 +1809,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1243 public void SetMusicUrl(string url) 1809 public void SetMusicUrl(string url)
1244 { 1810 {
1245 LandData.MusicURL = url; 1811 LandData.MusicURL = url;
1812 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1246 SendLandUpdateToAvatarsOverMe(); 1813 SendLandUpdateToAvatarsOverMe();
1247 } 1814 }
1248 1815
@@ -1257,6 +1824,48 @@ namespace OpenSim.Region.CoreModules.World.Land
1257 1824
1258 #endregion 1825 #endregion
1259 1826
1827 private void OnFrame()
1828 {
1829 m_expiryCounter++;
1830
1831 if (m_expiryCounter >= 50)
1832 {
1833 ExpireAccessList();
1834 m_expiryCounter = 0;
1835 }
1836
1837 // need to update dwell here bc landdata has no parent info
1838 if(LandData != null && m_dwellModule != null)
1839 {
1840 double now = Util.GetTimeStampMS();
1841 double elapsed = now - LandData.LastDwellTimeMS;
1842 if(elapsed > 150000) //2.5 minutes resolution / throttle
1843 {
1844 float dwell = LandData.Dwell;
1845 double cur = dwell * 60000.0;
1846 double decay = 1.5e-8 * cur * elapsed;
1847 cur -= decay;
1848 if(cur < 0)
1849 cur = 0;
1850
1851 UUID lgid = LandData.GlobalID;
1852 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1853 {
1854 if(sp.IsNPC || sp.IsLoggingIn || sp.IsDeleted || sp.currentParcelUUID != lgid)
1855 return;
1856 cur += (now - sp.ParcelDwellTickMS);
1857 sp.ParcelDwellTickMS = now;
1858 });
1859
1860 float newdwell = (float)(cur * 1.666666666667e-5);
1861 LandData.Dwell = newdwell;
1862
1863 if(Math.Abs(newdwell - dwell) >= 0.9)
1864 m_scene.EventManager.TriggerLandObjectAdded(this);
1865 }
1866 }
1867 }
1868
1260 private void ExpireAccessList() 1869 private void ExpireAccessList()
1261 { 1870 {
1262 List<LandAccessEntry> delete = new List<LandAccessEntry>(); 1871 List<LandAccessEntry> delete = new List<LandAccessEntry>();
@@ -1267,7 +1876,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1267 delete.Add(entry); 1876 delete.Add(entry);
1268 } 1877 }
1269 foreach (LandAccessEntry entry in delete) 1878 foreach (LandAccessEntry entry in delete)
1879 {
1270 LandData.ParcelAccessList.Remove(entry); 1880 LandData.ParcelAccessList.Remove(entry);
1881 ScenePresence presence;
1882
1883 if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
1884 {
1885 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1886 if (land.LandData.LocalID == LandData.LocalID)
1887 {
1888 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1889 presence.TeleportOnEject(pos);
1890 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1891 }
1892 }
1893 m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1894 }
1271 1895
1272 if (delete.Count > 0) 1896 if (delete.Count > 0)
1273 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this); 1897 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);