diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs | 947 |
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using libsecondlife; | ||
32 | using libsecondlife.Packets; | ||
33 | using log4net; | ||
34 | using OpenSim.Framework; | ||
35 | using OpenSim.Region.Environment.Interfaces; | ||
36 | using OpenSim.Region.Environment.Scenes; | ||
37 | |||
38 | namespace 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 | } | ||