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