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