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.cs229
1 files changed, 229 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 388bc99..884f13a 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;
@@ -3251,6 +3252,7 @@ namespace OpenSim.Region.Framework.Scenes
3251 /// also return a reason.</returns> 3252 /// also return a reason.</returns>
3252 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) 3253 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason)
3253 { 3254 {
3255 TeleportFlags tp = (TeleportFlags)teleportFlags;
3254 //Teleport flags: 3256 //Teleport flags:
3255 // 3257 //
3256 // TeleportFlags.ViaGodlikeLure - Border Crossing 3258 // TeleportFlags.ViaGodlikeLure - Border Crossing
@@ -3284,6 +3286,17 @@ namespace OpenSim.Region.Framework.Scenes
3284 3286
3285 CapsModule.NewUserConnection(agent); 3287 CapsModule.NewUserConnection(agent);
3286 3288
3289 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3290
3291 //On login or border crossing test land permisions
3292 if (tp != TeleportFlags.Default)
3293 {
3294 if (land != null && !TestLandRestrictions(agent, land, out reason))
3295 {
3296 return false;
3297 }
3298 }
3299
3287 ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID); 3300 ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID);
3288 if (sp != null) 3301 if (sp != null)
3289 { 3302 {
@@ -3377,6 +3390,40 @@ namespace OpenSim.Region.Framework.Scenes
3377 return true; 3390 return true;
3378 } 3391 }
3379 3392
3393 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason)
3394 {
3395
3396 bool banned = land.IsBannedFromLand(agent.AgentID);
3397 bool restricted = land.IsRestrictedFromLand(agent.AgentID);
3398
3399 if (banned || restricted)
3400 {
3401 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y);
3402 if (nearestParcel != null)
3403 {
3404 //Move agent to nearest allowed
3405 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3406 agent.startpos.X = newPosition.X;
3407 agent.startpos.Y = newPosition.Y;
3408 }
3409 else
3410 {
3411 if (banned)
3412 {
3413 reason = "Cannot regioncross into banned parcel.";
3414 }
3415 else
3416 {
3417 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3418 RegionInfo.RegionName);
3419 }
3420 return false;
3421 }
3422 }
3423 reason = "";
3424 return true;
3425 }
3426
3380 /// <summary> 3427 /// <summary>
3381 /// Verifies that the user has a presence on the Grid 3428 /// Verifies that the user has a presence on the Grid
3382 /// </summary> 3429 /// </summary>
@@ -3508,6 +3555,18 @@ namespace OpenSim.Region.Framework.Scenes
3508 return true; 3555 return true;
3509 } 3556 }
3510 3557
3558 private ILandObject GetParcelAtPoint(float x, float y)
3559 {
3560 foreach (var parcel in AllParcels())
3561 {
3562 if( parcel.ContainsPoint((int)x,(int)y))
3563 {
3564 return parcel;
3565 }
3566 }
3567 return null;
3568 }
3569
3511 /// <summary> 3570 /// <summary>
3512 /// Update an AgentCircuitData object with new information 3571 /// Update an AgentCircuitData object with new information
3513 /// </summary> 3572 /// </summary>
@@ -4780,5 +4839,175 @@ namespace OpenSim.Region.Framework.Scenes
4780 { 4839 {
4781 get { return m_allowScriptCrossings; } 4840 get { return m_allowScriptCrossings; }
4782 } 4841 }
4842
4843 public Vector3? GetNearestAllowedPosition(ScenePresence avatar)
4844 {
4845 //simulate to make sure we have pretty up to date positions
4846 PhysicsScene.Simulate(0);
4847
4848 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
4849
4850 if (nearestParcel != null)
4851 {
4852 Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1));
4853 //Try to get a location that feels like where they came from
4854 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4855 if (nearestPoint != null)
4856 {
4857 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4858 return nearestPoint.Value;
4859 }
4860
4861 //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel
4862 Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition);
4863 dir = Vector3.Normalize(directionToParcelCenter);
4864 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4865 if (nearestPoint != null)
4866 {
4867 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4868 return nearestPoint.Value;
4869 }
4870
4871 //Ultimate backup if we have no idea where they are
4872 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
4873 return avatar.lastKnownAllowedPosition;
4874
4875 }
4876
4877 //Go to the edge, this happens in teleporting to a region with no available parcels
4878 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
4879 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
4880 return nearestRegionEdgePoint;
4881 return null;
4882 }
4883
4884 private Vector3 GetParcelCenterAtGround(ILandObject parcel)
4885 {
4886 Vector2 center = GetParcelCenter(parcel);
4887 return GetPositionAtGround(center.X, center.Y);
4888 }
4889
4890 private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel)
4891 {
4892 Vector3 unitDirection = Vector3.Normalize(direction);
4893 //Making distance to search go through some sane limit of distance
4894 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f)
4895 {
4896 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
4897 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
4898 {
4899 return testPos;
4900 }
4901 }
4902 return null;
4903 }
4904
4905 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4906 {
4907 List<ILandObject> all = AllParcels();
4908 float minParcelDistance = float.MaxValue;
4909 ILandObject nearestParcel = null;
4910
4911 foreach (var parcel in all)
4912 {
4913 if (!parcel.IsEitherBannedOrRestricted(avatarId))
4914 {
4915 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4916 if (parcelDistance < minParcelDistance)
4917 {
4918 minParcelDistance = parcelDistance;
4919 nearestParcel = parcel;
4920 }
4921 }
4922 }
4923
4924 return nearestParcel;
4925 }
4926
4927 private List<ILandObject> AllParcels()
4928 {
4929 return LandChannel.AllParcels();
4930 }
4931
4932 private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y)
4933 {
4934 return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel));
4935 }
4936
4937 //calculate the average center point of a parcel
4938 private Vector2 GetParcelCenter(ILandObject parcel)
4939 {
4940 int count = 0;
4941 int avgx = 0;
4942 int avgy = 0;
4943 for (int x = 0; x < Constants.RegionSize; x++)
4944 {
4945 for (int y = 0; y < Constants.RegionSize; y++)
4946 {
4947 //Just keep a running average as we check if all the points are inside or not
4948 if (parcel.ContainsPoint(x, y))
4949 {
4950 if (count == 0)
4951 {
4952 avgx = x;
4953 avgy = y;
4954 }
4955 else
4956 {
4957 avgx = (avgx * count + x) / (count + 1);
4958 avgy = (avgy * count + y) / (count + 1);
4959 }
4960 count += 1;
4961 }
4962 }
4963 }
4964 return new Vector2(avgx, avgy);
4965 }
4966
4967 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
4968 {
4969 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X;
4970 float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y;
4971
4972 //find out what vertical edge to go to
4973 if (xdistance < ydistance)
4974 {
4975 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2)
4976 {
4977 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
4978 }
4979 else
4980 {
4981 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y);
4982 }
4983 }
4984 //find out what horizontal edge to go to
4985 else
4986 {
4987 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2)
4988 {
4989 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
4990 }
4991 else
4992 {
4993 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize);
4994 }
4995 }
4996 }
4997
4998 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y)
4999 {
5000 Vector3 ground = GetPositionAtGround(x, y);
5001 if( avatar.AbsolutePosition.Z > ground.Z)
5002 {
5003 ground.Z = avatar.AbsolutePosition.Z;
5004 }
5005 return ground;
5006 }
5007
5008 private Vector3 GetPositionAtGround(float x, float y)
5009 {
5010 return new Vector3(x, y, GetGroundHeight(x, y));
5011 }
4783 } 5012 }
4784} 5013}