aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs
diff options
context:
space:
mode:
authorAdam Frisby2008-04-30 21:16:36 +0000
committerAdam Frisby2008-04-30 21:16:36 +0000
commitf5c312bc3c2567449c7268a54a08a54119f58d53 (patch)
tree424668a4bbec6873ebc5b8256f3671db102f5e9c /OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs
parent* Adds the AuthbuyerID field to sqlite and makes use of it. (diff)
downloadopensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.zip
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.gz
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.bz2
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.xz
* Refactored Environment/Modules directory - modules now reside in their own directory with any associated module-specific classes.
* Each module directory is currently inside one of the following category folders: Agent (Anything relating to do with Client<->Server communications.), Avatar (Anything to do with the avatar or presence inworld), Framework (Classes modules can use), Grid (Grid traffic, new OGS2 grid comms), Scripting (Scripting functions, etc), World (The enrivonment/scene, IE Sun/Tree modules.) * This should be moved into a seperate project file.
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}