From fce9e499e4682edf6db7b4f9c5546524b4a25197 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
---
OpenSim/Region/Framework/Scenes/Scene.cs | 229 +++++++++++++++++++++++++++++++
1 file changed, 229 insertions(+)
(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 388bc99..884f13a 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;
@@ -3251,6 +3252,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
@@ -3284,6 +3286,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)
{
@@ -3377,6 +3390,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
///
@@ -3508,6 +3555,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
///
@@ -4780,5 +4839,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