diff options
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 229 |
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.Drawing; | 31 | using System.Drawing; |
31 | using System.Drawing.Imaging; | 32 | using System.Drawing.Imaging; |
32 | using System.IO; | 33 | using 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 | } |