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