From 98f91a252cade093894511110157d7fcd7e4487e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Mar 2010 01:19:45 -0600 Subject: - parcel blocking, region crossing blocking, teleport blocking Signed-off-by: Melanie --- OpenSim/Region/Framework/Scenes/Scene.cs | 230 ++++++++++++++++++++++++++++++- 1 file changed, 229 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs') 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 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; @@ -3224,6 +3225,7 @@ namespace OpenSim.Region.Framework.Scenes /// also return a reason. public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) { + TeleportFlags tp = (TeleportFlags)teleportFlags; //Teleport flags: // // TeleportFlags.ViaGodlikeLure - Border Crossing @@ -3257,6 +3259,17 @@ namespace OpenSim.Region.Framework.Scenes CapsModule.NewUserConnection(agent); + ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + + //On login or border crossing test land permisions + if (tp != TeleportFlags.Default) + { + if (land != null && !TestLandRestrictions(agent, land, out reason)) + { + return false; + } + } + ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID); if (sp != null) { @@ -3329,7 +3342,6 @@ namespace OpenSim.Region.Framework.Scenes } } // Honor parcel landing type and position. - ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); if (land != null) { if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) @@ -3345,6 +3357,40 @@ namespace OpenSim.Region.Framework.Scenes return true; } + private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) + { + + bool banned = land.IsBannedFromLand(agent.AgentID); + bool restricted = land.IsRestrictedFromLand(agent.AgentID); + + if (banned || restricted) + { + ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); + if (nearestParcel != null) + { + //Move agent to nearest allowed + Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); + agent.startpos.X = newPosition.X; + agent.startpos.Y = newPosition.Y; + } + else + { + if (banned) + { + reason = "Cannot regioncross into banned parcel."; + } + else + { + reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + RegionInfo.RegionName); + } + return false; + } + } + reason = ""; + return true; + } + /// /// Verifies that the user has a presence on the Grid /// @@ -3476,6 +3522,18 @@ namespace OpenSim.Region.Framework.Scenes return true; } + private ILandObject GetParcelAtPoint(float x, float y) + { + foreach (var parcel in AllParcels()) + { + if( parcel.ContainsPoint((int)x,(int)y)) + { + return parcel; + } + } + return null; + } + /// /// Update an AgentCircuitData object with new information /// @@ -4748,5 +4806,175 @@ namespace OpenSim.Region.Framework.Scenes { get { return m_allowScriptCrossings; } } + + public Vector3? GetNearestAllowedPosition(ScenePresence avatar) + { + //simulate to make sure we have pretty up to date positions + PhysicsScene.Simulate(0); + + ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + + if (nearestParcel != null) + { + Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); + //Try to get a location that feels like where they came from + Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel + Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); + dir = Vector3.Normalize(directionToParcelCenter); + nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + //Ultimate backup if we have no idea where they are + Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString()); + return avatar.lastKnownAllowedPosition; + + } + + //Go to the edge, this happens in teleporting to a region with no available parcels + Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); + //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); + return nearestRegionEdgePoint; + return null; + } + + private Vector3 GetParcelCenterAtGround(ILandObject parcel) + { + Vector2 center = GetParcelCenter(parcel); + return GetPositionAtGround(center.X, center.Y); + } + + private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) + { + Vector3 unitDirection = Vector3.Normalize(direction); + //Making distance to search go through some sane limit of distance + for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) + { + Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); + if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) + { + return testPos; + } + } + return null; + } + + public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) + { + List all = AllParcels(); + float minParcelDistance = float.MaxValue; + ILandObject nearestParcel = null; + + foreach (var parcel in all) + { + if (!parcel.IsEitherBannedOrRestricted(avatarId)) + { + float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); + if (parcelDistance < minParcelDistance) + { + minParcelDistance = parcelDistance; + nearestParcel = parcel; + } + } + } + + return nearestParcel; + } + + private List AllParcels() + { + return LandChannel.AllParcels(); + } + + private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) + { + return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); + } + + //calculate the average center point of a parcel + private Vector2 GetParcelCenter(ILandObject parcel) + { + int count = 0; + int avgx = 0; + int avgy = 0; + for (int x = 0; x < Constants.RegionSize; x++) + { + for (int y = 0; y < Constants.RegionSize; y++) + { + //Just keep a running average as we check if all the points are inside or not + if (parcel.ContainsPoint(x, y)) + { + if (count == 0) + { + avgx = x; + avgy = y; + } + else + { + avgx = (avgx * count + x) / (count + 1); + avgy = (avgy * count + y) / (count + 1); + } + count += 1; + } + } + } + return new Vector2(avgx, avgy); + } + + private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) + { + float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; + float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y; + + //find out what vertical edge to go to + if (xdistance < ydistance) + { + if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); + } + else + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); + } + } + //find out what horizontal edge to go to + else + { + if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); + } + else + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); + } + } + } + + private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) + { + Vector3 ground = GetPositionAtGround(x, y); + if( avatar.AbsolutePosition.Z > ground.Z) + { + ground.Z = avatar.AbsolutePosition.Z; + } + return ground; + } + + private Vector3 GetPositionAtGround(float x, float y) + { + return new Vector3(x, y, GetGroundHeight(x, y)); + } } } -- cgit v1.1