aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs230
1 files changed, 229 insertions, 1 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 1eb3117..311821a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.Drawing; 31using System.Drawing;
31using System.Drawing.Imaging; 32using System.Drawing.Imaging;
32using System.IO; 33using System.IO;
@@ -3224,6 +3225,7 @@ namespace OpenSim.Region.Framework.Scenes
3224 /// also return a reason.</returns> 3225 /// also return a reason.</returns>
3225 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) 3226 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason)
3226 { 3227 {
3228 TeleportFlags tp = (TeleportFlags)teleportFlags;
3227 //Teleport flags: 3229 //Teleport flags:
3228 // 3230 //
3229 // TeleportFlags.ViaGodlikeLure - Border Crossing 3231 // TeleportFlags.ViaGodlikeLure - Border Crossing
@@ -3257,6 +3259,17 @@ namespace OpenSim.Region.Framework.Scenes
3257 3259
3258 CapsModule.NewUserConnection(agent); 3260 CapsModule.NewUserConnection(agent);
3259 3261
3262 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3263
3264 //On login or border crossing test land permisions
3265 if (tp != TeleportFlags.Default)
3266 {
3267 if (land != null && !TestLandRestrictions(agent, land, out reason))
3268 {
3269 return false;
3270 }
3271 }
3272
3260 ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID); 3273 ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID);
3261 if (sp != null) 3274 if (sp != null)
3262 { 3275 {
@@ -3329,7 +3342,6 @@ namespace OpenSim.Region.Framework.Scenes
3329 } 3342 }
3330 } 3343 }
3331 // Honor parcel landing type and position. 3344 // Honor parcel landing type and position.
3332 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3333 if (land != null) 3345 if (land != null)
3334 { 3346 {
3335 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3347 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3345,6 +3357,40 @@ namespace OpenSim.Region.Framework.Scenes
3345 return true; 3357 return true;
3346 } 3358 }
3347 3359
3360 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason)
3361 {
3362
3363 bool banned = land.IsBannedFromLand(agent.AgentID);
3364 bool restricted = land.IsRestrictedFromLand(agent.AgentID);
3365
3366 if (banned || restricted)
3367 {
3368 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y);
3369 if (nearestParcel != null)
3370 {
3371 //Move agent to nearest allowed
3372 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3373 agent.startpos.X = newPosition.X;
3374 agent.startpos.Y = newPosition.Y;
3375 }
3376 else
3377 {
3378 if (banned)
3379 {
3380 reason = "Cannot regioncross into banned parcel.";
3381 }
3382 else
3383 {
3384 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3385 RegionInfo.RegionName);
3386 }
3387 return false;
3388 }
3389 }
3390 reason = "";
3391 return true;
3392 }
3393
3348 /// <summary> 3394 /// <summary>
3349 /// Verifies that the user has a presence on the Grid 3395 /// Verifies that the user has a presence on the Grid
3350 /// </summary> 3396 /// </summary>
@@ -3476,6 +3522,18 @@ namespace OpenSim.Region.Framework.Scenes
3476 return true; 3522 return true;
3477 } 3523 }
3478 3524
3525 private ILandObject GetParcelAtPoint(float x, float y)
3526 {
3527 foreach (var parcel in AllParcels())
3528 {
3529 if( parcel.ContainsPoint((int)x,(int)y))
3530 {
3531 return parcel;
3532 }
3533 }
3534 return null;
3535 }
3536
3479 /// <summary> 3537 /// <summary>
3480 /// Update an AgentCircuitData object with new information 3538 /// Update an AgentCircuitData object with new information
3481 /// </summary> 3539 /// </summary>
@@ -4748,5 +4806,175 @@ namespace OpenSim.Region.Framework.Scenes
4748 { 4806 {
4749 get { return m_allowScriptCrossings; } 4807 get { return m_allowScriptCrossings; }
4750 } 4808 }
4809
4810 public Vector3? GetNearestAllowedPosition(ScenePresence avatar)
4811 {
4812 //simulate to make sure we have pretty up to date positions
4813 PhysicsScene.Simulate(0);
4814
4815 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
4816
4817 if (nearestParcel != null)
4818 {
4819 Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1));
4820 //Try to get a location that feels like where they came from
4821 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4822 if (nearestPoint != null)
4823 {
4824 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4825 return nearestPoint.Value;
4826 }
4827
4828 //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel
4829 Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition);
4830 dir = Vector3.Normalize(directionToParcelCenter);
4831 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4832 if (nearestPoint != null)
4833 {
4834 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4835 return nearestPoint.Value;
4836 }
4837
4838 //Ultimate backup if we have no idea where they are
4839 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
4840 return avatar.lastKnownAllowedPosition;
4841
4842 }
4843
4844 //Go to the edge, this happens in teleporting to a region with no available parcels
4845 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
4846 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
4847 return nearestRegionEdgePoint;
4848 return null;
4849 }
4850
4851 private Vector3 GetParcelCenterAtGround(ILandObject parcel)
4852 {
4853 Vector2 center = GetParcelCenter(parcel);
4854 return GetPositionAtGround(center.X, center.Y);
4855 }
4856
4857 private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel)
4858 {
4859 Vector3 unitDirection = Vector3.Normalize(direction);
4860 //Making distance to search go through some sane limit of distance
4861 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f)
4862 {
4863 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
4864 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
4865 {
4866 return testPos;
4867 }
4868 }
4869 return null;
4870 }
4871
4872 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4873 {
4874 List<ILandObject> all = AllParcels();
4875 float minParcelDistance = float.MaxValue;
4876 ILandObject nearestParcel = null;
4877
4878 foreach (var parcel in all)
4879 {
4880 if (!parcel.IsEitherBannedOrRestricted(avatarId))
4881 {
4882 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4883 if (parcelDistance < minParcelDistance)
4884 {
4885 minParcelDistance = parcelDistance;
4886 nearestParcel = parcel;
4887 }
4888 }
4889 }
4890
4891 return nearestParcel;
4892 }
4893
4894 private List<ILandObject> AllParcels()
4895 {
4896 return LandChannel.AllParcels();
4897 }
4898
4899 private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y)
4900 {
4901 return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel));
4902 }
4903
4904 //calculate the average center point of a parcel
4905 private Vector2 GetParcelCenter(ILandObject parcel)
4906 {
4907 int count = 0;
4908 int avgx = 0;
4909 int avgy = 0;
4910 for (int x = 0; x < Constants.RegionSize; x++)
4911 {
4912 for (int y = 0; y < Constants.RegionSize; y++)
4913 {
4914 //Just keep a running average as we check if all the points are inside or not
4915 if (parcel.ContainsPoint(x, y))
4916 {
4917 if (count == 0)
4918 {
4919 avgx = x;
4920 avgy = y;
4921 }
4922 else
4923 {
4924 avgx = (avgx * count + x) / (count + 1);
4925 avgy = (avgy * count + y) / (count + 1);
4926 }
4927 count += 1;
4928 }
4929 }
4930 }
4931 return new Vector2(avgx, avgy);
4932 }
4933
4934 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
4935 {
4936 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X;
4937 float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y;
4938
4939 //find out what vertical edge to go to
4940 if (xdistance < ydistance)
4941 {
4942 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2)
4943 {
4944 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
4945 }
4946 else
4947 {
4948 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y);
4949 }
4950 }
4951 //find out what horizontal edge to go to
4952 else
4953 {
4954 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2)
4955 {
4956 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
4957 }
4958 else
4959 {
4960 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize);
4961 }
4962 }
4963 }
4964
4965 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y)
4966 {
4967 Vector3 ground = GetPositionAtGround(x, y);
4968 if( avatar.AbsolutePosition.Z > ground.Z)
4969 {
4970 ground.Z = avatar.AbsolutePosition.Z;
4971 }
4972 return ground;
4973 }
4974
4975 private Vector3 GetPositionAtGround(float x, float y)
4976 {
4977 return new Vector3(x, y, GetGroundHeight(x, y));
4978 }
4751 } 4979 }
4752} 4980}