aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs947
1 files changed, 0 insertions, 947 deletions
diff --git a/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs b/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs
deleted file mode 100644
index da42c21..0000000
--- a/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs
+++ /dev/null
@@ -1,947 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using libsecondlife;
32using libsecondlife.Packets;
33using log4net;
34using OpenSim.Framework;
35using OpenSim.Region.Environment.Interfaces;
36using OpenSim.Region.Environment.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.LandManagement
39{
40
41 #region LandObject Class
42
43 /// <summary>
44 /// Keeps track of a specific piece of land's information
45 /// </summary>
46 public class LandObject : ILandObject
47 {
48 #region Member Variables
49
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 protected LandData m_landData = new LandData();
53 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
54 protected Scene m_scene;
55
56 private bool[,] m_landBitmap = new bool[64,64];
57
58 public bool[,] landBitmap
59 {
60 get
61 {
62 return m_landBitmap;
63 }
64 set
65 {
66 m_landBitmap = value;
67 }
68 }
69
70 #endregion
71
72 #region ILandObject Members
73
74 public LandData landData
75 {
76 get
77 {
78 return m_landData;
79 }
80
81 set
82 {
83 m_landData = value;
84 }
85 }
86
87 public LLUUID regionUUID
88 {
89 get { return m_scene.RegionInfo.RegionID; }
90 }
91
92 #endregion
93
94
95 #region Constructors
96
97 public LandObject(LLUUID owner_id, bool is_group_owned, Scene scene)
98 {
99 m_scene = scene;
100 landData.ownerID = owner_id;
101 landData.isGroupOwned = is_group_owned;
102 }
103
104 #endregion
105
106 #region Member Functions
107
108 #region General Functions
109
110 /// <summary>
111 /// Checks to see if this land object contains a point
112 /// </summary>
113 /// <param name="x"></param>
114 /// <param name="y"></param>
115 /// <returns>Returns true if the piece of land contains the specified point</returns>
116 public bool containsPoint(int x, int y)
117 {
118 if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize)
119 {
120 return (landBitmap[x/4, y/4] == true);
121 }
122 else
123 {
124 return false;
125 }
126 }
127
128 public ILandObject Copy()
129 {
130 ILandObject newLand = new LandObject(landData.ownerID, landData.isGroupOwned, m_scene);
131
132 //Place all new variables here!
133 newLand.landBitmap = (bool[,]) (landBitmap.Clone());
134 newLand.landData = landData.Copy();
135
136 return newLand;
137 }
138
139 #endregion
140
141 #region Packet Request Handling
142
143 /// <summary>
144 /// Sends land properties as requested
145 /// </summary>
146 /// <param name="sequence_id">ID sent by client for them to keep track of</param>
147 /// <param name="snap_selection">Bool sent by client for them to use</param>
148 /// <param name="remote_client">Object representing the client</param>
149 public void sendLandProperties(int sequence_id, bool snap_selection, int request_result,
150 IClientAPI remote_client)
151 {
152 ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ParcelProperties);
153 // TODO: don't create new blocks if recycling an old packet
154
155 updatePacket.ParcelData.AABBMax = landData.AABBMax;
156 updatePacket.ParcelData.AABBMin = landData.AABBMin;
157 updatePacket.ParcelData.Area = landData.area;
158 updatePacket.ParcelData.AuctionID = landData.auctionID;
159 updatePacket.ParcelData.AuthBuyerID = landData.authBuyerID; //unemplemented
160
161 updatePacket.ParcelData.Bitmap = landData.landBitmapByteArray;
162
163 updatePacket.ParcelData.Desc = Helpers.StringToField(landData.landDesc);
164 updatePacket.ParcelData.Category = (byte) landData.category;
165 updatePacket.ParcelData.ClaimDate = landData.claimDate;
166 updatePacket.ParcelData.ClaimPrice = landData.claimPrice;
167 updatePacket.ParcelData.GroupID = landData.groupID;
168 updatePacket.ParcelData.GroupPrims = landData.groupPrims;
169 updatePacket.ParcelData.IsGroupOwned = landData.isGroupOwned;
170 updatePacket.ParcelData.LandingType = (byte) landData.landingType;
171 updatePacket.ParcelData.LocalID = landData.localID;
172 if (landData.area > 0)
173 {
174 updatePacket.ParcelData.MaxPrims =
175 Convert.ToInt32(
176 Math.Round((Convert.ToDecimal(landData.area)/Convert.ToDecimal(65536))*m_scene.objectCapacity*
177 Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor)));
178 }
179 else
180 {
181 updatePacket.ParcelData.MaxPrims = 0;
182 }
183 updatePacket.ParcelData.MediaAutoScale = landData.mediaAutoScale;
184 updatePacket.ParcelData.MediaID = landData.mediaID;
185 updatePacket.ParcelData.MediaURL = Helpers.StringToField(landData.mediaURL);
186 updatePacket.ParcelData.MusicURL = Helpers.StringToField(landData.musicURL);
187 updatePacket.ParcelData.Name = Helpers.StringToField(landData.landName);
188 updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented
189 updatePacket.ParcelData.OtherCount = 0; //unemplemented
190 updatePacket.ParcelData.OtherPrims = landData.otherPrims;
191 updatePacket.ParcelData.OwnerID = landData.ownerID;
192 updatePacket.ParcelData.OwnerPrims = landData.ownerPrims;
193 updatePacket.ParcelData.ParcelFlags = landData.landFlags;
194 updatePacket.ParcelData.ParcelPrimBonus = m_scene.RegionInfo.EstateSettings.objectBonusFactor;
195 updatePacket.ParcelData.PassHours = landData.passHours;
196 updatePacket.ParcelData.PassPrice = landData.passPrice;
197 updatePacket.ParcelData.PublicCount = 0; //unemplemented
198
199 uint regionFlags = (uint) m_scene.RegionInfo.EstateSettings.regionFlags;
200 updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint) Simulator.RegionFlags.DenyAnonymous) >
201 0);
202 updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint) Simulator.RegionFlags.DenyIdentified) >
203 0);
204 updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint) Simulator.RegionFlags.DenyTransacted) >
205 0);
206 updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint) Simulator.RegionFlags.RestrictPushObject) >
207 0);
208
209 updatePacket.ParcelData.RentPrice = 0;
210 updatePacket.ParcelData.RequestResult = request_result;
211 updatePacket.ParcelData.SalePrice = landData.salePrice;
212 updatePacket.ParcelData.SelectedPrims = landData.selectedPrims;
213 updatePacket.ParcelData.SelfCount = 0; //unemplemented
214 updatePacket.ParcelData.SequenceID = sequence_id;
215 if (landData.simwideArea > 0)
216 {
217 updatePacket.ParcelData.SimWideMaxPrims =
218 Convert.ToInt32(
219 Math.Round((Convert.ToDecimal(landData.simwideArea) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
220 Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor)));
221 }
222 else
223 {
224 updatePacket.ParcelData.SimWideMaxPrims = 0;
225 }
226 updatePacket.ParcelData.SimWideTotalPrims = landData.simwidePrims;
227 updatePacket.ParcelData.SnapSelection = snap_selection;
228 updatePacket.ParcelData.SnapshotID = landData.snapshotID;
229 updatePacket.ParcelData.Status = (byte) landData.landStatus;
230 updatePacket.ParcelData.TotalPrims = landData.ownerPrims + landData.groupPrims + landData.otherPrims +
231 landData.selectedPrims;
232 updatePacket.ParcelData.UserLocation = landData.userLocation;
233 updatePacket.ParcelData.UserLookAt = landData.userLookAt;
234 remote_client.OutPacket((Packet) updatePacket, ThrottleOutPacketType.Task);
235 }
236
237 public void updateLandProperties(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client)
238 {
239 if (remote_client.AgentId == landData.ownerID)
240 {
241 //Needs later group support
242 LandData newData = landData.Copy();
243 newData.authBuyerID = packet.ParcelData.AuthBuyerID;
244 newData.category = (Parcel.ParcelCategory) packet.ParcelData.Category;
245 newData.landDesc = Helpers.FieldToUTF8String(packet.ParcelData.Desc);
246 newData.groupID = packet.ParcelData.GroupID;
247 newData.landingType = packet.ParcelData.LandingType;
248 newData.mediaAutoScale = packet.ParcelData.MediaAutoScale;
249 newData.mediaID = packet.ParcelData.MediaID;
250 newData.mediaURL = Helpers.FieldToUTF8String(packet.ParcelData.MediaURL);
251 newData.musicURL = Helpers.FieldToUTF8String(packet.ParcelData.MusicURL);
252 newData.landName = Helpers.FieldToUTF8String(packet.ParcelData.Name);
253 newData.landFlags = packet.ParcelData.ParcelFlags;
254 newData.passHours = packet.ParcelData.PassHours;
255 newData.passPrice = packet.ParcelData.PassPrice;
256 newData.salePrice = packet.ParcelData.SalePrice;
257 newData.snapshotID = packet.ParcelData.SnapshotID;
258 newData.userLocation = packet.ParcelData.UserLocation;
259 newData.userLookAt = packet.ParcelData.UserLookAt;
260
261 m_scene.LandChannel.updateLandObject(landData.localID, newData);
262
263 sendLandUpdateToAvatarsOverMe();
264 }
265 }
266 public void updateLandSold(LLUUID avatarID, LLUUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
267 {
268 LandData newData = landData.Copy();
269 newData.ownerID = avatarID;
270 newData.groupID = groupID;
271 newData.isGroupOwned = groupOwned;
272 //newData.auctionID = AuctionID;
273 newData.claimDate = Util.UnixTimeSinceEpoch();
274 newData.claimPrice = claimprice;
275 newData.salePrice = 0;
276 newData.authBuyerID = LLUUID.Zero;
277 newData.landFlags &= ~(uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects);
278 m_scene.LandChannel.updateLandObject(landData.localID, newData);
279
280 sendLandUpdateToAvatarsOverMe();
281 }
282
283 public bool isEitherBannedOrRestricted(LLUUID avatar)
284 {
285 if (isBannedFromLand(avatar))
286 {
287 return true;
288 }
289 else if (isRestrictedFromLand(avatar))
290 {
291 return true;
292 }
293 return false;
294 }
295
296 public bool isBannedFromLand(LLUUID avatar)
297 {
298 if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseBanList) > 0)
299 {
300 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
301 entry.AgentID = avatar;
302 entry.Flags = ParcelManager.AccessList.Ban;
303 entry.Time = new DateTime();
304 if (landData.parcelAccessList.Contains(entry))
305 {
306 //They are banned, so lets send them a notice about this parcel
307 return true;
308 }
309 }
310 return false;
311 }
312
313 public bool isRestrictedFromLand(LLUUID avatar)
314 {
315 if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseAccessList) > 0)
316 {
317 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
318 entry.AgentID = avatar;
319 entry.Flags = ParcelManager.AccessList.Access;
320 entry.Time = new DateTime();
321 if (!landData.parcelAccessList.Contains(entry))
322 {
323 //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
324 return true;
325 }
326 }
327 return false;
328 }
329
330 public void sendLandUpdateToClient(IClientAPI remote_client)
331 {
332 sendLandProperties(0, false, 0, remote_client);
333 }
334
335 public void sendLandUpdateToAvatarsOverMe()
336 {
337 List<ScenePresence> avatars = m_scene.GetAvatars();
338 ILandObject over = null;
339 for (int i = 0; i < avatars.Count; i++)
340 {
341 try
342 {
343 over =
344 m_scene.LandChannel.getLandObject((int)Math.Max(255,Math.Min(0,Math.Round(avatars[i].AbsolutePosition.X))),
345 (int)Math.Max(255,Math.Min(0,Math.Round(avatars[i].AbsolutePosition.Y))));
346 }
347 catch (Exception)
348 {
349 m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatars[i].AbsolutePosition.X) + " y: " + Math.Round(avatars[i].AbsolutePosition.Y));
350 }
351
352 if (over != null)
353 {
354 if (over.landData.localID == landData.localID)
355 {
356 sendLandUpdateToClient(avatars[i].ControllingClient);
357 }
358 }
359 }
360 }
361
362 #endregion
363
364 #region AccessList Functions
365
366 public ParcelAccessListReplyPacket.ListBlock[] createAccessListArrayByFlag(ParcelManager.AccessList flag)
367 {
368 List<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>();
369 foreach (ParcelManager.ParcelAccessEntry entry in landData.parcelAccessList)
370 {
371 if (entry.Flags == flag)
372 {
373 ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock();
374
375 listBlock.Flags = (uint) 0;
376 listBlock.ID = entry.AgentID;
377 listBlock.Time = 0;
378
379 list.Add(listBlock);
380 }
381 }
382
383 if (list.Count == 0)
384 {
385 ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock();
386
387 listBlock.Flags = (uint) 0;
388 listBlock.ID = LLUUID.Zero;
389 listBlock.Time = 0;
390
391 list.Add(listBlock);
392 }
393 return list.ToArray();
394 }
395
396 public void sendAccessList(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID,
397 IClientAPI remote_client)
398 {
399 ParcelAccessListReplyPacket replyPacket;
400
401 if (flags == (uint) ParcelManager.AccessList.Access || flags == (uint) ParcelManager.AccessList.Both)
402 {
403 replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
404 replyPacket.Data.AgentID = agentID;
405 replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Access;
406 replyPacket.Data.LocalID = landData.localID;
407 replyPacket.Data.SequenceID = 0;
408
409 replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Access);
410 remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task);
411 }
412
413 if (flags == (uint) ParcelManager.AccessList.Ban || flags == (uint) ParcelManager.AccessList.Both)
414 {
415 replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
416 replyPacket.Data.AgentID = agentID;
417 replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Ban;
418 replyPacket.Data.LocalID = landData.localID;
419 replyPacket.Data.SequenceID = 0;
420
421 replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Ban);
422 remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task);
423 }
424 }
425
426 public void updateAccessList(uint flags, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client)
427 {
428 LandData newData = landData.Copy();
429
430 if (entries.Count == 1 && entries[0].AgentID == LLUUID.Zero)
431 {
432 entries.Clear();
433 }
434
435 List<ParcelManager.ParcelAccessEntry> toRemove = new List<ParcelManager.ParcelAccessEntry>();
436 foreach (ParcelManager.ParcelAccessEntry entry in newData.parcelAccessList)
437 {
438 if (entry.Flags == (ParcelManager.AccessList) flags)
439 {
440 toRemove.Add(entry);
441 }
442 }
443
444 foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
445 {
446 newData.parcelAccessList.Remove(entry);
447 }
448 foreach (ParcelManager.ParcelAccessEntry entry in entries)
449 {
450 ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry();
451 temp.AgentID = entry.AgentID;
452 temp.Time = new DateTime(); //Pointless? Yes.
453 temp.Flags = (ParcelManager.AccessList) flags;
454
455 if (!newData.parcelAccessList.Contains(temp))
456 {
457 newData.parcelAccessList.Add(temp);
458 }
459 }
460
461 m_scene.LandChannel.updateLandObject(landData.localID, newData);
462 }
463
464 #endregion
465
466 #region Update Functions
467
468 /// <summary>
469 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
470 /// </summary>
471 private void updateAABBAndAreaValues()
472 {
473 int min_x = 64;
474 int min_y = 64;
475 int max_x = 0;
476 int max_y = 0;
477 int tempArea = 0;
478 int x, y;
479 for (x = 0; x < 64; x++)
480 {
481 for (y = 0; y < 64; y++)
482 {
483 if (landBitmap[x, y] == true)
484 {
485 if (min_x > x) min_x = x;
486 if (min_y > y) min_y = y;
487 if (max_x < x) max_x = x;
488 if (max_y < y) max_y = y;
489 tempArea += 16; //16sqm peice of land
490 }
491 }
492 }
493 int tx = min_x * 4;
494 if (tx > 255)
495 tx = 255;
496 int ty = min_y * 4;
497 if (ty > 255)
498 ty = 255;
499 landData.AABBMin =
500 new LLVector3((float)(min_x * 4), (float)(min_y * 4),
501 (float)m_scene.Heightmap[tx, ty]);
502
503 tx = max_x * 4;
504 if (tx > 255)
505 tx = 255;
506 ty = max_y * 4;
507 if (ty > 255)
508 ty = 255;
509 landData.AABBMax =
510 new LLVector3((float)(max_x * 4), (float)(max_y * 4),
511 (float)m_scene.Heightmap[tx, ty]);
512 landData.area = tempArea;
513 }
514
515 public void updateLandBitmapByteArray()
516 {
517 landData.landBitmapByteArray = convertLandBitmapToBytes();
518 }
519
520 /// <summary>
521 /// Update all settings in land such as area, bitmap byte array, etc
522 /// </summary>
523 public void forceUpdateLandInfo()
524 {
525 updateAABBAndAreaValues();
526 updateLandBitmapByteArray();
527 }
528
529 public void setLandBitmapFromByteArray()
530 {
531 landBitmap = convertBytesToLandBitmap();
532 }
533
534 #endregion
535
536 #region Land Bitmap Functions
537
538 /// <summary>
539 /// Sets the land's bitmap manually
540 /// </summary>
541 /// <param name="bitmap">64x64 block representing where this land is on a map</param>
542 public void setLandBitmap(bool[,] bitmap)
543 {
544 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
545 {
546 //Throw an exception - The bitmap is not 64x64
547 //throw new Exception("Error: Invalid Parcel Bitmap");
548 }
549 else
550 {
551 //Valid: Lets set it
552 landBitmap = bitmap;
553 forceUpdateLandInfo();
554 }
555 }
556
557 /// <summary>
558 /// Gets the land's bitmap manually
559 /// </summary>
560 /// <returns></returns>
561 public bool[,] getLandBitmap()
562 {
563 return landBitmap;
564 }
565
566 /// <summary>
567 /// Converts the land bitmap to a packet friendly byte array
568 /// </summary>
569 /// <returns></returns>
570 private byte[] convertLandBitmapToBytes()
571 {
572 byte[] tempConvertArr = new byte[512];
573 byte tempByte = 0;
574 int x, y, i, byteNum = 0;
575 i = 0;
576 for (y = 0; y < 64; y++)
577 {
578 for (x = 0; x < 64; x++)
579 {
580 tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++%8));
581 if (i%8 == 0)
582 {
583 tempConvertArr[byteNum] = tempByte;
584 tempByte = (byte) 0;
585 i = 0;
586 byteNum++;
587 }
588 }
589 }
590 return tempConvertArr;
591 }
592
593 private bool[,] convertBytesToLandBitmap()
594 {
595 bool[,] tempConvertMap = new bool[64,64];
596 tempConvertMap.Initialize();
597 byte tempByte = 0;
598 int x = 0, y = 0, i = 0, bitNum = 0;
599 for (i = 0; i < 512; i++)
600 {
601 tempByte = landData.landBitmapByteArray[i];
602 for (bitNum = 0; bitNum < 8; bitNum++)
603 {
604 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
605 tempConvertMap[x, y] = bit;
606 x++;
607 if (x > 63)
608 {
609 x = 0;
610 y++;
611 }
612 }
613 }
614 return tempConvertMap;
615 }
616
617 /// <summary>
618 /// Full sim land object creation
619 /// </summary>
620 /// <returns></returns>
621 public bool[,] basicFullRegionLandBitmap()
622 {
623 return getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize);
624 }
625
626 /// <summary>
627 /// Used to modify the bitmap between the x and y points. Points use 64 scale
628 /// </summary>
629 /// <param name="start_x"></param>
630 /// <param name="start_y"></param>
631 /// <param name="end_x"></param>
632 /// <param name="end_y"></param>
633 /// <returns></returns>
634 public bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
635 {
636 bool[,] tempBitmap = new bool[64,64];
637 tempBitmap.Initialize();
638
639 tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
640 return tempBitmap;
641 }
642
643 /// <summary>
644 /// Change a land bitmap at within a square and set those points to a specific value
645 /// </summary>
646 /// <param name="land_bitmap"></param>
647 /// <param name="start_x"></param>
648 /// <param name="start_y"></param>
649 /// <param name="end_x"></param>
650 /// <param name="end_y"></param>
651 /// <param name="set_value"></param>
652 /// <returns></returns>
653 public bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
654 bool set_value)
655 {
656 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
657 {
658 //Throw an exception - The bitmap is not 64x64
659 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
660 }
661
662 int x, y;
663 for (y = 0; y < 64; y++)
664 {
665 for (x = 0; x < 64; x++)
666 {
667 if (x >= start_x/4 && x < end_x/4
668 && y >= start_y/4 && y < end_y/4)
669 {
670 land_bitmap[x, y] = set_value;
671 }
672 }
673 }
674 return land_bitmap;
675 }
676
677 /// <summary>
678 /// Join the true values of 2 bitmaps together
679 /// </summary>
680 /// <param name="bitmap_base"></param>
681 /// <param name="bitmap_add"></param>
682 /// <returns></returns>
683 public bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
684 {
685 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
686 {
687 //Throw an exception - The bitmap is not 64x64
688 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
689 }
690 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
691 {
692 //Throw an exception - The bitmap is not 64x64
693 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
694 }
695
696 int x, y;
697 for (y = 0; y < 64; y++)
698 {
699 for (x = 0; x < 64; x++)
700 {
701 if (bitmap_add[x, y])
702 {
703 bitmap_base[x, y] = true;
704 }
705 }
706 }
707 return bitmap_base;
708 }
709
710 #endregion
711
712 #region Object Select and Object Owner Listing
713
714 public void sendForceObjectSelect(int local_id, int request_type, IClientAPI remote_client)
715 {
716 List<uint> resultLocalIDs = new List<uint>();
717 foreach (SceneObjectGroup obj in primsOverMe)
718 {
719 if (obj.LocalId > 0)
720 {
721 if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.ownerID)
722 {
723 resultLocalIDs.Add(obj.LocalId);
724 }
725 // else if (request_type == LandManager.LAND_SELECT_OBJECTS_GROUP && ...) // TODO: group support
726 // {
727 // }
728 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
729 obj.OwnerID != remote_client.AgentId)
730 {
731 resultLocalIDs.Add(obj.LocalId);
732 }
733 }
734 }
735
736
737 bool firstCall = true;
738 int MAX_OBJECTS_PER_PACKET = 251;
739 ForceObjectSelectPacket pack = (ForceObjectSelectPacket) PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
740 // TODO: don't create new blocks if recycling an old packet
741 ForceObjectSelectPacket.DataBlock[] data;
742 while (resultLocalIDs.Count > 0)
743 {
744 if (firstCall)
745 {
746 pack._Header.ResetList = true;
747 firstCall = false;
748 }
749 else
750 {
751 pack._Header.ResetList = false;
752 }
753
754 if (resultLocalIDs.Count > MAX_OBJECTS_PER_PACKET)
755 {
756 data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET];
757 }
758 else
759 {
760 data = new ForceObjectSelectPacket.DataBlock[resultLocalIDs.Count];
761 }
762
763 int i;
764 for (i = 0; i < MAX_OBJECTS_PER_PACKET && resultLocalIDs.Count > 0; i++)
765 {
766 data[i] = new ForceObjectSelectPacket.DataBlock();
767 data[i].LocalID = Convert.ToUInt32(resultLocalIDs[0]);
768 resultLocalIDs.RemoveAt(0);
769 }
770 pack.Data = data;
771 remote_client.OutPacket((Packet) pack, ThrottleOutPacketType.Task);
772 }
773 }
774
775 /// <summary>
776 /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
777 /// aggreagete details such as the number of prims.
778 ///
779 /// </summary>
780 /// <param name="remote_client">
781 /// A <see cref="IClientAPI"/>
782 /// </param>
783 public void sendLandObjectOwners(IClientAPI remote_client)
784 {
785 Dictionary<LLUUID, int> primCount = new Dictionary<LLUUID, int>();
786 ParcelObjectOwnersReplyPacket pack
787 = (ParcelObjectOwnersReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
788 // TODO: don't create new blocks if recycling an old packet
789
790 foreach (SceneObjectGroup obj in primsOverMe)
791 {
792 try
793 {
794 if (!primCount.ContainsKey(obj.OwnerID))
795 {
796 primCount.Add(obj.OwnerID, 0);
797 }
798 }
799 catch (NullReferenceException)
800 {
801 m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
802 }
803 try
804 {
805 primCount[obj.OwnerID] += obj.PrimCount;
806 }
807 catch (KeyNotFoundException)
808 {
809 m_log.Error("[LAND]: Unable to match a prim with it's owner.");
810 }
811 }
812
813 int notifyCount = primCount.Count;
814
815 if (notifyCount > 0)
816 {
817 if (notifyCount > 32)
818 {
819 m_log.InfoFormat(
820 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
821 + " - a developer might want to investigate whether this is a hard limit", 32);
822
823 notifyCount = 32;
824 }
825
826 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
827 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
828
829 int num = 0;
830 foreach (LLUUID owner in primCount.Keys)
831 {
832 dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock();
833 dataBlock[num].Count = primCount[owner];
834 dataBlock[num].IsGroupOwned = false; //TODO: fix me when group support is added
835 dataBlock[num].OnlineStatus = true; //TODO: fix me later
836 dataBlock[num].OwnerID = owner;
837
838 num++;
839
840 if (num >= notifyCount)
841 {
842 break;
843 }
844 }
845
846 pack.Data = dataBlock;
847 }
848
849 remote_client.OutPacket(pack, ThrottleOutPacketType.Task);
850 }
851
852 public Dictionary<LLUUID, int> getLandObjectOwners()
853 {
854 Dictionary<LLUUID, int> ownersAndCount = new Dictionary<LLUUID, int>();
855 foreach (SceneObjectGroup obj in primsOverMe)
856 {
857 if (!ownersAndCount.ContainsKey(obj.OwnerID))
858 {
859 ownersAndCount.Add(obj.OwnerID, 0);
860 }
861 ownersAndCount[obj.OwnerID] += obj.PrimCount;
862 }
863 return ownersAndCount;
864 }
865
866 #endregion
867
868 #region Object Returning
869
870 public void returnObject(SceneObjectGroup obj)
871 {
872 }
873
874 public void returnLandObjects(int type, LLUUID owner)
875 {
876 }
877
878 #endregion
879
880 #region Object Adding/Removing from Parcel
881
882 public void resetLandPrimCounts()
883 {
884 landData.groupPrims = 0;
885 landData.ownerPrims = 0;
886 landData.otherPrims = 0;
887 landData.selectedPrims = 0;
888 primsOverMe.Clear();
889 }
890
891 public void addPrimToCount(SceneObjectGroup obj)
892 {
893 LLUUID prim_owner = obj.OwnerID;
894 int prim_count = obj.PrimCount;
895
896 if (obj.IsSelected)
897 {
898 landData.selectedPrims += prim_count;
899 }
900 else
901 {
902 if (prim_owner == landData.ownerID)
903 {
904 landData.ownerPrims += prim_count;
905 }
906 else
907 {
908 landData.otherPrims += prim_count;
909 }
910 }
911
912 primsOverMe.Add(obj);
913 }
914
915 public void removePrimFromCount(SceneObjectGroup obj)
916 {
917 if (primsOverMe.Contains(obj))
918 {
919 LLUUID prim_owner = obj.OwnerID;
920 int prim_count = obj.PrimCount;
921
922 if (prim_owner == landData.ownerID)
923 {
924 landData.ownerPrims -= prim_count;
925 }
926 else if (prim_owner == landData.groupID)
927 {
928 landData.groupPrims -= prim_count;
929 }
930 else
931 {
932 landData.otherPrims -= prim_count;
933 }
934
935 primsOverMe.Remove(obj);
936 }
937 }
938
939 #endregion
940
941 #endregion
942
943
944}
945
946 #endregion
947}