aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/World/Land
diff options
context:
space:
mode:
authorDr Scofield2009-02-10 13:10:57 +0000
committerDr Scofield2009-02-10 13:10:57 +0000
commit180be7de07014aa33bc6066f12a0819b731c1c9d (patch)
tree3aa13af3cda4b808fa9453655875327699b61311 /OpenSim/Region/Environment/Modules/World/Land
parentStopgap measure: To use gridlaunch, or GUI, start opensim with (diff)
downloadopensim-SC-180be7de07014aa33bc6066f12a0819b731c1c9d.zip
opensim-SC-180be7de07014aa33bc6066f12a0819b731c1c9d.tar.gz
opensim-SC-180be7de07014aa33bc6066f12a0819b731c1c9d.tar.bz2
opensim-SC-180be7de07014aa33bc6066f12a0819b731c1c9d.tar.xz
this is step 2 of 2 of the OpenSim.Region.Environment refactor.
NOTHING has been deleted or moved off to forge at this point. what has happened is that OpenSim.Region.Environment.Modules has been split in two: - OpenSim.Region.CoreModules: all those modules that are either directly or indirectly referenced from other OpenSim packages, or that provide functionality that the OpenSim developer community considers core functionality: CoreModules/Agent/AssetTransaction CoreModules/Agent/Capabilities CoreModules/Agent/TextureDownload CoreModules/Agent/TextureSender CoreModules/Agent/TextureSender/Tests CoreModules/Agent/Xfer CoreModules/Avatar/AvatarFactory CoreModules/Avatar/Chat/ChatModule CoreModules/Avatar/Combat CoreModules/Avatar/Currency/SampleMoney CoreModules/Avatar/Dialog CoreModules/Avatar/Friends CoreModules/Avatar/Gestures CoreModules/Avatar/Groups CoreModules/Avatar/InstantMessage CoreModules/Avatar/Inventory CoreModules/Avatar/Inventory/Archiver CoreModules/Avatar/Inventory/Transfer CoreModules/Avatar/Lure CoreModules/Avatar/ObjectCaps CoreModules/Avatar/Profiles CoreModules/Communications/Local CoreModules/Communications/REST CoreModules/Framework/EventQueue CoreModules/Framework/InterfaceCommander CoreModules/Hypergrid CoreModules/InterGrid CoreModules/Scripting/DynamicTexture CoreModules/Scripting/EMailModules CoreModules/Scripting/HttpRequest CoreModules/Scripting/LoadImageURL CoreModules/Scripting/VectorRender CoreModules/Scripting/WorldComm CoreModules/Scripting/XMLRPC CoreModules/World/Archiver CoreModules/World/Archiver/Tests CoreModules/World/Estate CoreModules/World/Land CoreModules/World/Permissions CoreModules/World/Serialiser CoreModules/World/Sound CoreModules/World/Sun CoreModules/World/Terrain CoreModules/World/Terrain/DefaultEffects CoreModules/World/Terrain/DefaultEffects/bin CoreModules/World/Terrain/DefaultEffects/bin/Debug CoreModules/World/Terrain/Effects CoreModules/World/Terrain/FileLoaders CoreModules/World/Terrain/FloodBrushes CoreModules/World/Terrain/PaintBrushes CoreModules/World/Terrain/Tests CoreModules/World/Vegetation CoreModules/World/Wind CoreModules/World/WorldMap - OpenSim.Region.OptionalModules: all those modules that are not core modules: OptionalModules/Avatar/Chat/IRC-stuff OptionalModules/Avatar/Concierge OptionalModules/Avatar/Voice/AsterixVoice OptionalModules/Avatar/Voice/SIPVoice OptionalModules/ContentManagementSystem OptionalModules/Grid/Interregion OptionalModules/Python OptionalModules/SvnSerialiser OptionalModules/World/NPC OptionalModules/World/TreePopulator
Diffstat (limited to 'OpenSim/Region/Environment/Modules/World/Land')
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs188
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs1347
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandObject.cs930
3 files changed, 0 insertions, 2465 deletions
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs b/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
deleted file mode 100644
index 76555d2..0000000
--- a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
+++ /dev/null
@@ -1,188 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes;
34
35namespace OpenSim.Region.Environment.Modules.World.Land
36{
37 public class LandChannel : ILandChannel
38 {
39 #region Constants
40
41 //Land types set with flags in ParcelOverlay.
42 //Only one of these can be used.
43 public const float BAN_LINE_SAFETY_HIEGHT = 100;
44 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000
45 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000
46
47 //RequestResults (I think these are right, they seem to work):
48 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
49 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
50
51 //ParcelSelectObjects
52 public const int LAND_SELECT_OBJECTS_GROUP = 4;
53 public const int LAND_SELECT_OBJECTS_OTHER = 8;
54 public const int LAND_SELECT_OBJECTS_OWNER = 2;
55 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
56 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
57 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
59 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
60 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
61
62 //These are other constants. Yay!
63 public const int START_LAND_LOCAL_ID = 1;
64
65 #endregion
66
67 private readonly Scene m_scene;
68 private readonly LandManagementModule m_landManagementModule;
69
70 public LandChannel(Scene scene, LandManagementModule landManagementMod)
71 {
72 m_scene = scene;
73 m_landManagementModule = landManagementMod;
74 }
75
76 #region ILandChannel Members
77
78
79 /// <summary>
80 /// Get the land object at the specified point
81 /// </summary>
82 /// <param name="x_float">Value between 0 - 256 on the x axis of the point</param>
83 /// <param name="y_float">Value between 0 - 256 on the y axis of the point</param>
84 /// <returns>Land object at the point supplied</returns>
85 public ILandObject GetLandObject(float x_float, float y_float)
86 {
87 if (m_landManagementModule != null)
88 {
89 return m_landManagementModule.GetLandObject(x_float, y_float);
90 }
91 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
92 obj.landData.Name = "NO LAND";
93 return obj;
94 }
95
96 public ILandObject GetLandObject(int x, int y)
97 {
98 if (m_landManagementModule != null)
99 {
100 return m_landManagementModule.GetLandObject(x, y);
101 }
102 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
103 obj.landData.Name = "NO LAND";
104 return obj;
105 }
106
107 public List<ILandObject> AllParcels()
108 {
109 if (m_landManagementModule != null)
110 {
111 return m_landManagementModule.AllParcels();
112 }
113
114 return new List<ILandObject>();
115 }
116
117 public List<ILandObject> ParcelsNearPoint(Vector3 position)
118 {
119 if (m_landManagementModule != null)
120 {
121 return m_landManagementModule.ParcelsNearPoint(position);
122 }
123
124 return new List<ILandObject>();
125 }
126
127 public bool IsLandPrimCountTainted()
128 {
129 if (m_landManagementModule != null)
130 {
131 return m_landManagementModule.IsLandPrimCountTainted();
132 }
133
134 return false;
135 }
136
137 public bool IsForcefulBansAllowed()
138 {
139 if (m_landManagementModule != null)
140 {
141 return m_landManagementModule.AllowedForcefulBans;
142 }
143
144 return false;
145 }
146
147 public void UpdateLandObject(int localID, LandData data)
148 {
149 if (m_landManagementModule != null)
150 {
151 m_landManagementModule.UpdateLandObject(localID, data);
152 }
153 }
154 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
155 {
156 if (m_landManagementModule != null)
157 {
158 m_landManagementModule.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient);
159 }
160 }
161
162 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
163 {
164 if (m_landManagementModule != null)
165 {
166 m_landManagementModule.setParcelObjectMaxOverride(overrideDel);
167 }
168 }
169
170 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
171 {
172 if (m_landManagementModule != null)
173 {
174 m_landManagementModule.setSimulatorObjectMaxOverride(overrideDel);
175 }
176 }
177
178 public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
179 {
180 if (m_landManagementModule != null)
181 {
182 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
183 }
184 }
185
186 #endregion
187 }
188}
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
deleted file mode 100644
index 58176e4..0000000
--- a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
+++ /dev/null
@@ -1,1347 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework;
38using OpenSim.Framework.Servers;
39using OpenSim.Framework.Communications.Capabilities;
40using OpenSim.Region.Physics.Manager;
41using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
42
43namespace OpenSim.Region.Environment.Modules.World.Land
44{
45 // used for caching
46 internal class ExtendedLandData {
47 public LandData landData;
48 public ulong regionHandle;
49 public uint x, y;
50 }
51
52 public class LandManagementModule : IRegionModule
53 {
54 private static readonly ILog m_log =
55 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 private static readonly string remoteParcelRequestPath = "0009/";
58
59 private LandChannel landChannel;
60 private Scene m_scene;
61
62 private readonly int[,] m_landIDList = new int[64, 64];
63 private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
64
65 private bool m_landPrimCountTainted;
66 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
67
68 private bool m_allowedForcefulBans = true;
69
70 // caches ExtendedLandData
71 private Cache parcelInfoCache;
72
73 #region IRegionModule Members
74
75 public void Initialise(Scene scene, IConfigSource source)
76 {
77 m_scene = scene;
78 m_landIDList.Initialize();
79 landChannel = new LandChannel(scene, this);
80
81 parcelInfoCache = new Cache();
82 parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache
83 parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0);
84
85 m_scene.EventManager.OnParcelPrimCountAdd += AddPrimToLandPrimCounts;
86 m_scene.EventManager.OnParcelPrimCountUpdate += UpdateLandPrimCounts;
87 m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(handleAvatarChangingParcel);
88 m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(handleAnyClientMovement);
89 m_scene.EventManager.OnValidateLandBuy += handleLandValidationRequest;
90 m_scene.EventManager.OnLandBuy += handleLandBuyRequest;
91 m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
92 m_scene.EventManager.OnSignificantClientMovement += handleSignificantClientMovement;
93 m_scene.EventManager.OnObjectBeingRemovedFromScene += RemovePrimFromLandPrimCounts;
94
95 m_scene.EventManager.OnNoticeNoLandDataFromStorage += this.NoLandDataFromStorage;
96 m_scene.EventManager.OnIncomingLandDataFromStorage += this.IncomingLandObjectsFromStorage;
97 m_scene.EventManager.OnSetAllowForcefulBan += this.SetAllowedForcefulBans;
98 m_scene.EventManager.OnRequestParcelPrimCountUpdate += this.PerformParcelPrimCountUpdate;
99 m_scene.EventManager.OnParcelPrimCountTainted += this.SetPrimsTainted;
100 m_scene.EventManager.OnRegisterCaps += this.OnRegisterCaps;
101
102 lock (m_scene)
103 {
104 m_scene.LandChannel = (ILandChannel) landChannel;
105 }
106 }
107
108 void EventManager_OnNewClient(IClientAPI client)
109 {
110 //Register some client events
111 client.OnParcelPropertiesRequest += new ParcelPropertiesRequest(handleParcelPropertiesRequest);
112 client.OnParcelDivideRequest += new ParcelDivideRequest(handleParcelDivideRequest);
113 client.OnParcelJoinRequest += new ParcelJoinRequest(handleParcelJoinRequest);
114 client.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(handleParcelPropertiesUpdateRequest);
115 client.OnParcelSelectObjects += new ParcelSelectObjects(handleParcelSelectObjectsRequest);
116 client.OnParcelObjectOwnerRequest += new ParcelObjectOwnerRequest(handleParcelObjectOwnersRequest);
117 client.OnParcelAccessListRequest += new ParcelAccessListRequest(handleParcelAccessRequest);
118 client.OnParcelAccessListUpdateRequest += new ParcelAccessListUpdateRequest(handleParcelAccessUpdateRequest);
119 client.OnParcelAbandonRequest += new ParcelAbandonRequest(handleParcelAbandonRequest);
120 client.OnParcelGodForceOwner += new ParcelGodForceOwner(handleParcelGodForceOwner);
121 client.OnParcelReclaim += new ParcelReclaim(handleParcelReclaim);
122 client.OnParcelInfoRequest += new ParcelInfoRequest(handleParcelInfo);
123 client.OnParcelDwellRequest += new ParcelDwellRequest(handleParcelDwell);
124 if (m_scene.Entities.ContainsKey(client.AgentId))
125 {
126 SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true);
127 SendParcelOverlay(client);
128 }
129 }
130
131 public void PostInitialise()
132 {
133 }
134
135 public void Close()
136 {
137 }
138
139 public string Name
140 {
141 get { return "LandManagementModule"; }
142 }
143
144 public bool IsSharedModule
145 {
146 get { return false; }
147 }
148
149 #endregion
150
151 #region Parcel Add/Remove/Get/Create
152
153 public void SetAllowedForcefulBans(bool forceful)
154 {
155 AllowedForcefulBans = forceful;
156 }
157
158 public void UpdateLandObject(int local_id, LandData data)
159 {
160 LandData newData = data.Copy();
161 newData.LocalID = local_id;
162
163 lock (m_landList)
164 {
165 if (m_landList.ContainsKey(local_id))
166 {
167 m_landList[local_id].landData = newData;
168 m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]);
169 }
170 }
171 }
172
173 public bool AllowedForcefulBans
174 {
175 get { return m_allowedForcefulBans; }
176 set { m_allowedForcefulBans = value; }
177 }
178
179 /// <summary>
180 /// Resets the sim to the default land object (full sim piece of land owned by the default user)
181 /// </summary>
182 public void ResetSimLandObjects()
183 {
184 //Remove all the land objects in the sim and add a blank, full sim land object set to public
185 lock (m_landList)
186 {
187 m_landList.Clear();
188 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
189 m_landIDList.Initialize();
190 }
191
192 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
193
194 fullSimParcel.setLandBitmap(fullSimParcel.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
195 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
196 fullSimParcel.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
197 else
198 fullSimParcel.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
199 fullSimParcel.landData.ClaimDate = Util.UnixTimeSinceEpoch();
200 AddLandObject(fullSimParcel);
201 }
202
203 public List<ILandObject> AllParcels()
204 {
205 lock (m_landList)
206 {
207 return new List<ILandObject>(m_landList.Values);
208 }
209 }
210
211 public List<ILandObject> ParcelsNearPoint(Vector3 position)
212 {
213 List<ILandObject> parcelsNear = new List<ILandObject>();
214 for (int x = -4; x <= 4; x += 4)
215 {
216 for (int y = -4; y <= 4; y += 4)
217 {
218 ILandObject check = GetLandObject(position.X + x, position.Y + y);
219 if (check != null)
220 {
221 if (!parcelsNear.Contains(check))
222 {
223 parcelsNear.Add(check);
224 }
225 }
226 }
227 }
228
229 return parcelsNear;
230 }
231
232 public void SendYouAreBannedNotice(ScenePresence avatar)
233 {
234 if (AllowedForcefulBans)
235 {
236 avatar.ControllingClient.SendAlertMessage(
237 "You are not allowed on this parcel because you are banned. Please go away.");
238
239 avatar.PhysicsActor.Position =
240 new PhysicsVector(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y,
241 avatar.lastKnownAllowedPosition.Z);
242 avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0);
243 }
244 else
245 {
246 avatar.ControllingClient.SendAlertMessage(
247 "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!");
248 }
249 }
250
251 public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, UUID regionID)
252 {
253 if (m_scene.RegionInfo.RegionID == regionID)
254 {
255 ILandObject parcelAvatarIsEntering;
256 lock (m_landList)
257 {
258 parcelAvatarIsEntering = m_landList[localLandID];
259 }
260
261 if (parcelAvatarIsEntering != null)
262 {
263 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
264 {
265 if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID))
266 {
267 SendYouAreBannedNotice(avatar);
268 }
269 else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID))
270 {
271 avatar.ControllingClient.SendAlertMessage(
272 "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!).");
273 }
274 else
275 {
276 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
277 }
278 }
279 else
280 {
281 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
282 }
283 }
284 }
285 }
286
287 public void SendOutNearestBanLine(IClientAPI avatar)
288 {
289 List<ScenePresence> avatars = m_scene.GetAvatars();
290 foreach (ScenePresence presence in avatars)
291 {
292 if (presence.UUID == avatar.AgentId)
293 {
294 List<ILandObject> checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition);
295 foreach (ILandObject checkBan in checkLandParcels)
296 {
297 if (checkBan.isBannedFromLand(avatar.AgentId))
298 {
299 checkBan.sendLandProperties((int)ParcelStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar);
300 return; //Only send one
301 }
302 if (checkBan.isRestrictedFromLand(avatar.AgentId))
303 {
304 checkBan.sendLandProperties((int)ParcelStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar);
305 return; //Only send one
306 }
307 }
308 return;
309 }
310 }
311 }
312
313 public void SendLandUpdate(ScenePresence avatar, bool force)
314 {
315 ILandObject over = GetLandObject((int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
316 (int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
317
318 if (over != null)
319 {
320 if (force)
321 {
322 if (!avatar.IsChildAgent)
323 {
324 over.sendLandUpdateToClient(avatar.ControllingClient);
325 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID,
326 m_scene.RegionInfo.RegionID);
327 }
328 }
329
330 if (avatar.currentParcelUUID != over.landData.GlobalID)
331 {
332 if (!avatar.IsChildAgent)
333 {
334 over.sendLandUpdateToClient(avatar.ControllingClient);
335 avatar.currentParcelUUID = over.landData.GlobalID;
336 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID,
337 m_scene.RegionInfo.RegionID);
338 }
339 }
340 }
341 }
342
343 public void SendLandUpdate(ScenePresence avatar)
344 {
345 SendLandUpdate(avatar, false);
346 }
347
348 public void handleSignificantClientMovement(IClientAPI remote_client)
349 {
350 ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId);
351
352 if (clientAvatar != null)
353 {
354 SendLandUpdate(clientAvatar);
355 SendOutNearestBanLine(remote_client);
356 ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
357 if (parcel != null)
358 {
359 if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
360 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown)
361 {
362 handleAvatarChangingParcel(clientAvatar, parcel.landData.LocalID, m_scene.RegionInfo.RegionID);
363 //They are going below the safety line!
364 if (!parcel.isBannedFromLand(clientAvatar.UUID))
365 {
366 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
367 }
368 }
369 else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
370 parcel.isBannedFromLand(clientAvatar.UUID))
371 {
372 SendYouAreBannedNotice(clientAvatar);
373 }
374 }
375 }
376 }
377
378 public void handleAnyClientMovement(ScenePresence avatar)
379 //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance.
380 {
381 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
382 if (over != null)
383 {
384 if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)
385 {
386 avatar.lastKnownAllowedPosition =
387 new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
388 }
389 }
390 }
391
392
393 public void handleParcelAccessRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID,
394 int landLocalID, IClientAPI remote_client)
395 {
396 ILandObject land;
397 lock (m_landList)
398 {
399 m_landList.TryGetValue(landLocalID, out land);
400 }
401
402 if (land != null)
403 {
404 m_landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
405 }
406 }
407
408 public void handleParcelAccessUpdateRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID,
409 List<ParcelManager.ParcelAccessEntry> entries,
410 IClientAPI remote_client)
411 {
412 ILandObject land;
413 lock (m_landList)
414 {
415 m_landList.TryGetValue(landLocalID, out land);
416 }
417
418 if (land != null)
419 {
420 if (agentID == land.landData.OwnerID)
421 {
422 land.updateAccessList(flags, entries, remote_client);
423 }
424 }
425 else
426 {
427 m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID);
428 }
429 }
430
431 /// <summary>
432 /// Creates a basic Parcel object without an owner (a zeroed key)
433 /// </summary>
434 /// <returns></returns>
435 public ILandObject CreateBaseLand()
436 {
437 return new LandObject(UUID.Zero, false, m_scene);
438 }
439
440 /// <summary>
441 /// Adds a land object to the stored list and adds them to the landIDList to what they own
442 /// </summary>
443 /// <param name="new_land">The land object being added</param>
444 public ILandObject AddLandObject(ILandObject land)
445 {
446 ILandObject new_land = land.Copy();
447
448 lock (m_landList)
449 {
450 int newLandLocalID = ++m_lastLandLocalID;
451 new_land.landData.LocalID = newLandLocalID;
452
453 bool[,] landBitmap = new_land.getLandBitmap();
454 for (int x = 0; x < 64; x++)
455 {
456 for (int y = 0; y < 64; y++)
457 {
458 if (landBitmap[x, y])
459 {
460 m_landIDList[x, y] = newLandLocalID;
461 }
462 }
463 }
464
465 m_landList.Add(newLandLocalID, new_land);
466 }
467
468 new_land.forceUpdateLandInfo();
469 m_scene.EventManager.TriggerLandObjectAdded(new_land);
470 return new_land;
471 }
472
473 /// <summary>
474 /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
475 /// </summary>
476 /// <param name="local_id">Land.localID of the peice of land to remove.</param>
477 public void removeLandObject(int local_id)
478 {
479 lock (m_landList)
480 {
481 for (int x = 0; x < 64; x++)
482 {
483 for (int y = 0; y < 64; y++)
484 {
485 if (m_landIDList[x, y] == local_id)
486 {
487 m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}",
488 local_id, x, y);
489 return;
490 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
491 }
492 }
493 }
494
495 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].landData.GlobalID);
496 m_landList.Remove(local_id);
497 }
498 }
499
500 private void performFinalLandJoin(ILandObject master, ILandObject slave)
501 {
502 bool[,] landBitmapSlave = slave.getLandBitmap();
503 lock (m_landList)
504 {
505 for (int x = 0; x < 64; x++)
506 {
507 for (int y = 0; y < 64; y++)
508 {
509 if (landBitmapSlave[x, y])
510 {
511 m_landIDList[x, y] = master.landData.LocalID;
512 }
513 }
514 }
515 }
516
517 removeLandObject(slave.landData.LocalID);
518 UpdateLandObject(master.landData.LocalID, master.landData);
519 }
520
521 public ILandObject GetLandObject(int parcelLocalID)
522 {
523 lock (m_landList)
524 {
525 if (m_landList.ContainsKey(parcelLocalID))
526 {
527 return m_landList[parcelLocalID];
528 }
529 }
530 return null;
531 }
532
533 /// <summary>
534 /// Get the land object at the specified point
535 /// </summary>
536 /// <param name="x_float">Value between 0 - 256 on the x axis of the point</param>
537 /// <param name="y_float">Value between 0 - 256 on the y axis of the point</param>
538 /// <returns>Land object at the point supplied</returns>
539 public ILandObject GetLandObject(float x_float, float y_float)
540 {
541 int x;
542 int y;
543
544 try
545 {
546 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0));
547 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0));
548 }
549 catch (OverflowException)
550 {
551 return null;
552 }
553
554 if (x >= 64 || y >= 64 || x < 0 || y < 0)
555 {
556 return null;
557 }
558 lock (m_landList)
559 {
560 // Corner case. If an autoreturn happens during sim startup
561 // we will come here with the list uninitialized
562 //
563 if (m_landList.ContainsKey(m_landIDList[x, y]))
564 return m_landList[m_landIDList[x, y]];
565 return null;
566 }
567 }
568
569 public ILandObject GetLandObject(int x, int y)
570 {
571 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
572 {
573 // These exceptions here will cause a lot of complaints from the users specifically because
574 // they happen every time at border crossings
575 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
576 }
577 lock (m_landIDList)
578 {
579 return m_landList[m_landIDList[x / 4, y / 4]];
580 }
581 }
582
583 #endregion
584
585 #region Parcel Modification
586
587 public void ResetAllLandPrimCounts()
588 {
589 lock (m_landList)
590 {
591 foreach (LandObject p in m_landList.Values)
592 {
593 p.resetLandPrimCounts();
594 }
595 }
596 }
597
598 public void SetPrimsTainted()
599 {
600 m_landPrimCountTainted = true;
601 }
602
603 public bool IsLandPrimCountTainted()
604 {
605 return m_landPrimCountTainted;
606 }
607
608 public void AddPrimToLandPrimCounts(SceneObjectGroup obj)
609 {
610 Vector3 position = obj.AbsolutePosition;
611 ILandObject landUnderPrim = GetLandObject(position.X, position.Y);
612 if (landUnderPrim != null)
613 {
614 landUnderPrim.addPrimToCount(obj);
615 }
616 }
617
618 public void RemovePrimFromLandPrimCounts(SceneObjectGroup obj)
619 {
620
621 lock (m_landList)
622 {
623 foreach (LandObject p in m_landList.Values)
624 {
625 p.removePrimFromCount(obj);
626 }
627 }
628 }
629
630 public void FinalizeLandPrimCountUpdate()
631 {
632 //Get Simwide prim count for owner
633 Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>();
634 lock (m_landList)
635 {
636 foreach (LandObject p in m_landList.Values)
637 {
638 if (!landOwnersAndParcels.ContainsKey(p.landData.OwnerID))
639 {
640 List<LandObject> tempList = new List<LandObject>();
641 tempList.Add(p);
642 landOwnersAndParcels.Add(p.landData.OwnerID, tempList);
643 }
644 else
645 {
646 landOwnersAndParcels[p.landData.OwnerID].Add(p);
647 }
648 }
649 }
650
651 foreach (UUID owner in landOwnersAndParcels.Keys)
652 {
653 int simArea = 0;
654 int simPrims = 0;
655 foreach (LandObject p in landOwnersAndParcels[owner])
656 {
657 simArea += p.landData.Area;
658 simPrims += p.landData.OwnerPrims + p.landData.OtherPrims + p.landData.GroupPrims +
659 p.landData.SelectedPrims;
660 }
661
662 foreach (LandObject p in landOwnersAndParcels[owner])
663 {
664 p.landData.SimwideArea = simArea;
665 p.landData.SimwidePrims = simPrims;
666 }
667 }
668 }
669
670 public void UpdateLandPrimCounts()
671 {
672 ResetAllLandPrimCounts();
673 foreach (EntityBase obj in m_scene.Entities)
674 {
675 if (obj != null)
676 {
677 if ((obj is SceneObjectGroup) && !obj.IsDeleted && !((SceneObjectGroup) obj).IsAttachment)
678 {
679 m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj);
680 }
681 }
682 }
683 FinalizeLandPrimCountUpdate();
684 m_landPrimCountTainted = false;
685 }
686
687 public void PerformParcelPrimCountUpdate()
688 {
689 ResetAllLandPrimCounts();
690 m_scene.EventManager.TriggerParcelPrimCountUpdate();
691 FinalizeLandPrimCountUpdate();
692 m_landPrimCountTainted = false;
693 }
694
695 /// <summary>
696 /// Subdivides a piece of land
697 /// </summary>
698 /// <param name="start_x">West Point</param>
699 /// <param name="start_y">South Point</param>
700 /// <param name="end_x">East Point</param>
701 /// <param name="end_y">North Point</param>
702 /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param>
703 /// <returns>Returns true if successful</returns>
704 private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
705 {
706 //First, lets loop through the points and make sure they are all in the same peice of land
707 //Get the land object at start
708
709 ILandObject startLandObject = GetLandObject(start_x, start_y);
710
711 if (startLandObject == null) return;
712
713 //Loop through the points
714 try
715 {
716 int totalX = end_x - start_x;
717 int totalY = end_y - start_y;
718 for (int y = 0; y < totalY; y++)
719 {
720 for (int x = 0; x < totalX; x++)
721 {
722 ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y);
723 if (tempLandObject == null) return;
724 if (tempLandObject != startLandObject) return;
725 }
726 }
727 }
728 catch (Exception)
729 {
730 return;
731 }
732
733 //If we are still here, then they are subdividing within one piece of land
734 //Check owner
735 if (!m_scene.Permissions.CanEditParcel(attempting_user_id, startLandObject))
736 {
737 return;
738 }
739
740 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
741 ILandObject newLand = startLandObject.Copy();
742 newLand.landData.Name = "Subdivision of " + newLand.landData.Name;
743 newLand.landData.GlobalID = UUID.Random();
744
745 newLand.setLandBitmap(newLand.getSquareLandBitmap(start_x, start_y, end_x, end_y));
746
747 //Now, lets set the subdivision area of the original to false
748 int startLandObjectIndex = startLandObject.landData.LocalID;
749 lock (m_landList)
750 {
751 m_landList[startLandObjectIndex].setLandBitmap(
752 newLand.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false));
753 m_landList[startLandObjectIndex].forceUpdateLandInfo();
754 }
755
756 SetPrimsTainted();
757
758 //Now add the new land object
759 ILandObject result = AddLandObject(newLand);
760 UpdateLandObject(startLandObject.landData.LocalID, startLandObject.landData);
761 result.sendLandUpdateToAvatarsOverMe();
762 }
763
764 /// <summary>
765 /// Join 2 land objects together
766 /// </summary>
767 /// <param name="start_x">x value in first piece of land</param>
768 /// <param name="start_y">y value in first piece of land</param>
769 /// <param name="end_x">x value in second peice of land</param>
770 /// <param name="end_y">y value in second peice of land</param>
771 /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param>
772 /// <returns>Returns true if successful</returns>
773 private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
774 {
775 end_x -= 4;
776 end_y -= 4;
777
778 List<ILandObject> selectedLandObjects = new List<ILandObject>();
779 int stepYSelected;
780 for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
781 {
782 int stepXSelected;
783 for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
784 {
785 ILandObject p = GetLandObject(stepXSelected, stepYSelected);
786
787 if (p != null)
788 {
789 if (!selectedLandObjects.Contains(p))
790 {
791 selectedLandObjects.Add(p);
792 }
793 }
794 }
795 }
796 ILandObject masterLandObject = selectedLandObjects[0];
797 selectedLandObjects.RemoveAt(0);
798
799 if (selectedLandObjects.Count < 1)
800 {
801 return;
802 }
803 if (!m_scene.Permissions.CanEditParcel(attempting_user_id, masterLandObject))
804 {
805 return;
806 }
807 foreach (ILandObject p in selectedLandObjects)
808 {
809 if (p.landData.OwnerID != masterLandObject.landData.OwnerID)
810 {
811 return;
812 }
813 }
814
815 lock (m_landList)
816 {
817 foreach (ILandObject slaveLandObject in selectedLandObjects)
818 {
819 m_landList[masterLandObject.landData.LocalID].setLandBitmap(
820 slaveLandObject.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap()));
821 performFinalLandJoin(masterLandObject, slaveLandObject);
822 }
823 }
824 SetPrimsTainted();
825
826 masterLandObject.sendLandUpdateToAvatarsOverMe();
827 }
828
829 #endregion
830
831 #region Parcel Updating
832
833 /// <summary>
834 /// Where we send the ParcelOverlay packet to the client
835 /// </summary>
836 /// <param name="remote_client">The object representing the client</param>
837 public void SendParcelOverlay(IClientAPI remote_client)
838 {
839 const int LAND_BLOCKS_PER_PACKET = 1024;
840
841 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
842 int byteArrayCount = 0;
843 int sequenceID = 0;
844
845 for (int y = 0; y < 64; y++)
846 {
847 for (int x = 0; x < 64; x++)
848 {
849 byte tempByte = 0; //This represents the byte for the current 4x4
850
851 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4);
852
853 if (currentParcelBlock != null)
854 {
855 if (currentParcelBlock.landData.OwnerID == remote_client.AgentId)
856 {
857 //Owner Flag
858 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
859 }
860 else if (currentParcelBlock.landData.SalePrice > 0 &&
861 (currentParcelBlock.landData.AuthBuyerID == UUID.Zero ||
862 currentParcelBlock.landData.AuthBuyerID == remote_client.AgentId))
863 {
864 //Sale Flag
865 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
866 }
867 else if (currentParcelBlock.landData.OwnerID == UUID.Zero)
868 {
869 //Public Flag
870 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
871 }
872 else
873 {
874 //Other Flag
875 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
876 }
877
878 //Now for border control
879
880 ILandObject westParcel = null;
881 ILandObject southParcel = null;
882 if (x > 0)
883 {
884 westParcel = GetLandObject((x - 1) * 4, y * 4);
885 }
886 if (y > 0)
887 {
888 southParcel = GetLandObject(x * 4, (y - 1) * 4);
889 }
890
891 if (x == 0)
892 {
893 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
894 }
895 else if (westParcel != null && westParcel != currentParcelBlock)
896 {
897 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
898 }
899
900 if (y == 0)
901 {
902 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
903 }
904 else if (southParcel != null && southParcel != currentParcelBlock)
905 {
906 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
907 }
908
909 byteArray[byteArrayCount] = tempByte;
910 byteArrayCount++;
911 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
912 {
913 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
914 byteArrayCount = 0;
915 sequenceID++;
916 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
917 }
918 }
919 }
920 }
921 }
922
923 public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
924 bool snap_selection, IClientAPI remote_client)
925 {
926 //Get the land objects within the bounds
927 List<ILandObject> temp = new List<ILandObject>();
928 int inc_x = end_x - start_x;
929 int inc_y = end_y - start_y;
930 for (int x = 0; x < inc_x; x++)
931 {
932 for (int y = 0; y < inc_y; y++)
933 {
934 ILandObject currentParcel = GetLandObject(start_x + x, start_y + y);
935
936 if (currentParcel != null)
937 {
938 if (!temp.Contains(currentParcel))
939 {
940 currentParcel.forceUpdateLandInfo();
941 temp.Add(currentParcel);
942 }
943 }
944 }
945 }
946
947 int requestResult = LandChannel.LAND_RESULT_SINGLE;
948 if (temp.Count > 1)
949 {
950 requestResult = LandChannel.LAND_RESULT_MULTIPLE;
951 }
952
953 for (int i = 0; i < temp.Count; i++)
954 {
955 temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
956 }
957
958 SendParcelOverlay(remote_client);
959 }
960
961 public void handleParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
962 {
963 ILandObject land;
964 lock (m_landList)
965 {
966 m_landList.TryGetValue(localID, out land);
967 }
968
969 if (land != null) land.updateLandProperties(args, remote_client);
970 }
971
972 public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
973 {
974 subdivide(west, south, east, north, remote_client.AgentId);
975 }
976
977 public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
978 {
979 join(west, south, east, north, remote_client.AgentId);
980 }
981
982 public void handleParcelSelectObjectsRequest(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
983 {
984 m_landList[local_id].sendForceObjectSelect(local_id, request_type, returnIDs, remote_client);
985 }
986
987 public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client)
988 {
989 ILandObject land;
990 lock (m_landList)
991 {
992 m_landList.TryGetValue(local_id, out land);
993 }
994
995 if (land != null)
996 {
997 m_landList[local_id].sendLandObjectOwners(remote_client);
998 }
999 else
1000 {
1001 m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id);
1002 }
1003 }
1004
1005 public void handleParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client)
1006 {
1007 ILandObject land;
1008 lock (m_landList)
1009 {
1010 m_landList.TryGetValue(local_id, out land);
1011 }
1012
1013 if (land != null)
1014 {
1015 if (m_scene.Permissions.IsGod(remote_client.AgentId))
1016 {
1017 land.landData.OwnerID = ownerID;
1018
1019 m_scene.Broadcast(SendParcelOverlay);
1020 land.sendLandUpdateToClient(remote_client);
1021 }
1022 }
1023 }
1024
1025 public void handleParcelAbandonRequest(int local_id, IClientAPI remote_client)
1026 {
1027 ILandObject land;
1028 lock (m_landList)
1029 {
1030 m_landList.TryGetValue(local_id, out land);
1031 }
1032
1033 if (land != null)
1034 {
1035 if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land))
1036 {
1037 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
1038 land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1039 else
1040 land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1041 m_scene.Broadcast(SendParcelOverlay);
1042 land.sendLandUpdateToClient(remote_client);
1043 }
1044 }
1045 }
1046
1047 public void handleParcelReclaim(int local_id, IClientAPI remote_client)
1048 {
1049 ILandObject land;
1050 lock (m_landList)
1051 {
1052 m_landList.TryGetValue(local_id, out land);
1053 }
1054
1055 if (land != null)
1056 {
1057 if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land))
1058 {
1059 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
1060 land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1061 else
1062 land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1063 land.landData.ClaimDate = Util.UnixTimeSinceEpoch();
1064 m_scene.Broadcast(SendParcelOverlay);
1065 land.sendLandUpdateToClient(remote_client);
1066 }
1067 }
1068 }
1069 #endregion
1070
1071 // If the economy has been validated by the economy module,
1072 // and land has been validated as well, this method transfers
1073 // the land ownership
1074
1075 public void handleLandBuyRequest(Object o, EventManager.LandBuyArgs e)
1076 {
1077 if (e.economyValidated && e.landValidated)
1078 {
1079 ILandObject land;
1080 lock (m_landList)
1081 {
1082 m_landList.TryGetValue(e.parcelLocalID, out land);
1083 }
1084
1085 if (land != null)
1086 {
1087 land.updateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea);
1088 }
1089 }
1090 }
1091
1092 // After receiving a land buy packet, first the data needs to
1093 // be validated. This method validates the right to buy the
1094 // parcel
1095
1096 public void handleLandValidationRequest(Object o, EventManager.LandBuyArgs e)
1097 {
1098 if (e.landValidated == false)
1099 {
1100 ILandObject lob = null;
1101 lock (m_landList)
1102 {
1103 m_landList.TryGetValue(e.parcelLocalID, out lob);
1104 }
1105
1106 if (lob != null)
1107 {
1108 UUID AuthorizedID = lob.landData.AuthBuyerID;
1109 int saleprice = lob.landData.SalePrice;
1110 UUID pOwnerID = lob.landData.OwnerID;
1111
1112 bool landforsale = ((lob.landData.Flags &
1113 (uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects)) != 0);
1114 if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale)
1115 {
1116 // TODO I don't think we have to lock it here, no?
1117 //lock (e)
1118 //{
1119 e.parcelOwnerID = pOwnerID;
1120 e.landValidated = true;
1121 //}
1122 }
1123 }
1124 }
1125 }
1126
1127 #region Land Object From Storage Functions
1128
1129 public void IncomingLandObjectsFromStorage(List<LandData> data)
1130 {
1131 for (int i = 0; i < data.Count; i++)
1132 {
1133 IncomingLandObjectFromStorage(data[i]);
1134 }
1135 }
1136
1137 public void IncomingLandObjectFromStorage(LandData data)
1138 {
1139 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1140 new_land.landData = data.Copy();
1141 new_land.setLandBitmapFromByteArray();
1142 AddLandObject(new_land);
1143 }
1144
1145 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
1146 {
1147 ILandObject selectedParcel = null;
1148 lock (m_landList)
1149 {
1150 m_landList.TryGetValue(localID, out selectedParcel);
1151 }
1152
1153 if (selectedParcel == null) return;
1154
1155 selectedParcel.returnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
1156 }
1157
1158 public void NoLandDataFromStorage()
1159 {
1160 ResetSimLandObjects();
1161 }
1162
1163 #endregion
1164
1165 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
1166 {
1167 lock (m_landList)
1168 {
1169 foreach (LandObject obj in m_landList.Values)
1170 {
1171 obj.setParcelObjectMaxOverride(overrideDel);
1172 }
1173 }
1174 }
1175
1176 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
1177 {
1178 }
1179
1180 #region CAPS handler
1181
1182 private void OnRegisterCaps(UUID agentID, Caps caps)
1183 {
1184 string capsBase = "/CAPS/" + caps.CapsObjectPath;
1185 caps.RegisterHandler("RemoteParcelRequest",
1186 new RestStreamHandler("POST", capsBase + remoteParcelRequestPath,
1187 delegate(string request, string path, string param,
1188 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
1189 {
1190 return RemoteParcelRequest(request, path, param, agentID, caps);
1191 }));
1192 }
1193
1194 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
1195 // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to.
1196 // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x
1197 // and y coordinate (each 8 bit), encoded in a UUID (128 bit).
1198 //
1199 // Request format:
1200 // <llsd>
1201 // <map>
1202 // <key>location</key>
1203 // <array>
1204 // <real>1.23</real>
1205 // <real>45..6</real>
1206 // <real>78.9</real>
1207 // </array>
1208 // <key>region_id</key>
1209 // <uuid>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</uuid>
1210 // </map>
1211 // </llsd>
1212 private string RemoteParcelRequest(string request, string path, string param, UUID agentID, Caps caps)
1213 {
1214 UUID parcelID = UUID.Zero;
1215 try
1216 {
1217 Hashtable hash = new Hashtable();
1218 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
1219 if (hash.ContainsKey("region_id") && hash.ContainsKey("location"))
1220 {
1221 UUID regionID = (UUID)hash["region_id"];
1222 ArrayList list = (ArrayList)hash["location"];
1223 uint x = (uint)(double)list[0];
1224 uint y = (uint)(double)list[1];
1225 if (hash.ContainsKey("region_handle"))
1226 {
1227 // if you do a "About Landmark" on a landmark a second time, the viewer sends the
1228 // region_handle it got earlier via RegionHandleRequest
1229 ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]);
1230 parcelID = Util.BuildFakeParcelID(regionHandle, x, y);
1231 }
1232 else if (regionID == m_scene.RegionInfo.RegionID)
1233 {
1234 // a parcel request for a local parcel => no need to query the grid
1235 parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y);
1236 }
1237 else
1238 {
1239 // a parcel request for a parcel in another region. Ask the grid about the region
1240 RegionInfo info = m_scene.CommsManager.GridService.RequestNeighbourInfo(regionID);
1241 if (info != null)
1242 parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
1243 }
1244 }
1245 }
1246 catch (LLSD.LLSDParseException e)
1247 {
1248 m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message);
1249 m_log.ErrorFormat("[LAND] ... in request {0}", request);
1250 }
1251 catch(InvalidCastException)
1252 {
1253 m_log.ErrorFormat("[LAND] Wrong type in request {0}", request);
1254 }
1255
1256 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
1257 response.parcel_id = parcelID;
1258 m_log.DebugFormat("[LAND] got parcelID {0}", parcelID);
1259
1260 return LLSDHelpers.SerialiseLLSDReply(response);
1261 }
1262
1263 #endregion
1264
1265 private void handleParcelDwell(int localID, IClientAPI remoteClient)
1266 {
1267 ILandObject selectedParcel = null;
1268 lock (m_landList)
1269 {
1270 if (!m_landList.TryGetValue(localID, out selectedParcel))
1271 return;
1272 }
1273
1274 remoteClient.SendParcelDwellReply(localID, selectedParcel.landData.GlobalID, selectedParcel.landData.Dwell);
1275 }
1276
1277 private void handleParcelInfo(IClientAPI remoteClient, UUID parcelID)
1278 {
1279 if (parcelID == UUID.Zero)
1280 return;
1281
1282 ExtendedLandData data = (ExtendedLandData)parcelInfoCache.Get(parcelID, delegate(UUID parcel) {
1283 // assume we've got the parcelID we just computed in RemoteParcelRequest
1284 ExtendedLandData extLandData = new ExtendedLandData();
1285 Util.ParseFakeParcelID(parcel, out extLandData.regionHandle, out extLandData.x, out extLandData.y);
1286 m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
1287 extLandData.regionHandle, extLandData.x, extLandData.y);
1288
1289 // for this region or for somewhere else?
1290 if (extLandData.regionHandle == m_scene.RegionInfo.RegionHandle)
1291 {
1292 extLandData.landData = this.GetLandObject(extLandData.x, extLandData.y).landData;
1293 }
1294 else
1295 {
1296 extLandData.landData = m_scene.CommsManager.GridService.RequestLandData(extLandData.regionHandle,
1297 extLandData.x,
1298 extLandData.y);
1299 if (extLandData.landData == null)
1300 {
1301 // we didn't find the region/land => don't cache
1302 return null;
1303 }
1304 }
1305 return extLandData;
1306 });
1307
1308 if (data != null) // if we found some data, send it
1309 {
1310 RegionInfo info;
1311 if (data.regionHandle == m_scene.RegionInfo.RegionHandle)
1312 {
1313 info = m_scene.RegionInfo;
1314 }
1315 else
1316 {
1317 // most likely still cached from building the extLandData entry
1318 info = m_scene.CommsManager.GridService.RequestNeighbourInfo(data.regionHandle);
1319 }
1320 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
1321 m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...",
1322 data.landData.Name, data.regionHandle);
1323 remoteClient.SendParcelInfo(info, data.landData, parcelID, data.x, data.y);
1324 }
1325 else
1326 m_log.Debug("[LAND] got no parcelinfo; not sending");
1327 }
1328
1329 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
1330 {
1331 ILandObject land;
1332 lock (m_landList)
1333 {
1334 m_landList.TryGetValue(localID, out land);
1335 }
1336
1337 if (land == null) return;
1338
1339 if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land))
1340 return;
1341
1342 land.landData.OtherCleanTime = otherCleanTime;
1343
1344 UpdateLandObject(localID, land.landData);
1345 }
1346 }
1347}
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs b/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs
deleted file mode 100644
index b5f7225..0000000
--- a/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs
+++ /dev/null
@@ -1,930 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.Environment.Modules.World.Land
38{
39 /// <summary>
40 /// Keeps track of a specific piece of land's information
41 /// </summary>
42 public class LandObject : ILandObject
43 {
44 #region Member Variables
45
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private bool[,] m_landBitmap = new bool[64,64];
48
49 protected LandData m_landData = new LandData();
50 protected Scene m_scene;
51 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
52
53 public bool[,] landBitmap
54 {
55 get { return m_landBitmap; }
56 set { m_landBitmap = value; }
57 }
58
59 #endregion
60
61 #region ILandObject Members
62
63 public LandData landData
64 {
65 get { return m_landData; }
66
67 set { m_landData = value; }
68 }
69
70 public UUID regionUUID
71 {
72 get { return m_scene.RegionInfo.RegionID; }
73 }
74
75 #region Constructors
76
77 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
78 {
79 m_scene = scene;
80 landData.OwnerID = owner_id;
81 landData.IsGroupOwned = is_group_owned;
82 }
83
84 #endregion
85
86 #region Member Functions
87
88 #region General Functions
89
90 /// <summary>
91 /// Checks to see if this land object contains a point
92 /// </summary>
93 /// <param name="x"></param>
94 /// <param name="y"></param>
95 /// <returns>Returns true if the piece of land contains the specified point</returns>
96 public bool containsPoint(int x, int y)
97 {
98 if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize)
99 {
100 return (landBitmap[x / 4, y / 4] == true);
101 }
102 else
103 {
104 return false;
105 }
106 }
107
108 public ILandObject Copy()
109 {
110 ILandObject newLand = new LandObject(landData.OwnerID, landData.IsGroupOwned, m_scene);
111
112 //Place all new variables here!
113 newLand.landBitmap = (bool[,]) (landBitmap.Clone());
114 newLand.landData = landData.Copy();
115
116 return newLand;
117 }
118
119
120 static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
121 static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
122
123 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
124 {
125 overrideParcelMaxPrimCount = overrideDel;
126 }
127 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
128 {
129 overrideSimulatorMaxPrimCount = overrideDel;
130 }
131
132 public int getParcelMaxPrimCount(ILandObject thisObject)
133 {
134 if (overrideParcelMaxPrimCount != null)
135 {
136 return overrideParcelMaxPrimCount(thisObject);
137 }
138 else
139 {
140 //Normal Calculations
141 return Convert.ToInt32(
142 Math.Round((Convert.ToDecimal(landData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
143 Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ;
144 }
145 }
146 public int getSimulatorMaxPrimCount(ILandObject thisObject)
147 {
148 if (overrideSimulatorMaxPrimCount != null)
149 {
150 return overrideSimulatorMaxPrimCount(thisObject);
151 }
152 else
153 {
154 //Normal Calculations
155 return m_scene.objectCapacity;
156 }
157 }
158 #endregion
159
160 #region Packet Request Handling
161
162 public void sendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
163 {
164 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
165 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
166 if (estateModule != null)
167 regionFlags = estateModule.GetRegionFlags();
168
169 // In a perfect world, this would have worked.
170 //
171// if ((landData.Flags & (uint)Parcel.ParcelFlags.AllowLandmark) != 0)
172// regionFlags |= (uint)RegionFlags.AllowLandmark;
173// if (landData.OwnerID == remote_client.AgentId)
174// regionFlags |= (uint)RegionFlags.AllowSetHome;
175 remote_client.SendLandProperties(sequence_id,
176 snap_selection, request_result, landData,
177 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
178 getParcelMaxPrimCount(this),
179 getSimulatorMaxPrimCount(this), regionFlags);
180 }
181
182 public void updateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
183 {
184 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this))
185 {
186 //Needs later group support
187 LandData newData = landData.Copy();
188
189 if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice)
190 {
191 if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this))
192 {
193 newData.AuthBuyerID = args.AuthBuyerID;
194 newData.SalePrice = args.SalePrice;
195 }
196 }
197 newData.Category = args.Category;
198 newData.Description = args.Desc;
199 newData.GroupID = args.GroupID;
200 newData.LandingType = args.LandingType;
201 newData.MediaAutoScale = args.MediaAutoScale;
202 newData.MediaID = args.MediaID;
203 newData.MediaURL = args.MediaURL;
204 newData.MusicURL = args.MusicURL;
205 newData.Name = args.Name;
206 newData.Flags = args.ParcelFlags;
207 newData.PassHours = args.PassHours;
208 newData.PassPrice = args.PassPrice;
209 newData.SnapshotID = args.SnapshotID;
210 newData.UserLocation = args.UserLocation;
211 newData.UserLookAt = args.UserLookAt;
212
213 m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData);
214
215 sendLandUpdateToAvatarsOverMe();
216 }
217 }
218
219 public void updateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
220 {
221 LandData newData = landData.Copy();
222 newData.OwnerID = avatarID;
223 newData.GroupID = groupID;
224 newData.IsGroupOwned = groupOwned;
225 //newData.auctionID = AuctionID;
226 newData.ClaimDate = Util.UnixTimeSinceEpoch();
227 newData.ClaimPrice = claimprice;
228 newData.SalePrice = 0;
229 newData.AuthBuyerID = UUID.Zero;
230 newData.Flags &= ~(uint) (Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects);
231 m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData);
232
233 sendLandUpdateToAvatarsOverMe();
234 }
235
236 public bool isEitherBannedOrRestricted(UUID avatar)
237 {
238 if (isBannedFromLand(avatar))
239 {
240 return true;
241 }
242 else if (isRestrictedFromLand(avatar))
243 {
244 return true;
245 }
246 return false;
247 }
248
249 public bool isBannedFromLand(UUID avatar)
250 {
251 if ((landData.Flags & (uint) Parcel.ParcelFlags.UseBanList) > 0)
252 {
253 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
254 entry.AgentID = avatar;
255 entry.Flags = AccessList.Ban;
256 entry.Time = new DateTime();
257 if (landData.ParcelAccessList.Contains(entry))
258 {
259 //They are banned, so lets send them a notice about this parcel
260 return true;
261 }
262 }
263 return false;
264 }
265
266 public bool isRestrictedFromLand(UUID avatar)
267 {
268 if ((landData.Flags & (uint) Parcel.ParcelFlags.UseAccessList) > 0)
269 {
270 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
271 entry.AgentID = avatar;
272 entry.Flags = AccessList.Access;
273 entry.Time = new DateTime();
274 if (!landData.ParcelAccessList.Contains(entry))
275 {
276 //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
277 return true;
278 }
279 }
280 return false;
281 }
282
283 public void sendLandUpdateToClient(IClientAPI remote_client)
284 {
285 sendLandProperties(0, false, 0, remote_client);
286 }
287
288 public void sendLandUpdateToAvatarsOverMe()
289 {
290 List<ScenePresence> avatars = m_scene.GetAvatars();
291 ILandObject over = null;
292 for (int i = 0; i < avatars.Count; i++)
293 {
294 try
295 {
296 over =
297 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatars[i].AbsolutePosition.X), 0, 255),
298 Util.Clamp<int>((int)Math.Round(avatars[i].AbsolutePosition.Y), 0, 255));
299 }
300 catch (Exception)
301 {
302 m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatars[i].AbsolutePosition.X) + " y: " +
303 Math.Round(avatars[i].AbsolutePosition.Y));
304 }
305
306 if (over != null)
307 {
308 if (over.landData.LocalID == landData.LocalID)
309 {
310 if (((over.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0) && m_scene.RegionInfo.RegionSettings.AllowDamage)
311 avatars[i].Invulnerable = false;
312 else
313 avatars[i].Invulnerable = true;
314
315 sendLandUpdateToClient(avatars[i].ControllingClient);
316 }
317 }
318 }
319 }
320
321 #endregion
322
323 #region AccessList Functions
324
325 public List<UUID> createAccessListArrayByFlag(AccessList flag)
326 {
327 List<UUID> list = new List<UUID>();
328 foreach (ParcelManager.ParcelAccessEntry entry in landData.ParcelAccessList)
329 {
330 if (entry.Flags == flag)
331 {
332 list.Add(entry.AgentID);
333 }
334 }
335 if (list.Count == 0)
336 {
337 list.Add(UUID.Zero);
338 }
339
340 return list;
341 }
342
343 public void sendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
344 IClientAPI remote_client)
345 {
346
347 if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
348 {
349 List<UUID> avatars = createAccessListArrayByFlag(AccessList.Access);
350 remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,landData.LocalID);
351 }
352
353 if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
354 {
355 List<UUID> avatars = createAccessListArrayByFlag(AccessList.Ban);
356 remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, landData.LocalID);
357 }
358 }
359
360 public void updateAccessList(uint flags, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client)
361 {
362 LandData newData = landData.Copy();
363
364 if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
365 {
366 entries.Clear();
367 }
368
369 List<ParcelManager.ParcelAccessEntry> toRemove = new List<ParcelManager.ParcelAccessEntry>();
370 foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList)
371 {
372 if (entry.Flags == (AccessList)flags)
373 {
374 toRemove.Add(entry);
375 }
376 }
377
378 foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
379 {
380 newData.ParcelAccessList.Remove(entry);
381 }
382 foreach (ParcelManager.ParcelAccessEntry entry in entries)
383 {
384 ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry();
385 temp.AgentID = entry.AgentID;
386 temp.Time = new DateTime(); //Pointless? Yes.
387 temp.Flags = (AccessList)flags;
388
389 if (!newData.ParcelAccessList.Contains(temp))
390 {
391 newData.ParcelAccessList.Add(temp);
392 }
393 }
394
395 m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData);
396 }
397
398 #endregion
399
400 #region Update Functions
401
402 public void updateLandBitmapByteArray()
403 {
404 landData.Bitmap = convertLandBitmapToBytes();
405 }
406
407 /// <summary>
408 /// Update all settings in land such as area, bitmap byte array, etc
409 /// </summary>
410 public void forceUpdateLandInfo()
411 {
412 updateAABBAndAreaValues();
413 updateLandBitmapByteArray();
414 }
415
416 public void setLandBitmapFromByteArray()
417 {
418 landBitmap = convertBytesToLandBitmap();
419 }
420
421 /// <summary>
422 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
423 /// </summary>
424 private void updateAABBAndAreaValues()
425 {
426 int min_x = 64;
427 int min_y = 64;
428 int max_x = 0;
429 int max_y = 0;
430 int tempArea = 0;
431 int x, y;
432 for (x = 0; x < 64; x++)
433 {
434 for (y = 0; y < 64; y++)
435 {
436 if (landBitmap[x, y] == true)
437 {
438 if (min_x > x) min_x = x;
439 if (min_y > y) min_y = y;
440 if (max_x < x) max_x = x;
441 if (max_y < y) max_y = y;
442 tempArea += 16; //16sqm peice of land
443 }
444 }
445 }
446 int tx = min_x * 4;
447 if (tx > 255)
448 tx = 255;
449 int ty = min_y * 4;
450 if (ty > 255)
451 ty = 255;
452 landData.AABBMin =
453 new Vector3((float) (min_x * 4), (float) (min_y * 4),
454 (float) m_scene.Heightmap[tx, ty]);
455
456 tx = max_x * 4;
457 if (tx > 255)
458 tx = 255;
459 ty = max_y * 4;
460 if (ty > 255)
461 ty = 255;
462 landData.AABBMax =
463 new Vector3((float) (max_x * 4), (float) (max_y * 4),
464 (float) m_scene.Heightmap[tx, ty]);
465 landData.Area = tempArea;
466 }
467
468 #endregion
469
470 #region Land Bitmap Functions
471
472 /// <summary>
473 /// Sets the land's bitmap manually
474 /// </summary>
475 /// <param name="bitmap">64x64 block representing where this land is on a map</param>
476 public void setLandBitmap(bool[,] bitmap)
477 {
478 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
479 {
480 //Throw an exception - The bitmap is not 64x64
481 //throw new Exception("Error: Invalid Parcel Bitmap");
482 }
483 else
484 {
485 //Valid: Lets set it
486 landBitmap = bitmap;
487 forceUpdateLandInfo();
488 }
489 }
490
491 /// <summary>
492 /// Gets the land's bitmap manually
493 /// </summary>
494 /// <returns></returns>
495 public bool[,] getLandBitmap()
496 {
497 return landBitmap;
498 }
499
500 /// <summary>
501 /// Full sim land object creation
502 /// </summary>
503 /// <returns></returns>
504 public bool[,] basicFullRegionLandBitmap()
505 {
506 return getSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
507 }
508
509 /// <summary>
510 /// Used to modify the bitmap between the x and y points. Points use 64 scale
511 /// </summary>
512 /// <param name="start_x"></param>
513 /// <param name="start_y"></param>
514 /// <param name="end_x"></param>
515 /// <param name="end_y"></param>
516 /// <returns></returns>
517 public bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
518 {
519 bool[,] tempBitmap = new bool[64,64];
520 tempBitmap.Initialize();
521
522 tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
523 return tempBitmap;
524 }
525
526 /// <summary>
527 /// Change a land bitmap at within a square and set those points to a specific value
528 /// </summary>
529 /// <param name="land_bitmap"></param>
530 /// <param name="start_x"></param>
531 /// <param name="start_y"></param>
532 /// <param name="end_x"></param>
533 /// <param name="end_y"></param>
534 /// <param name="set_value"></param>
535 /// <returns></returns>
536 public bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
537 bool set_value)
538 {
539 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
540 {
541 //Throw an exception - The bitmap is not 64x64
542 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
543 }
544
545 int x, y;
546 for (y = 0; y < 64; y++)
547 {
548 for (x = 0; x < 64; x++)
549 {
550 if (x >= start_x / 4 && x < end_x / 4
551 && y >= start_y / 4 && y < end_y / 4)
552 {
553 land_bitmap[x, y] = set_value;
554 }
555 }
556 }
557 return land_bitmap;
558 }
559
560 /// <summary>
561 /// Join the true values of 2 bitmaps together
562 /// </summary>
563 /// <param name="bitmap_base"></param>
564 /// <param name="bitmap_add"></param>
565 /// <returns></returns>
566 public bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
567 {
568 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
569 {
570 //Throw an exception - The bitmap is not 64x64
571 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
572 }
573 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
574 {
575 //Throw an exception - The bitmap is not 64x64
576 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
577 }
578
579 int x, y;
580 for (y = 0; y < 64; y++)
581 {
582 for (x = 0; x < 64; x++)
583 {
584 if (bitmap_add[x, y])
585 {
586 bitmap_base[x, y] = true;
587 }
588 }
589 }
590 return bitmap_base;
591 }
592
593 /// <summary>
594 /// Converts the land bitmap to a packet friendly byte array
595 /// </summary>
596 /// <returns></returns>
597 private byte[] convertLandBitmapToBytes()
598 {
599 byte[] tempConvertArr = new byte[512];
600 byte tempByte = 0;
601 int x, y, i, byteNum = 0;
602 i = 0;
603 for (y = 0; y < 64; y++)
604 {
605 for (x = 0; x < 64; x++)
606 {
607 tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++ % 8));
608 if (i % 8 == 0)
609 {
610 tempConvertArr[byteNum] = tempByte;
611 tempByte = (byte) 0;
612 i = 0;
613 byteNum++;
614 }
615 }
616 }
617 return tempConvertArr;
618 }
619
620 private bool[,] convertBytesToLandBitmap()
621 {
622 bool[,] tempConvertMap = new bool[64,64];
623 tempConvertMap.Initialize();
624 byte tempByte = 0;
625 int x = 0, y = 0, i = 0, bitNum = 0;
626 for (i = 0; i < 512; i++)
627 {
628 tempByte = landData.Bitmap[i];
629 for (bitNum = 0; bitNum < 8; bitNum++)
630 {
631 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
632 tempConvertMap[x, y] = bit;
633 x++;
634 if (x > 63)
635 {
636 x = 0;
637 y++;
638 }
639 }
640 }
641 return tempConvertMap;
642 }
643
644 #endregion
645
646 #region Object Select and Object Owner Listing
647
648 public void sendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
649 {
650 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
651 {
652 List<uint> resultLocalIDs = new List<uint>();
653 try
654 {
655 lock (primsOverMe)
656 {
657 foreach (SceneObjectGroup obj in primsOverMe)
658 {
659 if (obj.LocalId > 0)
660 {
661 if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.OwnerID)
662 {
663 resultLocalIDs.Add(obj.LocalId);
664 }
665 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == landData.GroupID && landData.GroupID != UUID.Zero)
666 {
667 resultLocalIDs.Add(obj.LocalId);
668 }
669 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
670 obj.OwnerID != remote_client.AgentId)
671 {
672 resultLocalIDs.Add(obj.LocalId);
673 }
674 else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
675 {
676 resultLocalIDs.Add(obj.LocalId);
677 }
678 }
679 }
680 }
681 } catch (InvalidOperationException)
682 {
683 m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
684 }
685
686 remote_client.SendForceClientSelectObjects(resultLocalIDs);
687 }
688 }
689
690 /// <summary>
691 /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
692 /// aggreagete details such as the number of prims.
693 ///
694 /// </summary>
695 /// <param name="remote_client">
696 /// A <see cref="IClientAPI"/>
697 /// </param>
698 public void sendLandObjectOwners(IClientAPI remote_client)
699 {
700 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
701 {
702 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
703
704 lock (primsOverMe)
705 {
706 try
707 {
708
709 foreach (SceneObjectGroup obj in primsOverMe)
710 {
711 try
712 {
713 if (!primCount.ContainsKey(obj.OwnerID))
714 {
715 primCount.Add(obj.OwnerID, 0);
716 }
717 }
718 catch (NullReferenceException)
719 {
720 m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
721 }
722 try
723 {
724 primCount[obj.OwnerID] += obj.PrimCount;
725 }
726 catch (KeyNotFoundException)
727 {
728 m_log.Error("[LAND]: Unable to match a prim with it's owner.");
729 }
730 }
731 }
732 catch (InvalidOperationException)
733 {
734 m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
735 }
736 }
737
738 remote_client.SendLandObjectOwners(primCount);
739 }
740 }
741
742 public Dictionary<UUID, int> getLandObjectOwners()
743 {
744 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
745 lock (primsOverMe)
746 {
747 try
748 {
749
750 foreach (SceneObjectGroup obj in primsOverMe)
751 {
752 if (!ownersAndCount.ContainsKey(obj.OwnerID))
753 {
754 ownersAndCount.Add(obj.OwnerID, 0);
755 }
756 ownersAndCount[obj.OwnerID] += obj.PrimCount;
757 }
758 }
759 catch (InvalidOperationException)
760 {
761 m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
762 }
763
764 }
765 return ownersAndCount;
766 }
767
768 #endregion
769
770 #region Object Returning
771
772 public void returnObject(SceneObjectGroup obj)
773 {
774 SceneObjectGroup[] objs = new SceneObjectGroup[1];
775 objs[0] = obj;
776 m_scene.returnObjects(objs, obj.OwnerID);
777 }
778
779 public void returnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
780 {
781 Dictionary<UUID,List<SceneObjectGroup>> returns =
782 new Dictionary<UUID,List<SceneObjectGroup>>();
783
784 lock (primsOverMe)
785 {
786 if (type == (uint)ObjectReturnType.Owner)
787 {
788 foreach (SceneObjectGroup obj in primsOverMe)
789 {
790 if (obj.OwnerID == m_landData.OwnerID)
791 {
792 if (!returns.ContainsKey(obj.OwnerID))
793 returns[obj.OwnerID] =
794 new List<SceneObjectGroup>();
795 returns[obj.OwnerID].Add(obj);
796 }
797 }
798 }
799 else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero)
800 {
801 foreach (SceneObjectGroup obj in primsOverMe)
802 {
803 if (obj.GroupID == m_landData.GroupID)
804 {
805 if (!returns.ContainsKey(obj.OwnerID))
806 returns[obj.OwnerID] =
807 new List<SceneObjectGroup>();
808 returns[obj.OwnerID].Add(obj);
809 }
810 }
811 }
812 else if (type == (uint)ObjectReturnType.Other)
813 {
814 foreach (SceneObjectGroup obj in primsOverMe)
815 {
816 if (obj.OwnerID != m_landData.OwnerID &&
817 (obj.GroupID != m_landData.GroupID ||
818 m_landData.GroupID == UUID.Zero))
819 {
820 if (!returns.ContainsKey(obj.OwnerID))
821 returns[obj.OwnerID] =
822 new List<SceneObjectGroup>();
823 returns[obj.OwnerID].Add(obj);
824 }
825 }
826 }
827 else if (type == (uint)ObjectReturnType.List)
828 {
829 List<UUID> ownerlist = new List<UUID>(owners);
830
831 foreach (SceneObjectGroup obj in primsOverMe)
832 {
833 if (ownerlist.Contains(obj.OwnerID))
834 {
835 if (!returns.ContainsKey(obj.OwnerID))
836 returns[obj.OwnerID] =
837 new List<SceneObjectGroup>();
838 returns[obj.OwnerID].Add(obj);
839 }
840 }
841 }
842 }
843
844 foreach (List<SceneObjectGroup> ol in returns.Values)
845 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
846 }
847
848 #endregion
849
850 #region Object Adding/Removing from Parcel
851
852 public void resetLandPrimCounts()
853 {
854 landData.GroupPrims = 0;
855 landData.OwnerPrims = 0;
856 landData.OtherPrims = 0;
857 landData.SelectedPrims = 0;
858
859
860 lock (primsOverMe)
861 primsOverMe.Clear();
862 }
863
864 public void addPrimToCount(SceneObjectGroup obj)
865 {
866
867 UUID prim_owner = obj.OwnerID;
868 int prim_count = obj.PrimCount;
869
870 if (obj.IsSelected)
871 {
872 landData.SelectedPrims += prim_count;
873 }
874 else
875 {
876 if (prim_owner == landData.OwnerID)
877 {
878 landData.OwnerPrims += prim_count;
879 }
880 else if ((obj.GroupID == landData.GroupID ||
881 prim_owner == landData.GroupID) &&
882 landData.GroupID != UUID.Zero)
883 {
884 landData.GroupPrims += prim_count;
885 }
886 else
887 {
888 landData.OtherPrims += prim_count;
889 }
890 }
891
892 lock (primsOverMe)
893 primsOverMe.Add(obj);
894 }
895
896 public void removePrimFromCount(SceneObjectGroup obj)
897 {
898 lock (primsOverMe)
899 {
900 if (primsOverMe.Contains(obj))
901 {
902 UUID prim_owner = obj.OwnerID;
903 int prim_count = obj.PrimCount;
904
905 if (prim_owner == landData.OwnerID)
906 {
907 landData.OwnerPrims -= prim_count;
908 }
909 else if (obj.GroupID == landData.GroupID ||
910 prim_owner == landData.GroupID)
911 {
912 landData.GroupPrims -= prim_count;
913 }
914 else
915 {
916 landData.OtherPrims -= prim_count;
917 }
918
919 primsOverMe.Remove(obj);
920 }
921 }
922 }
923
924 #endregion
925
926 #endregion
927
928 #endregion
929 }
930}