aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Simulation/ParcelManager.cs
diff options
context:
space:
mode:
authorMW2007-06-27 15:28:52 +0000
committerMW2007-06-27 15:28:52 +0000
commit646bbbc84b8010e0dacbeed5342cdb045f46cc49 (patch)
tree770b34d19855363c3c113ab9a0af9a56d821d887 /OpenSim/Region/Simulation/ParcelManager.cs
downloadopensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.zip
opensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.gz
opensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.bz2
opensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.xz
Some work on restructuring the namespaces / project names. Note this doesn't compile yet as not all the code has been changed to use the new namespaces. Am committing it now for feedback on the namespaces.
Diffstat (limited to 'OpenSim/Region/Simulation/ParcelManager.cs')
-rw-r--r--OpenSim/Region/Simulation/ParcelManager.cs892
1 files changed, 892 insertions, 0 deletions
diff --git a/OpenSim/Region/Simulation/ParcelManager.cs b/OpenSim/Region/Simulation/ParcelManager.cs
new file mode 100644
index 0000000..d15d77d
--- /dev/null
+++ b/OpenSim/Region/Simulation/ParcelManager.cs
@@ -0,0 +1,892 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.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.Text;
31using libsecondlife;
32using libsecondlife.Packets;
33using OpenSim.Framework.Interfaces;
34using OpenSim.Framework.Types;
35using OpenSim.Region.Scenes;
36using Avatar = OpenSim.Region.Scenes.ScenePresence;
37
38namespace OpenSim.Region
39{
40
41
42 #region ParcelManager Class
43 /// <summary>
44 /// Handles Parcel objects and operations requiring information from other Parcel objects (divide, join, etc)
45 /// </summary>
46 public class ParcelManager : OpenSim.Framework.Interfaces.ILocalStorageParcelReceiver
47 {
48
49 #region Constants
50 //Parcel types set with flags in ParcelOverlay.
51 //Only one of these can be used.
52 public const byte PARCEL_TYPE_PUBLIC = (byte)0; //Equals 00000000
53 public const byte PARCEL_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001
54 public const byte PARCEL_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010
55 public const byte PARCEL_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011
56 public const byte PARCEL_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100
57 public const byte PARCEL_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101
58
59
60 //Flags that when set, a border on the given side will be placed
61 //NOTE: North and East is assumable by the west and south sides (if parcel to east has a west border, then I have an east border; etc)
62 //This took forever to figure out -- jeesh. /blame LL for even having to send these
63 public const byte PARCEL_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000
64 public const byte PARCEL_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000
65
66 //RequestResults (I think these are right, they seem to work):
67 public const int PARCEL_RESULT_ONE_PARCEL = 0; // The request they made contained only one parcel
68 public const int PARCEL_RESULT_MULTIPLE_PARCELS = 1; // The request they made contained more than one parcel
69
70 //These are other constants. Yay!
71 public const int START_PARCEL_LOCAL_ID = 1;
72 #endregion
73
74 #region Member Variables
75 public Dictionary<int, Parcel> parcelList = new Dictionary<int, Parcel>();
76 private int lastParcelLocalID = START_PARCEL_LOCAL_ID - 1;
77 private int[,] parcelIDList = new int[64, 64];
78
79 private Scene m_world;
80 private RegionInfo m_regInfo;
81
82 #endregion
83
84 #region Constructors
85 public ParcelManager(Scene world, RegionInfo reginfo)
86 {
87
88 m_world = world;
89 m_regInfo = reginfo;
90 parcelIDList.Initialize();
91
92 }
93 #endregion
94
95 #region Member Functions
96
97 #region Parcel From Storage Functions
98 public void ParcelFromStorage(ParcelData data)
99 {
100 Parcel new_parcel = new Parcel(data.ownerID, data.isGroupOwned, m_world);
101 new_parcel.parcelData = data.Copy();
102 new_parcel.setParcelBitmapFromByteArray();
103 addParcel(new_parcel);
104
105 }
106
107 public void NoParcelDataFromStorage()
108 {
109 resetSimParcels();
110 }
111 #endregion
112
113 #region Parcel Add/Remove/Get/Create
114 /// <summary>
115 /// Creates a basic Parcel object without an owner (a zeroed key)
116 /// </summary>
117 /// <returns></returns>
118 public Parcel createBaseParcel()
119 {
120 return new Parcel(new LLUUID(), false, m_world);
121 }
122
123 /// <summary>
124 /// Adds a parcel to the stored list and adds them to the parcelIDList to what they own
125 /// </summary>
126 /// <param name="new_parcel">The parcel being added</param>
127 public void addParcel(Parcel new_parcel)
128 {
129 lastParcelLocalID++;
130 new_parcel.parcelData.localID = lastParcelLocalID;
131 parcelList.Add(lastParcelLocalID, new_parcel.Copy());
132
133
134 bool[,] parcelBitmap = new_parcel.getParcelBitmap();
135 int x, y;
136 for (x = 0; x < 64; x++)
137 {
138 for (y = 0; y < 64; y++)
139 {
140 if (parcelBitmap[x, y])
141 {
142 parcelIDList[x, y] = lastParcelLocalID;
143 }
144 }
145 }
146 parcelList[lastParcelLocalID].forceUpdateParcelInfo();
147
148
149 }
150 /// <summary>
151 /// Removes a parcel from the list. Will not remove if local_id is still owning an area in parcelIDList
152 /// </summary>
153 /// <param name="local_id">Parcel.localID of the parcel to remove.</param>
154 public void removeParcel(int local_id)
155 {
156 int x, y;
157 for (x = 0; x < 64; x++)
158 {
159 for (y = 0; y < 64; y++)
160 {
161 if (parcelIDList[x, y] == local_id)
162 {
163 throw new Exception("Could not remove parcel. Still being used at " + x + ", " + y);
164 }
165 }
166 }
167 m_world.localStorage.RemoveParcel(parcelList[local_id].parcelData);
168 parcelList.Remove(local_id);
169 }
170
171 private void performFinalParcelJoin(Parcel master, Parcel slave)
172 {
173 int x, y;
174 bool[,] parcelBitmapSlave = slave.getParcelBitmap();
175 for (x = 0; x < 64; x++)
176 {
177 for (y = 0; y < 64; y++)
178 {
179 if (parcelBitmapSlave[x, y])
180 {
181 parcelIDList[x, y] = master.parcelData.localID;
182 }
183 }
184 }
185 removeParcel(slave.parcelData.localID);
186 }
187 /// <summary>
188 /// Get the parcel at the specified point
189 /// </summary>
190 /// <param name="x">Value between 0 - 256 on the x axis of the point</param>
191 /// <param name="y">Value between 0 - 256 on the y axis of the point</param>
192 /// <returns>Parcel at the point supplied</returns>
193 public Parcel getParcel(int x, int y)
194 {
195 if (x > 256 || y > 256 || x < 0 || y < 0)
196 {
197 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
198 }
199 else
200 {
201 return parcelList[parcelIDList[x / 4, y / 4]];
202 }
203
204 }
205 #endregion
206
207 #region Parcel Modification
208 /// <summary>
209 /// Subdivides a parcel
210 /// </summary>
211 /// <param name="start_x">West Point</param>
212 /// <param name="start_y">South Point</param>
213 /// <param name="end_x">East Point</param>
214 /// <param name="end_y">North Point</param>
215 /// <param name="attempting_user_id">LLUUID of user who is trying to subdivide</param>
216 /// <returns>Returns true if successful</returns>
217 private bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
218 {
219 //First, lets loop through the points and make sure they are all in the same parcel
220 //Get the parcel at start
221 Parcel startParcel = getParcel(start_x, start_y);
222 if (startParcel == null) return false; //No such parcel at the beginning
223
224 //Loop through the points
225 try
226 {
227 int totalX = end_x - start_x;
228 int totalY = end_y - start_y;
229 int x, y;
230 for (y = 0; y < totalY; y++)
231 {
232 for (x = 0; x < totalX; x++)
233 {
234 Parcel tempParcel = getParcel(start_x + x, start_y + y);
235 if (tempParcel == null) return false; //No such parcel at that point
236 if (tempParcel != startParcel) return false; //Subdividing over 2 parcels; no-no
237 }
238 }
239 }
240 catch (Exception)
241 {
242 return false; //Exception. For now, lets skip subdivision
243 }
244
245 //If we are still here, then they are subdividing within one parcel
246 //Check owner
247 if (startParcel.parcelData.ownerID != attempting_user_id)
248 {
249 return false; //They cant do this!
250 }
251
252 //Lets create a new parcel with bitmap activated at that point (keeping the old parcels info)
253 Parcel newParcel = startParcel.Copy();
254 newParcel.parcelData.parcelName = "Subdivision of " + newParcel.parcelData.parcelName;
255 newParcel.parcelData.globalID = LLUUID.Random();
256
257 newParcel.setParcelBitmap(Parcel.getSquareParcelBitmap(start_x, start_y, end_x, end_y));
258
259 //Now, lets set the subdivision area of the original to false
260 int startParcelIndex = startParcel.parcelData.localID;
261 parcelList[startParcelIndex].setParcelBitmap(Parcel.modifyParcelBitmapSquare(startParcel.getParcelBitmap(), start_x, start_y, end_x, end_y, false));
262 parcelList[startParcelIndex].forceUpdateParcelInfo();
263
264
265 //Now add the new parcel
266 addParcel(newParcel);
267
268
269
270
271
272 return true;
273 }
274 /// <summary>
275 /// Join 2 parcels together
276 /// </summary>
277 /// <param name="start_x">x value in first parcel</param>
278 /// <param name="start_y">y value in first parcel</param>
279 /// <param name="end_x">x value in second parcel</param>
280 /// <param name="end_y">y value in second parcel</param>
281 /// <param name="attempting_user_id">LLUUID of the avatar trying to join the parcels</param>
282 /// <returns>Returns true if successful</returns>
283 private bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
284 {
285 end_x -= 4;
286 end_y -= 4;
287
288 //NOTE: The following only connects the parcels in each corner and not all the parcels that are within the selection box!
289 //This should be fixed later -- somewhat "incomplete code" --Ming
290 Parcel startParcel, endParcel;
291
292 try
293 {
294 startParcel = getParcel(start_x, start_y);
295 endParcel = getParcel(end_x, end_y);
296 }
297 catch (Exception)
298 {
299 return false; //Error occured when trying to get the start and end parcels
300 }
301 if (startParcel == endParcel)
302 {
303 return false; //Subdivision of the same parcel is not allowed
304 }
305
306 //Check the parcel owners:
307 if (startParcel.parcelData.ownerID != endParcel.parcelData.ownerID)
308 {
309 return false;
310 }
311 if (startParcel.parcelData.ownerID != attempting_user_id)
312 {
313 //TODO: Group editing stuff. Avatar owner support for now
314 return false;
315 }
316
317 //Same owners! Lets join them
318 //Merge them to startParcel
319 parcelList[startParcel.parcelData.localID].setParcelBitmap(Parcel.mergeParcelBitmaps(startParcel.getParcelBitmap(), endParcel.getParcelBitmap()));
320 performFinalParcelJoin(startParcel, endParcel);
321
322 return true;
323
324
325
326 }
327 #endregion
328
329 #region Parcel Updating
330 /// <summary>
331 /// Where we send the ParcelOverlay packet to the client
332 /// </summary>
333 /// <param name="remote_client">The object representing the client</param>
334 public void sendParcelOverlay(IClientAPI remote_client)
335 {
336 const int PARCEL_BLOCKS_PER_PACKET = 1024;
337 int x, y = 0;
338 byte[] byteArray = new byte[PARCEL_BLOCKS_PER_PACKET];
339 int byteArrayCount = 0;
340 int sequenceID = 0;
341 ParcelOverlayPacket packet;
342
343 for (y = 0; y < 64; y++)
344 {
345 for (x = 0; x < 64; x++)
346 {
347 byte tempByte = (byte)0; //This represents the byte for the current 4x4
348 Parcel currentParcelBlock = getParcel(x * 4, y * 4);
349
350 if (currentParcelBlock.parcelData.ownerID == remote_client.AgentId)
351 {
352 //Owner Flag
353 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_OWNED_BY_REQUESTER);
354 }
355 else if (currentParcelBlock.parcelData.salePrice > 0 && (currentParcelBlock.parcelData.authBuyerID == LLUUID.Zero || currentParcelBlock.parcelData.authBuyerID == remote_client.AgentId))
356 {
357 //Sale Flag
358 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_IS_FOR_SALE);
359 }
360 else if (currentParcelBlock.parcelData.ownerID == LLUUID.Zero)
361 {
362 //Public Flag
363 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_PUBLIC);
364 }
365 else
366 {
367 //Other Flag
368 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_OWNED_BY_OTHER);
369 }
370
371
372 //Now for border control
373 if (x == 0)
374 {
375 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_WEST);
376 }
377 else if (getParcel((x - 1) * 4, y * 4) != currentParcelBlock)
378 {
379 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_WEST);
380 }
381
382 if (y == 0)
383 {
384 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_SOUTH);
385 }
386 else if (getParcel(x * 4, (y - 1) * 4) != currentParcelBlock)
387 {
388 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_SOUTH);
389 }
390
391 byteArray[byteArrayCount] = tempByte;
392 byteArrayCount++;
393 if (byteArrayCount >= PARCEL_BLOCKS_PER_PACKET)
394 {
395 byteArrayCount = 0;
396 packet = new ParcelOverlayPacket();
397 packet.ParcelData.Data = byteArray;
398 packet.ParcelData.SequenceID = sequenceID;
399 remote_client.OutPacket((Packet)packet);
400 sequenceID++;
401 byteArray = new byte[PARCEL_BLOCKS_PER_PACKET];
402 }
403 }
404 }
405
406 packet = new ParcelOverlayPacket();
407 packet.ParcelData.Data = byteArray;
408 packet.ParcelData.SequenceID = sequenceID; //Eh?
409 remote_client.OutPacket((Packet)packet);
410 }
411
412 public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, IClientAPI remote_client)
413 {
414 //Get the parcels within the bounds
415 List<Parcel> temp = new List<Parcel>();
416 int x, y, i;
417 int inc_x = end_x - start_x;
418 int inc_y = end_y - start_y;
419 for (x = 0; x < inc_x; x++)
420 {
421 for (y = 0; y < inc_y; y++)
422 {
423 OpenSim.Region.Parcel currentParcel = getParcel(start_x + x, start_y + y);
424 if (!temp.Contains(currentParcel))
425 {
426 currentParcel.forceUpdateParcelInfo();
427 temp.Add(currentParcel);
428 }
429 }
430 }
431
432 int requestResult = ParcelManager.PARCEL_RESULT_ONE_PARCEL;
433 if (temp.Count > 1)
434 {
435 requestResult = ParcelManager.PARCEL_RESULT_MULTIPLE_PARCELS;
436 }
437
438 for (i = 0; i < temp.Count; i++)
439 {
440 temp[i].sendParcelProperties(sequence_id, snap_selection, requestResult, remote_client);
441 }
442
443
444 sendParcelOverlay(remote_client);
445 }
446
447 public void handleParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client)
448 {
449 if (parcelList.ContainsKey(packet.ParcelData.LocalID))
450 {
451 parcelList[packet.ParcelData.LocalID].updateParcelProperties(packet, remote_client);
452 }
453 }
454 public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
455 {
456 subdivide(west, south, east, north, remote_client.AgentId);
457 }
458 public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
459 {
460 join(west, south, east, north, remote_client.AgentId);
461
462 }
463 #endregion
464
465 /// <summary>
466 /// Resets the sim to the default parcel (full sim parcel owned by the default user)
467 /// </summary>
468 public void resetSimParcels()
469 {
470 //Remove all the parcels in the sim and add a blank, full sim parcel set to public
471 parcelList.Clear();
472 lastParcelLocalID = START_PARCEL_LOCAL_ID - 1;
473 parcelIDList.Initialize();
474
475 Parcel fullSimParcel = new Parcel(LLUUID.Zero, false, m_world);
476
477 fullSimParcel.setParcelBitmap(Parcel.getSquareParcelBitmap(0, 0, 256, 256));
478 fullSimParcel.parcelData.parcelName = "Your Sim Parcel";
479 fullSimParcel.parcelData.parcelDesc = "";
480
481 fullSimParcel.parcelData.ownerID = m_regInfo.MasterAvatarAssignedUUID;
482 fullSimParcel.parcelData.salePrice = 1;
483 fullSimParcel.parcelData.parcelFlags = libsecondlife.Parcel.ParcelFlags.ForSale;
484 fullSimParcel.parcelData.parcelStatus = libsecondlife.Parcel.ParcelStatus.Leased;
485
486 addParcel(fullSimParcel);
487
488 }
489 #endregion
490 }
491 #endregion
492
493
494 #region Parcel Class
495 /// <summary>
496 /// Keeps track of a specific parcel's information
497 /// </summary>
498 public class Parcel
499 {
500 #region Member Variables
501 public ParcelData parcelData = new ParcelData();
502 public Scene m_world;
503
504 private bool[,] parcelBitmap = new bool[64, 64];
505
506 #endregion
507
508
509 #region Constructors
510 public Parcel(LLUUID owner_id, bool is_group_owned, Scene world)
511 {
512 m_world = world;
513 parcelData.ownerID = owner_id;
514 parcelData.isGroupOwned = is_group_owned;
515
516 }
517 #endregion
518
519
520 #region Member Functions
521
522 #region General Functions
523 /// <summary>
524 /// Checks to see if this parcel contains a point
525 /// </summary>
526 /// <param name="x"></param>
527 /// <param name="y"></param>
528 /// <returns>Returns true if the parcel contains the specified point</returns>
529 public bool containsPoint(int x, int y)
530 {
531 if (x >= 0 && y >= 0 && x <= 256 && x <= 256)
532 {
533 return (parcelBitmap[x / 4, y / 4] == true);
534 }
535 else
536 {
537 return false;
538 }
539 }
540
541 public Parcel Copy()
542 {
543 Parcel newParcel = new Parcel(this.parcelData.ownerID, this.parcelData.isGroupOwned, m_world);
544
545 //Place all new variables here!
546 newParcel.parcelBitmap = (bool[,])(this.parcelBitmap.Clone());
547 newParcel.parcelData = parcelData.Copy();
548
549 return newParcel;
550 }
551
552 #endregion
553
554
555 #region Packet Request Handling
556 /// <summary>
557 /// Sends parcel properties as requested
558 /// </summary>
559 /// <param name="sequence_id">ID sent by client for them to keep track of</param>
560 /// <param name="snap_selection">Bool sent by client for them to use</param>
561 /// <param name="remote_client">Object representing the client</param>
562 public void sendParcelProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
563 {
564
565 ParcelPropertiesPacket updatePacket = new ParcelPropertiesPacket();
566 updatePacket.ParcelData.AABBMax = parcelData.AABBMax;
567 updatePacket.ParcelData.AABBMin = parcelData.AABBMin;
568 updatePacket.ParcelData.Area = parcelData.area;
569 updatePacket.ParcelData.AuctionID = parcelData.auctionID;
570 updatePacket.ParcelData.AuthBuyerID = parcelData.authBuyerID; //unemplemented
571
572 updatePacket.ParcelData.Bitmap = parcelData.parcelBitmapByteArray;
573
574 updatePacket.ParcelData.Desc = libsecondlife.Helpers.StringToField(parcelData.parcelDesc);
575 updatePacket.ParcelData.Category = (byte)parcelData.category;
576 updatePacket.ParcelData.ClaimDate = parcelData.claimDate;
577 updatePacket.ParcelData.ClaimPrice = parcelData.claimPrice;
578 updatePacket.ParcelData.GroupID = parcelData.groupID;
579 updatePacket.ParcelData.GroupPrims = parcelData.groupPrims;
580 updatePacket.ParcelData.IsGroupOwned = parcelData.isGroupOwned;
581 updatePacket.ParcelData.LandingType = (byte)parcelData.landingType;
582 updatePacket.ParcelData.LocalID = parcelData.localID;
583 updatePacket.ParcelData.MaxPrims = 1000; //unemplemented
584 updatePacket.ParcelData.MediaAutoScale = parcelData.mediaAutoScale;
585 updatePacket.ParcelData.MediaID = parcelData.mediaID;
586 updatePacket.ParcelData.MediaURL = Helpers.StringToField(parcelData.mediaURL);
587 updatePacket.ParcelData.MusicURL = Helpers.StringToField(parcelData.musicURL);
588 updatePacket.ParcelData.Name = Helpers.StringToField(parcelData.parcelName);
589 updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented
590 updatePacket.ParcelData.OtherCount = 0; //unemplemented
591 updatePacket.ParcelData.OtherPrims = 0; //unemplented
592 updatePacket.ParcelData.OwnerID = parcelData.ownerID;
593 updatePacket.ParcelData.OwnerPrims = 0; //unemplemented
594 updatePacket.ParcelData.ParcelFlags = (uint)parcelData.parcelFlags; //unemplemented
595 updatePacket.ParcelData.ParcelPrimBonus = (float)1.0; //unemplemented
596 updatePacket.ParcelData.PassHours = parcelData.passHours;
597 updatePacket.ParcelData.PassPrice = parcelData.passPrice;
598 updatePacket.ParcelData.PublicCount = 0; //unemplemented
599 updatePacket.ParcelData.RegionDenyAnonymous = false; //unemplemented
600 updatePacket.ParcelData.RegionDenyIdentified = false; //unemplemented
601 updatePacket.ParcelData.RegionDenyTransacted = false; //unemplemented
602 updatePacket.ParcelData.RegionPushOverride = true; //unemplemented
603 updatePacket.ParcelData.RentPrice = 0; //??
604 updatePacket.ParcelData.RequestResult = request_result;
605 updatePacket.ParcelData.SalePrice = parcelData.salePrice; //unemplemented
606 updatePacket.ParcelData.SelectedPrims = 0; //unemeplemented
607 updatePacket.ParcelData.SelfCount = 0;//unemplemented
608 updatePacket.ParcelData.SequenceID = sequence_id;
609 updatePacket.ParcelData.SimWideMaxPrims = 15000; //unemplemented
610 updatePacket.ParcelData.SimWideTotalPrims = 0; //unemplemented
611 updatePacket.ParcelData.SnapSelection = snap_selection;
612 updatePacket.ParcelData.SnapshotID = parcelData.snapshotID;
613 updatePacket.ParcelData.Status = (byte)parcelData.parcelStatus;
614 updatePacket.ParcelData.TotalPrims = 0; //unemplemented
615 updatePacket.ParcelData.UserLocation = parcelData.userLocation;
616 updatePacket.ParcelData.UserLookAt = parcelData.userLookAt;
617 remote_client.OutPacket((Packet)updatePacket);
618 }
619
620 public void updateParcelProperties(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client)
621 {
622 if (remote_client.AgentId == parcelData.ownerID)
623 {
624 //Needs later group support
625 parcelData.authBuyerID = packet.ParcelData.AuthBuyerID;
626 parcelData.category = (libsecondlife.Parcel.ParcelCategory)packet.ParcelData.Category;
627 parcelData.parcelDesc = Helpers.FieldToUTF8String(packet.ParcelData.Desc);
628 parcelData.groupID = packet.ParcelData.GroupID;
629 parcelData.landingType = packet.ParcelData.LandingType;
630 parcelData.mediaAutoScale = packet.ParcelData.MediaAutoScale;
631 parcelData.mediaID = packet.ParcelData.MediaID;
632 parcelData.mediaURL = Helpers.FieldToUTF8String(packet.ParcelData.MediaURL);
633 parcelData.musicURL = Helpers.FieldToUTF8String(packet.ParcelData.MusicURL);
634 parcelData.parcelName = libsecondlife.Helpers.FieldToUTF8String(packet.ParcelData.Name);
635 parcelData.parcelFlags = (libsecondlife.Parcel.ParcelFlags)packet.ParcelData.ParcelFlags;
636 parcelData.passHours = packet.ParcelData.PassHours;
637 parcelData.passPrice = packet.ParcelData.PassPrice;
638 parcelData.salePrice = packet.ParcelData.SalePrice;
639 parcelData.snapshotID = packet.ParcelData.SnapshotID;
640 parcelData.userLocation = packet.ParcelData.UserLocation;
641 parcelData.userLookAt = packet.ParcelData.UserLookAt;
642
643 List<Avatar> avatars = m_world.RequestAvatarList();
644
645 for (int i = 0; i < avatars.Count; i++)
646 {
647 Parcel over = m_world.parcelManager.getParcel((int)Math.Round(avatars[i].Pos.X), (int)Math.Round(avatars[i].Pos.Y));
648 if (over == this)
649 {
650 sendParcelProperties(0, false, 0, avatars[i].ControllingClient);
651 }
652 }
653
654 }
655 }
656 #endregion
657
658
659 #region Update Functions
660 /// <summary>
661 /// Updates the AABBMin and AABBMax values after area/shape modification of parcel
662 /// </summary>
663 private void updateAABBAndAreaValues()
664 {
665 int min_x = 64;
666 int min_y = 64;
667 int max_x = 0;
668 int max_y = 0;
669 int tempArea = 0;
670 int x, y;
671 for (x = 0; x < 64; x++)
672 {
673 for (y = 0; y < 64; y++)
674 {
675 if (parcelBitmap[x, y] == true)
676 {
677 if (min_x > x) min_x = x;
678 if (min_y > y) min_y = y;
679 if (max_x < x) max_x = x;
680 if (max_y < y) max_y = y;
681 tempArea += 16; //16sqm parcel
682 }
683 }
684 }
685 parcelData.AABBMin = new LLVector3((float)(min_x * 4), (float)(min_y * 4), m_world.Terrain[(min_x * 4), (min_y * 4)]);
686 parcelData.AABBMax = new LLVector3((float)(max_x * 4), (float)(max_y * 4), m_world.Terrain[(max_x * 4), (max_y * 4)]);
687 parcelData.area = tempArea;
688 }
689
690 public void updateParcelBitmapByteArray()
691 {
692 parcelData.parcelBitmapByteArray = convertParcelBitmapToBytes();
693 }
694
695 /// <summary>
696 /// Update all settings in parcel such as area, bitmap byte array, etc
697 /// </summary>
698 public void forceUpdateParcelInfo()
699 {
700 this.updateAABBAndAreaValues();
701 this.updateParcelBitmapByteArray();
702 }
703
704 public void setParcelBitmapFromByteArray()
705 {
706 parcelBitmap = convertBytesToParcelBitmap();
707 }
708 #endregion
709
710
711 #region Parcel Bitmap Functions
712 /// <summary>
713 /// Sets the parcel's bitmap manually
714 /// </summary>
715 /// <param name="bitmap">64x64 block representing where this parcel is on a map</param>
716 public void setParcelBitmap(bool[,] bitmap)
717 {
718 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
719 {
720 //Throw an exception - The bitmap is not 64x64
721 throw new Exception("Error: Invalid Parcel Bitmap");
722 }
723 else
724 {
725 //Valid: Lets set it
726 parcelBitmap = bitmap;
727 forceUpdateParcelInfo();
728
729 }
730 }
731 /// <summary>
732 /// Gets the parcels bitmap manually
733 /// </summary>
734 /// <returns></returns>
735 public bool[,] getParcelBitmap()
736 {
737 return parcelBitmap;
738 }
739 /// <summary>
740 /// Converts the parcel bitmap to a packet friendly byte array
741 /// </summary>
742 /// <returns></returns>
743 private byte[] convertParcelBitmapToBytes()
744 {
745 byte[] tempConvertArr = new byte[512];
746 byte tempByte = 0;
747 int x, y, i, byteNum = 0;
748 i = 0;
749 for (y = 0; y < 64; y++)
750 {
751 for (x = 0; x < 64; x++)
752 {
753 tempByte = Convert.ToByte(tempByte | Convert.ToByte(parcelBitmap[x, y]) << (i++ % 8));
754 if (i % 8 == 0)
755 {
756 tempConvertArr[byteNum] = tempByte;
757 tempByte = (byte)0;
758 i = 0;
759 byteNum++;
760 }
761 }
762 }
763 return tempConvertArr;
764 }
765
766 private bool[,] convertBytesToParcelBitmap()
767 {
768 bool[,] tempConvertMap = new bool[64, 64];
769 tempConvertMap.Initialize();
770 byte tempByte = 0;
771 int x = 0, y = 0, i = 0, bitNum = 0;
772 for (i = 0; i < 512; i++)
773 {
774 tempByte = parcelData.parcelBitmapByteArray[i];
775 for (bitNum = 0; bitNum < 8; bitNum++)
776 {
777 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte)1);
778 tempConvertMap[x, y] = bit;
779 x++;
780 if (x > 63)
781 {
782 x = 0;
783 y++;
784 }
785
786 }
787
788 }
789 return tempConvertMap;
790 }
791 /// <summary>
792 /// Full sim parcel creation
793 /// </summary>
794 /// <returns></returns>
795 public static bool[,] basicFullRegionParcelBitmap()
796 {
797 return getSquareParcelBitmap(0, 0, 256, 256);
798 }
799
800 /// <summary>
801 /// Used to modify the bitmap between the x and y points. Points use 64 scale
802 /// </summary>
803 /// <param name="start_x"></param>
804 /// <param name="start_y"></param>
805 /// <param name="end_x"></param>
806 /// <param name="end_y"></param>
807 /// <returns></returns>
808 public static bool[,] getSquareParcelBitmap(int start_x, int start_y, int end_x, int end_y)
809 {
810
811 bool[,] tempBitmap = new bool[64, 64];
812 tempBitmap.Initialize();
813
814 tempBitmap = modifyParcelBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
815 return tempBitmap;
816 }
817
818 /// <summary>
819 /// Change a parcel's bitmap at within a square and set those points to a specific value
820 /// </summary>
821 /// <param name="parcel_bitmap"></param>
822 /// <param name="start_x"></param>
823 /// <param name="start_y"></param>
824 /// <param name="end_x"></param>
825 /// <param name="end_y"></param>
826 /// <param name="set_value"></param>
827 /// <returns></returns>
828 public static bool[,] modifyParcelBitmapSquare(bool[,] parcel_bitmap, int start_x, int start_y, int end_x, int end_y, bool set_value)
829 {
830 if (parcel_bitmap.GetLength(0) != 64 || parcel_bitmap.GetLength(1) != 64 || parcel_bitmap.Rank != 2)
831 {
832 //Throw an exception - The bitmap is not 64x64
833 throw new Exception("Error: Invalid Parcel Bitmap in modifyParcelBitmapSquare()");
834 }
835
836 int x, y;
837 for (y = 0; y < 64; y++)
838 {
839 for (x = 0; x < 64; x++)
840 {
841 if (x >= start_x / 4 && x < end_x / 4
842 && y >= start_y / 4 && y < end_y / 4)
843 {
844 parcel_bitmap[x, y] = set_value;
845 }
846 }
847 }
848 return parcel_bitmap;
849 }
850 /// <summary>
851 /// Join the true values of 2 bitmaps together
852 /// </summary>
853 /// <param name="bitmap_base"></param>
854 /// <param name="bitmap_add"></param>
855 /// <returns></returns>
856 public static bool[,] mergeParcelBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
857 {
858 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
859 {
860 //Throw an exception - The bitmap is not 64x64
861 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeParcelBitmaps");
862 }
863 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
864 {
865 //Throw an exception - The bitmap is not 64x64
866 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeParcelBitmaps");
867
868 }
869
870 int x, y;
871 for (y = 0; y < 64; y++)
872 {
873 for (x = 0; x < 64; x++)
874 {
875 if (bitmap_add[x, y])
876 {
877 bitmap_base[x, y] = true;
878 }
879 }
880 }
881 return bitmap_base;
882 }
883 #endregion
884
885 #endregion
886
887
888 }
889 #endregion
890
891
892}