diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index ae2ff639eb..90188d29d7 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -149,11 +149,32 @@ namespace OpenSim.Framework
public uint WorldLocX = 0;
public uint WorldLocY = 0;
public uint WorldLocZ = 0;
+
+ ///
+ /// X dimension of the region.
+ ///
+ ///
+ /// If this is a varregion then the default size set here will be replaced when we load the region config.
+ ///
public uint RegionSizeX = Constants.RegionSize;
+
+ ///
+ /// X dimension of the region.
+ ///
+ ///
+ /// If this is a varregion then the default size set here will be replaced when we load the region config.
+ ///
public uint RegionSizeY = Constants.RegionSize;
+
+ ///
+ /// Z dimension of the region.
+ ///
+ ///
+ /// XXX: Unknown if this accounts for regions with negative Z.
+ ///
public uint RegionSizeZ = Constants.RegionHeight;
- private Dictionary m_otherSettings = new Dictionary();
+ private Dictionary m_extraSettings = new Dictionary();
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
@@ -506,16 +527,16 @@ namespace OpenSim.Framework
{
string val;
string keylower = key.ToLower();
- if (m_otherSettings.TryGetValue(keylower, out val))
+ if (m_extraSettings.TryGetValue(keylower, out val))
return val;
m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key);
return null;
}
- public void SetOtherSetting(string key, string value)
+ public void SetExtraSetting(string key, string value)
{
string keylower = key.ToLower();
- m_otherSettings[keylower] = value;
+ m_extraSettings[keylower] = value;
}
private void ReadNiniConfig(IConfigSource source, string name)
@@ -733,7 +754,7 @@ namespace OpenSim.Framework
foreach (String s in allKeys)
{
- SetOtherSetting(s, config.GetString(s));
+ SetExtraSetting(s, config.GetString(s));
}
}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index b32a169c97..0f6c507e09 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -121,8 +121,53 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
private EntityTransferStateMachine m_entityTransferStateMachine;
- private ExpiringCache> m_bannedRegions =
- new ExpiringCache>();
+ // For performance, we keed a cached of banned regions so we don't keep going
+ // to the grid service.
+ private class BannedRegionCache
+ {
+ private ExpiringCache> m_bannedRegions =
+ new ExpiringCache>();
+ ExpiringCache m_idCache;
+ DateTime m_banUntil;
+ public BannedRegionCache()
+ {
+ }
+ // Return 'true' if there is a valid ban entry for this agent in this region
+ public bool IfBanned(ulong pRegionHandle, UUID pAgentID)
+ {
+ bool ret = false;
+ if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
+ {
+ if (DateTime.Now < m_banUntil)
+ {
+ ret = true;
+ }
+ }
+ }
+ return ret;
+ }
+ // Add this agent in this region as a banned person
+ public void Add(ulong pRegionHandle, UUID pAgentID)
+ {
+ if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ m_idCache = new ExpiringCache();
+ m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45));
+ }
+ m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
+ }
+ // Remove the agent from the region's banned list
+ public void Remove(ulong pRegionHandle, UUID pAgentID)
+ {
+ if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ m_idCache.Remove(pRegionHandle);
+ }
+ }
+ }
+ private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
private IEventQueue m_eqModule;
private IRegionCombinerModule m_regionCombinerModule;
@@ -337,6 +382,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
}
+ // Attempt to teleport the ScenePresence to the specified position in the specified region (spec'ed by its handle).
public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
{
if (sp.Scene.Permissions.IsGridGod(sp.UUID))
@@ -418,7 +464,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Name, position, sp.Scene.RegionInfo.RegionName);
// Teleport within the same region
- if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
+ if (!sp.Scene.PositionIsInCurrentRegion(position) || position.Z < 0)
{
Vector3 emergencyPos = new Vector3(128, 128, 128);
@@ -437,10 +483,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
float posZLimit = 22;
// TODO: Check other Scene HeightField
- if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
- {
- posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
- }
+ posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
posZLimit += localHalfAVHeight + 0.1f;
@@ -484,9 +527,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
ScenePresence sp, ulong regionHandle, Vector3 position,
Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
{
- uint x = 0, y = 0;
- Utils.LongToUInts(regionHandle, out x, out y);
- GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
+ // Get destination region taking into account that the address could be an offset
+ // region inside a varregion.
+ GridRegion reg = GetTeleportDestinationRegion(sp.Scene.GridService, sp.Scene.RegionInfo.ScopeID, regionHandle, ref position);
if (reg != null)
{
@@ -537,12 +580,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// and set the map-tile to '(Offline)'
uint regX, regY;
- Utils.LongToUInts(regionHandle, out regX, out regY);
+ Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
MapBlockData block = new MapBlockData();
block.X = (ushort)(regX / Constants.RegionSize);
block.Y = (ushort)(regY / Constants.RegionSize);
- block.Access = 254; // == not there
+ block.Access = (byte)SimAccess.Down; // == not there
List blocks = new List();
blocks.Add(block);
@@ -550,6 +593,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
+ // The teleport address could be an address in a subregion of a larger varregion.
+ // Find the real base region and adjust the teleport location to account for the
+ // larger region.
+ private GridRegion GetTeleportDestinationRegion(IGridService gridService, UUID scope, ulong regionHandle, ref Vector3 position)
+ {
+ uint x = 0, y = 0;
+ Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
+
+ // Compute the world location we're teleporting to
+ double worldX = (double)x + position.X;
+ double worldY = (double)y + position.Y;
+
+ // Find the region that contains the position
+ GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
+
+ if (reg != null)
+ {
+ // modify the position for the offset into the actual region returned
+ position.X += x - reg.RegionLocX;
+ position.Y += y - reg.RegionLocY;
+ }
+
+ return reg;
+ }
+
// Nothing to validate here
protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
{
@@ -650,10 +718,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
- uint newRegionX = (uint)(reg.RegionHandle >> 40);
- uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
- uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
- uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
+ uint newRegionX, newRegionY, oldRegionX, oldRegionY;
+ Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
+ Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
ulong destinationHandle = finalDestination.RegionHandle;
@@ -675,8 +742,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
string reason;
string version;
+ string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
if (!Scene.SimulationService.QueryAccess(
- finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
+ finalDestination, sp.ControllingClient.AgentId, position, out version, out reason))
{
sp.ControllingClient.SendTeleportFailed(reason);
@@ -1274,6 +1342,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return region;
}
+ // This returns 'true' if the new region already has a child agent for our
+ // incoming agent. The implication is that, if 'false', we have to create the
+ // child and then teleport into the region.
protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
{
if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
@@ -1298,20 +1369,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
}
- protected virtual bool IsOutsideRegion(Scene s, Vector3 pos)
- {
- if (s.TestBorderCross(pos, Cardinals.N))
- return true;
- if (s.TestBorderCross(pos, Cardinals.S))
- return true;
- if (s.TestBorderCross(pos, Cardinals.E))
- return true;
- if (s.TestBorderCross(pos, Cardinals.W))
- return true;
-
- return false;
- }
-
#endregion
#region Landmark Teleport
@@ -1390,214 +1447,80 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Crossings
- public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason)
- {
- reason = String.Empty;
- version = String.Empty;
-
- UUID agentID = agent.UUID;
- ulong destinyHandle = destiny.RegionHandle;
-
- ExpiringCache r;
- DateTime banUntil;
- if (m_bannedRegions.TryGetValue(agentID, out r))
- {
- if (r.TryGetValue(destinyHandle, out banUntil))
- {
- if (DateTime.Now < banUntil)
- {
- reason = "Cannot connect to region";
- return false;
- }
- r.Remove(destinyHandle);
- }
- }
- else
- {
- r = null;
- }
-
- Scene ascene = agent.Scene;
-
- if (!ascene.SimulationService.QueryAccess(destiny, agentID, position, out version, out reason))
- {
- if (r == null)
- {
- r = new ExpiringCache();
- r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
-
- m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(30));
- }
- else
- {
- r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
- }
- return false;
- }
- return true;
- }
-
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
{
string r = String.Empty;
return GetDestination(scene, agentID, pos, out version, out newpos, out r);
}
- public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos, out string reason)
+ // Given a position relative to the current region (which has previously been tested to
+ // see that it is actually outside the current region), find the new region that the
+ // point is actually in.
+ // Returns the coordinates and information of the new region or 'null' of it doesn't exist.
+ public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
+ out string version, out Vector3 newpos, out string failureReason)
{
version = String.Empty;
- reason = String.Empty;
newpos = pos;
+ failureReason = string.Empty;
// m_log.DebugFormat(
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
- RegionInfo regInfo = scene.RegionInfo;
+ // Compute world location of the object's position
+ double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
+ double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
- uint neighbourx = regInfo.RegionLocX;
- uint neighboury = regInfo.RegionLocY;
- const float boundaryDistance = 0.7f;
+ // Call the grid service to lookup the region containing the new position.
+ GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
+ presenceWorldX, presenceWorldY,
+ Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
-/*
- Vector3 northCross = new Vector3(0, boundaryDistance, 0);
- Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
- Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
- Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
-
- // distance into new region to place avatar
- const float enterDistance = 0.5f;
- const float maxX = Constants.RegionSize - enterDistance;
- const float maxY = Constants.RegionSize - enterDistance;
-
- if (scene.TestBorderCross(pos + westCross, Cardinals.W))
+ if (neighbourRegion != null)
{
- if (scene.TestBorderCross(pos + northCross, Cardinals.N))
+ // Compute the entity's position relative to the new region
+ newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
+ (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
+ pos.Z);
+
+ if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
{
- Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
+ failureReason = "Cannot region cross into banned parcel";
+ neighbourRegion = null;
}
- else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
+ else
{
- neighboury--;
- newpos.Y += Constants.RegionSize;
+ // If not banned, make sure this agent is not in the list.
+ m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
}
- neighbourx--;
- newpos.X += Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
- {
- Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
- neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.X -= Constants.RegionSize;
-
- if (scene.TestBorderCross(pos + southCross, Cardinals.S))
+ // Check to see if we have access to the target region.
+ string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
+ if (neighbourRegion != null
+ && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out failureReason))
{
- neighboury--;
- newpos.Y += Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
- {
- Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
- }
- }
- else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
- {
- Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
- neighboury--;
- newpos.Y += Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
- {
- Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
- }
-
- newpos.X = Util.Clamp(newpos.X, enterDistance, maxX);
- newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY);
-*/
- float regionSizeX = regInfo.RegionSizeX;
- float regionSizeY = regInfo.RegionSizeY;
-
- if (pos.X < boundaryDistance)
- neighbourx--;
- else if (pos.X > regionSizeX - boundaryDistance)
- neighbourx += (uint)(regionSizeX / Constants.RegionSize);
-
- if (pos.Y < boundaryDistance)
- neighboury--;
- else if (pos.Y > regionSizeY - boundaryDistance)
- neighboury += (uint)(regionSizeY / Constants.RegionSize);
-
- int x = (int)(neighbourx * Constants.RegionSize);
- int y = (int)(neighboury * Constants.RegionSize);
-
- ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y);
-
- ExpiringCache r;
- DateTime banUntil;
-
- if (m_bannedRegions.TryGetValue(agentID, out r))
- {
- if (r.TryGetValue(neighbourHandle, out banUntil))
- {
- if (DateTime.Now < banUntil)
- return null;
- r.Remove(neighbourHandle);
+ // remember banned
+ m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
+ neighbourRegion = null;
}
}
else
{
- r = null;
+ // The destination region just doesn't exist
+ failureReason = "Cannot cross into non-existent region";
}
- GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
if (neighbourRegion == null)
- {
- reason = "";
- return null;
- }
-
- float newRegionSizeX = neighbourRegion.RegionSizeX;
- float newRegionSizeY = neighbourRegion.RegionSizeY;
- if (newRegionSizeX == 0)
- newRegionSizeX = Constants.RegionSize;
- if (newRegionSizeY == 0)
- newRegionSizeY = Constants.RegionSize;
-
- if (pos.X < boundaryDistance)
- newpos.X += newRegionSizeX;
- else if (pos.X > regionSizeX - boundaryDistance)
- newpos.X -= regionSizeX;
-
- if (pos.Y < boundaryDistance)
- newpos.Y += newRegionSizeY;
- else if (pos.Y > regionSizeY - boundaryDistance)
- newpos.Y -= regionSizeY;
-
- const float enterDistance = 0.5f;
- newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
- newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
-
- if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
- {
- if (r == null)
- {
- r = new ExpiringCache();
- r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
-
- m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45));
- }
- else
- {
- r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
- }
- return null;
- }
+ m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
+ LogHeader, scene.RegionInfo.RegionName,
+ scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
+ scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
+ pos);
+ else
+ m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
+ LogHeader, neighbourRegion.RegionName,
+ neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
+ newpos.X, newpos.Y);
return neighbourRegion;
}
@@ -1632,15 +1555,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
uint y;
Vector3 newpos;
string version;
- string reason;
+ string failureReason;
Vector3 pos = agent.AbsolutePosition + agent.Velocity;
- GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out version, out newpos, out reason);
+ GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
+ out version, out newpos, out failureReason);
if (neighbourRegion == null)
{
- if (reason != String.Empty)
- agent.ControllingClient.SendAlertMessage("Cannot cross to region");
+ if (failureReason != String.Empty)
+ agent.ControllingClient.SendAlertMessage(failureReason);
return agent;
}
@@ -1678,7 +1602,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.Scene.RequestTeleportLocation(
agent.ControllingClient,
- Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize),
+ Util.RegionLocToHandle(regionX, regionY),
position,
agent.Lookat,
(uint)Constants.TeleportFlags.ViaLocation);
@@ -1688,11 +1612,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (im != null)
{
UUID gotoLocation = Util.BuildFakeParcelID(
- Util.UIntsToLong(
- (regionX *
- (uint)Constants.RegionSize),
- (regionY *
- (uint)Constants.RegionSize)),
+ Util.RegionLocToHandle(regionX, regionY),
(uint)(int)position.X,
(uint)(int)position.Y,
(uint)(int)position.Z);
@@ -1745,8 +1665,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
///
public ScenePresence CrossAgentToNewRegionAsync(
- ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
- bool isFlying, string version)
+ ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
+ bool isFlying, string version)
{
if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
{
@@ -1893,11 +1813,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Next, let's close the child agent connections that are too far away.
uint neighbourx;
uint neighboury;
-
- Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
-
- neighbourx /= Constants.RegionSize;
- neighboury /= Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
agent.CloseChildAgents(neighbourx, neighboury);
@@ -2059,7 +1975,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (m_regionInfo != null)
{
- neighbours = RequestNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
+ neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
}
else
{
@@ -2216,15 +2132,195 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
+ // Computes the difference between two region bases.
+ // Returns a vector of world coordinates (meters) from base of first region to the second.
+ // The first region is the home region of the passed scene presence.
Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
{
- int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX;
- int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY;
+ /*
+ int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
+ int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
return new Vector3(shiftx, shifty, 0f);
+ */
+ return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
+ sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
+ 0f);
+ }
+
+ public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
+ {
+ // Since we don't know how big the regions could be, we have to search a very large area
+ // to find possible regions.
+ return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
+ }
+
+ #region NotFoundLocationCache class
+ // A collection of not found locations to make future lookups 'not found' lookups quick.
+ // A simple expiring cache that keeps not found locations for some number of seconds.
+ // A 'not found' location is presumed to be anywhere in the minimum sized region that
+ // contains that point. A conservitive estimate.
+ private class NotFoundLocationCache
+ {
+ private struct NotFoundLocation
+ {
+ public double minX, maxX, minY, maxY;
+ public DateTime expireTime;
+ }
+ private List m_notFoundLocations = new List();
+ public NotFoundLocationCache()
+ {
+ }
+ // Add an area to the list of 'not found' places. The area is the snapped region
+ // area around the added point.
+ public void Add(double pX, double pY)
+ {
+ lock (m_notFoundLocations)
+ {
+ if (!LockedContains(pX, pY))
+ {
+ NotFoundLocation nfl = new NotFoundLocation();
+ // A not found location is not found for at least a whole region sized area
+ nfl.minX = pX - (pX % (double)Constants.RegionSize);
+ nfl.minY = pY - (pY % (double)Constants.RegionSize);
+ nfl.maxX = nfl.minX + (double)Constants.RegionSize;
+ nfl.maxY = nfl.minY + (double)Constants.RegionSize;
+ nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
+ m_notFoundLocations.Add(nfl);
+ }
+ }
+
+ }
+ // Test to see of this point is in any of the 'not found' areas.
+ // Return 'true' if the point is found inside the 'not found' areas.
+ public bool Contains(double pX, double pY)
+ {
+ bool ret = false;
+ lock (m_notFoundLocations)
+ ret = LockedContains(pX, pY);
+ return ret;
+ }
+ private bool LockedContains(double pX, double pY)
+ {
+ bool ret = false;
+ this.DoExpiration();
+ foreach (NotFoundLocation nfl in m_notFoundLocations)
+ {
+ if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
+ {
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ }
+ private void DoExpiration()
+ {
+ List m_toRemove = null;
+ DateTime now = DateTime.Now;
+ foreach (NotFoundLocation nfl in m_notFoundLocations)
+ {
+ if (nfl.expireTime < now)
+ {
+ if (m_toRemove == null)
+ m_toRemove = new List();
+ m_toRemove.Add(nfl);
+ }
+ }
+ if (m_toRemove != null)
+ {
+ foreach (NotFoundLocation nfl in m_toRemove)
+ m_notFoundLocations.Remove(nfl);
+ m_toRemove.Clear();
+ }
+ }
+ }
+ #endregion // NotFoundLocationCache class
+ private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
+
+ // Given a world position (fractional meter coordinate), get the GridRegion info for
+ // the region containing that point.
+ // Someday this should be a method on GridService.
+ // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
+ // the size of the target region is unknown thus the search area might have to be very large.
+ // Return 'null' if no such region exists.
+ public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
+ double px, double py, uint pSizeHint)
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
+ GridRegion ret = null;
+ const double fudge = 2.0;
+
+ // One problem with this routine is negative results. That is, this can be called lots of times
+ // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
+ // will be quick 'not found's next time.
+ // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
+ // thus re-ask the GridService about the location.
+ if (m_notFoundLocationCache.Contains(px, py))
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
+ return null;
+ }
+
+ // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
+ // the region at the appropriate legacy region location.
+ uint possibleX = (uint)Math.Floor(px);
+ possibleX -= possibleX % Constants.RegionSize;
+ uint possibleY = (uint)Math.Floor(py);
+ possibleY -= possibleY % Constants.RegionSize;
+ ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
+ if (ret != null)
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
+ LogHeader, possibleX, possibleY, ret.RegionName);
+ }
+
+ if (ret == null)
+ {
+ // If the simple lookup failed, search the larger area for a region that contains this point
+ double range = (double)pSizeHint + fudge;
+ while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
+ {
+ // Get from the grid service a list of regions that might contain this point.
+ // The region origin will be in the zero direction so only subtract the range.
+ List possibleRegions = pGridService.GetRegionRange(pScopeID,
+ (int)(px - range), (int)(px),
+ (int)(py - range), (int)(py));
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
+ LogHeader, possibleRegions.Count, range);
+ if (possibleRegions != null && possibleRegions.Count > 0)
+ {
+ // If we found some regions, check to see if the point is within
+ foreach (GridRegion gr in possibleRegions)
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
+ LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
+ if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
+ && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
+ {
+ // Found a region that contains the point
+ ret = gr;
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
+ break;
+ }
+ }
+ }
+ // Larger search area for next time around if not found
+ range *= 2;
+ }
+ }
+
+ if (ret == null)
+ {
+ // remember this location was not found so we can quickly not find it next time
+ m_notFoundLocationCache.Add(px, py);
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
+ }
+
+ return ret;
}
private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2310,22 +2406,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
{
- Border[] northBorders = Scene.NorthBorders.ToArray();
- Border[] eastBorders = Scene.EastBorders.ToArray();
-
Vector2 extent = Vector2.Zero;
- for (int i = 0; i < eastBorders.Length; i++)
+
+ if (m_regionCombinerModule != null)
{
- extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
- }
- for (int i = 0; i < northBorders.Length; i++)
- {
- extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
+ Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
+ extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
+ extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
}
- // Loss of fraction on purpose
- extent.X = ((int)extent.X / (int)Constants.RegionSize);
- extent.Y = ((int)extent.Y / (int)Constants.RegionSize);
swCorner.X = Scene.RegionInfo.RegionLocX - 1;
swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
@@ -2340,56 +2429,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
///
///
- protected List RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
+ protected List GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
{
Scene pScene = avatar.Scene;
RegionInfo m_regionInfo = pScene.RegionInfo;
+ List neighbours;
// Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
// clear what should be done with a "far view" given that megaregions already extended the
// view to include everything in the megaregion
if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
{
- int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
+ // The area to check is as big as the current region.
+ // We presume all adjacent regions are the same size as this region.
+ uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
+ Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
- dd--;
+ uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
+ uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2;
- // region center
- int endX = (int)pRegionLocX * (int)Constants.RegionSize + (int)(Constants.RegionSize / 2);
- int endY = (int)pRegionLocY * (int)Constants.RegionSize + (int)(Constants.RegionSize / 2);
-
- int startX = endX - dd;
- int startY = endY - dd;
+ uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
+ uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
- endX += dd;
- endY += dd;
+ neighbours
+ = avatar.Scene.GridService.GetRegionRange(
+ m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
- if (startX < 0) startX = 0;
- if (startY < 0) startY = 0;
-
- List neighbours =
- avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
-
- neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
- return neighbours;
}
else
{
Vector2 swCorner, neCorner;
GetMegaregionViewRange(out swCorner, out neCorner);
- List neighbours
+ neighbours
= pScene.GridService.GetRegionRange(
m_regionInfo.ScopeID,
- (int)swCorner.X * (int)Constants.RegionSize,
- (int)neCorner.X * (int)Constants.RegionSize,
- (int)swCorner.Y * (int)Constants.RegionSize,
- (int)neCorner.Y * (int)Constants.RegionSize);
-
- neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
-
- return neighbours;
+ (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
+ (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
}
+
+ // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
+ neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
+
+ return neighbours;
}
/* not in use
private List NewNeighbours(List currentNeighbours, List previousNeighbours)
@@ -2509,8 +2591,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
/// This method locates the new region handle and offsets the prim position for the new region
///
- /// the attempted out of region position of the scene object
/// the scene object that we're crossing
+ /// the attempted out of region position of the scene object. This position is
+ /// relative to the region the object currently is in.
+ /// if 'true', the deletion of the client from the region is not broadcast to the clients
public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
{
if (grp == null)
@@ -2522,209 +2606,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (scene == null)
return;
-
- int thisx = (int)scene.RegionInfo.RegionLocX;
- int thisy = (int)scene.RegionInfo.RegionLocY;
- Vector3 EastCross = new Vector3(0.1f, 0, 0);
- Vector3 WestCross = new Vector3(-0.1f, 0, 0);
- Vector3 NorthCross = new Vector3(0, 0.1f, 0);
- Vector3 SouthCross = new Vector3(0, -0.1f, 0);
-
-
- // use this if no borders were crossed!
- ulong newRegionHandle
- = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
- (uint)((thisy) * Constants.RegionSize));
-
- Vector3 pos = attemptedPosition;
-
- int changeX = 1;
- int changeY = 1;
-
- if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
- {
- if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
- {
-
- Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
-
- if (crossedBorderx.BorderLine.Z > 0)
- {
- pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
- changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.X = ((pos.X + Constants.RegionSize));
-
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
-
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)((thisy - changeY) * Constants.RegionSize));
- // x - 1
- // y - 1
- }
- else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
- {
- Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
-
- if (crossedBorderx.BorderLine.Z > 0)
- {
- pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
- changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.X = ((pos.X + Constants.RegionSize));
-
-
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)((thisy + changeY) * Constants.RegionSize));
- // x - 1
- // y + 1
- }
- else
- {
- Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
-
- if (crossedBorderx.BorderLine.Z > 0)
- {
- pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
- changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.X = ((pos.X + Constants.RegionSize));
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)(thisy * Constants.RegionSize));
- // x - 1
- }
- }
- else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
- {
- if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
- {
-
- pos.X = ((pos.X - Constants.RegionSize));
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
- (uint)((thisy - changeY) * Constants.RegionSize));
- // x + 1
- // y - 1
- }
- else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
- {
- pos.X = ((pos.X - Constants.RegionSize));
- pos.Y = ((pos.Y - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
- (uint)((thisy + changeY) * Constants.RegionSize));
- // x + 1
- // y + 1
- }
- else
- {
- pos.X = ((pos.X - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
- (uint)(thisy * Constants.RegionSize));
- // x + 1
- }
- }
- else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
- {
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
- newRegionHandle
- = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
- // y - 1
- }
- else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
- {
-
- pos.Y = ((pos.Y - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize));
- // y + 1
- }
-
- // Offset the positions for the new region across the border
+ // Remember the old group position in case the region lookup fails so position can be restored.
Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
- // If we fail to cross the border, then reset the position of the scene object on that border.
- uint x = 0, y = 0;
- Utils.LongToUInts(newRegionHandle, out x, out y);
- GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
+ // Compute the absolute position of the object.
+ double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
+ double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
+ // Ask the grid service for the region that contains the passed address
+ GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
+ objectWorldLocX, objectWorldLocY);
+
+ Vector3 pos = Vector3.Zero;
if (destination != null)
{
- if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
- return; // we did it
+ // Adjust the object's relative position from the old region (attemptedPosition)
+ // to be relative to the new region (pos).
+ pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
+ (float)(objectWorldLocY - (double)destination.RegionLocY),
+ attemptedPosition.Z);
}
- // no one or failed lets go back and tell physics to go on
- oldGroupPosition.X = Util.Clamp(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
- oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
-// oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z, 0.5f, 4096.0f);
+ if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
+ {
+ m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
- grp.AbsolutePosition = oldGroupPosition;
- grp.Velocity = Vector3.Zero;
+ // We are going to move the object back to the old position so long as the old position
+ // is in the region
+ oldGroupPosition.X = Util.Clamp(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
+ oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
+ oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
- if (grp.RootPart.PhysActor != null)
- grp.RootPart.PhysActor.CrossingFailure();
+ grp.AbsolutePosition = oldGroupPosition;
+ grp.Velocity = Vector3.Zero;
+ if (grp.RootPart.PhysActor != null)
+ grp.RootPart.PhysActor.CrossingFailure();
- if (grp.RootPart.KeyframeMotion != null)
- grp.RootPart.KeyframeMotion.CrossingFailure();
+ if (grp.RootPart.KeyframeMotion != null)
+ grp.RootPart.KeyframeMotion.CrossingFailure();
- grp.ScheduleGroupForFullUpdate();
+ grp.ScheduleGroupForFullUpdate();
+ }
}
-
-
///
/// Move the given scene object into a new region
///
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
index e03ac5a26f..c6f531edd2 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
@@ -55,5 +55,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// Currently, will throw an exception if this does not match a root region.
///
Vector2 GetSizeOfMegaregion(UUID regionId);
+
+ ///
+ /// Tests to see of position (relative to the region) is within the megaregion
+ ///
+ bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy);
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index eb34f557aa..03270d7db0 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -160,11 +160,6 @@ namespace OpenSim.Region.Framework.Scenes
///
public SimStatsReporter StatsReporter { get; private set; }
- public List NorthBorders = new List();
- public List EastBorders = new List();
- public List SouthBorders = new List();
- public List WestBorders = new List();
-
///
/// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
/// PhysicsScene in order to perform collision detection
@@ -364,7 +359,6 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: Possibly stop other classes being able to manipulate this directly.
private SceneGraph m_sceneGraph;
- private volatile int m_bordersLocked;
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
private volatile bool m_backingup;
private Dictionary m_returns = new Dictionary();
@@ -446,18 +440,6 @@ namespace OpenSim.Region.Framework.Scenes
set { m_splitRegionID = value; }
}
- public bool BordersLocked
- {
- get { return m_bordersLocked == 1; }
- set
- {
- if (value == true)
- m_bordersLocked = 1;
- else
- m_bordersLocked = 0;
- }
- }
-
public new float TimeDilation
{
get { return m_sceneGraph.PhysicsScene.TimeDilation; }
@@ -1075,28 +1057,6 @@ namespace OpenSim.Region.Framework.Scenes
PeriodicBackup = true;
UseBackup = true;
- BordersLocked = true;
- Border northBorder = new Border();
- northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeY); //<---
- northBorder.CrossDirection = Cardinals.N;
- NorthBorders.Add(northBorder);
-
- Border southBorder = new Border();
- southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
- southBorder.CrossDirection = Cardinals.S;
- SouthBorders.Add(southBorder);
-
- Border eastBorder = new Border();
- eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeX); //<---
- eastBorder.CrossDirection = Cardinals.E;
- EastBorders.Add(eastBorder);
-
- Border westBorder = new Border();
- westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
- westBorder.CrossDirection = Cardinals.W;
- WestBorders.Add(westBorder);
- BordersLocked = false;
-
m_eventManager = new EventManager();
m_permissions = new ScenePermissions(this);
@@ -2611,185 +2571,35 @@ namespace OpenSim.Region.Framework.Scenes
EntityTransferModule.Cross(grp, attemptedPosition, silent);
}
- public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
+ // Simple test to see if a position is in the current region.
+ // This test is mostly used to see if a region crossing is necessary.
+ // Assuming the position is relative to the region so anything outside its bounds.
+ // Return 'true' if position inside region.
+ public bool PositionIsInCurrentRegion(Vector3 pos)
{
- if (BordersLocked)
+ bool ret = false;
+ int xx = (int)Math.Floor(pos.X);
+ int yy = (int)Math.Floor(pos.Y);
+ if (xx < 0 || yy < 0)
+ return false;
+
+ IRegionCombinerModule regionCombinerModule = RequestModuleInterface();
+ if (regionCombinerModule == null)
{
- switch (gridline)
- {
- case Cardinals.N:
- lock (NorthBorders)
- {
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
- break;
- case Cardinals.S:
- lock (SouthBorders)
- {
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
-
- break;
- case Cardinals.E:
- lock (EastBorders)
- {
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
-
- break;
- case Cardinals.W:
-
- lock (WestBorders)
- {
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
- break;
-
- }
+ // Regular region. Just check for region size
+ if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
+ ret = true;
}
else
{
- switch (gridline)
- {
- case Cardinals.N:
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
-
- break;
- case Cardinals.S:
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- break;
- case Cardinals.E:
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return b;
- }
-
- break;
- case Cardinals.W:
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- break;
-
- }
+ // We're in a mega-region so see if we are still in that larger region
+ ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
}
- return null;
+ return ret;
+
}
- public bool TestBorderCross(Vector3 position, Cardinals border)
- {
- if (BordersLocked)
- {
- switch (border)
- {
- case Cardinals.N:
- lock (NorthBorders)
- {
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- case Cardinals.E:
- lock (EastBorders)
- {
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- case Cardinals.S:
- lock (SouthBorders)
- {
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- case Cardinals.W:
- lock (WestBorders)
- {
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- }
- }
- else
- {
- switch (border)
- {
- case Cardinals.N:
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- case Cardinals.E:
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- case Cardinals.S:
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- case Cardinals.W:
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- }
- }
- return false;
- }
-
-
///
/// Called when objects or attachments cross the border, or teleport, between regions.
///
@@ -4116,60 +3926,11 @@ namespace OpenSim.Region.Framework.Scenes
{
// CleanDroppedAttachments();
- if (TestBorderCross(acd.startpos, Cardinals.E))
- {
- Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
- acd.startpos.X = crossedBorder.BorderLine.Z - 1;
- }
-
- if (TestBorderCross(acd.startpos, Cardinals.N))
- {
- Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
- acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
- //Mitigate http://opensimulator.org/mantis/view.php?id=3522
- // Check if start position is outside of region
- // If it is, check the Z start position also.. if not, leave it alone.
- if (BordersLocked)
- {
- lock (EastBorders)
- {
- if (acd.startpos.X > EastBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX AGENT POSITION");
- acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- }
- lock (NorthBorders)
- {
- if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX Agent POSITION");
- acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- }
- } else
- {
- if (acd.startpos.X > EastBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX AGENT POSITION");
- acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX Agent POSITION");
- acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- }
+ // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
+ if (acd.startpos.X < 0) acd.startpos.X = 1f;
+ if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
+ if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
+ if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
// m_log.DebugFormat(
// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
@@ -4883,44 +4644,6 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence sp = GetScenePresence(remoteClient.AgentId);
if (sp != null)
{
- uint regionX = RegionInfo.RegionLocX;
- uint regionY = RegionInfo.RegionLocY;
-
- Utils.LongToUInts(regionHandle, out regionX, out regionY);
-
- int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
- int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
-
- position.X += shiftx;
- position.Y += shifty;
-
- bool result = false;
-
- if (TestBorderCross(position,Cardinals.N))
- result = true;
-
- if (TestBorderCross(position, Cardinals.S))
- result = true;
-
- if (TestBorderCross(position, Cardinals.E))
- result = true;
-
- if (TestBorderCross(position, Cardinals.W))
- result = true;
-
- // bordercross if position is outside of region
-
- if (!result)
- {
- regionHandle = RegionInfo.RegionHandle;
- }
- else
- {
- // not in this region, undo the shift!
- position.X -= shiftx;
- position.Y -= shifty;
- }
-
if (EntityTransferModule != null)
{
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 89c7a1a3e1..a99e469fa4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -529,12 +529,10 @@ namespace OpenSim.Region.Framework.Scenes
set
{
Vector3 val = value;
- if (Scene != null && !IsAttachmentCheckFull()
- && !Scene.LoadingPrims &&
- (Scene.TestBorderCross(val, Cardinals.E) ||
- Scene.TestBorderCross(val, Cardinals.W) ||
- Scene.TestBorderCross(val, Cardinals.N) ||
- Scene.TestBorderCross(val, Cardinals.S))
+ if (Scene != null
+ && Scene.PositionIsInCurrentRegion(val)
+ && !IsAttachmentCheckFull()
+ && !Scene.LoadingPrims
)
{
if (!inTransit)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 91293c4ad8..897965913d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2979,10 +2979,7 @@ namespace OpenSim.Region.Framework.Scenes
{
Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
- if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
- || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
- || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
- || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
+ if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
{
ParentGroup.AbsolutePosition = newpos;
return;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cd9dcf58fc..2965903b3e 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1170,18 +1170,6 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentID == 0)
{
- if (m_scene.TestBorderCross(pos, Cardinals.E))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
- pos.X = crossedBorder.BorderLine.Z - 1;
- }
-
- if (m_scene.TestBorderCross(pos, Cardinals.N))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
- pos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
CheckAndAdjustLandingPoint(ref pos);
if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -3867,32 +3855,28 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
// pos2, Name, Scene.Name);
-
- if( Scene.TestBorderCross(pos2, Cardinals.E) ||
- Scene.TestBorderCross(pos2, Cardinals.W) ||
- Scene.TestBorderCross(pos2, Cardinals.N) ||
- Scene.TestBorderCross(pos2, Cardinals.S)
- )
+
+ if (Scene.PositionIsInCurrentRegion(pos2))
+ return;
+
+ if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
{
- if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
- {
- // we don't have entity transfer module
- Vector3 pos = AbsolutePosition;
- float px = pos.X;
- if (px < 0)
- pos.X += Velocity.X * 2;
- else if (px > m_scene.RegionInfo.RegionSizeX)
- pos.X -= Velocity.X * 2;
+ // we don't have entity transfer module
+ Vector3 pos = AbsolutePosition;
+ float px = pos.X;
+ if (px < 0)
+ pos.X += Velocity.X * 2;
+ else if (px > m_scene.RegionInfo.RegionSizeX)
+ pos.X -= Velocity.X * 2;
- float py = pos.Y;
- if (py < 0)
- pos.Y += Velocity.Y * 2;
- else if (py > m_scene.RegionInfo.RegionSizeY)
- pos.Y -= Velocity.Y * 2;
+ float py = pos.Y;
+ if (py < 0)
+ pos.Y += Velocity.Y * 2;
+ else if (py > m_scene.RegionInfo.RegionSizeY)
+ pos.Y -= Velocity.Y * 2;
- Velocity = Vector3.Zero;
- AbsolutePosition = pos;
- }
+ Velocity = Vector3.Zero;
+ AbsolutePosition = pos;
}
}
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 29b39e031a..6cbccc034f 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -116,37 +116,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
+ "If teleport is true then some extra teleport debug information is logged.\n"
+ "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
HandleDebugSceneSetCommand);
-
- scene.AddCommand(
- "Regions",
- this, "show borders", "show borders", "Show border information for regions", HandleShowBordersCommand);
- }
-
- private void HandleShowBordersCommand(string module, string[] args)
- {
- StringBuilder sb = new StringBuilder();
- sb.AppendFormat("Borders for {0}:\n", m_scene.Name);
-
- ConsoleDisplayTable cdt = new ConsoleDisplayTable();
- cdt.AddColumn("Cross Direction", 15);
- cdt.AddColumn("Line", 34);
- cdt.AddColumn("Trigger Region", 14);
-
- foreach (Border b in m_scene.NorthBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- foreach (Border b in m_scene.EastBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- foreach (Border b in m_scene.SouthBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- foreach (Border b in m_scene.WestBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- cdt.AddToStringBuilder(sb);
-
- MainConsole.Instance.Output(sb.ToString());
}
private void HandleDebugSceneGetCommand(string module, string[] args)
@@ -263,4 +232,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
}
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 7127c73c18..341c8f8bd6 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -134,6 +134,49 @@ namespace OpenSim.Region.RegionCombinerModule
throw new Exception(string.Format("Region with id {0} not found", regionId));
}
+ // Test to see if this postiion (relative to the region) is within the area covered
+ // by this megaregion.
+ public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
+ {
+ bool ret = false;
+ if (xx < 0 || yy < 0)
+ return ret;
+
+ foreach (RegionConnections rootRegion in m_regions.Values)
+ {
+ if (currentRegion == rootRegion.RegionId)
+ {
+ // The caller is in the root region so this is an easy test
+ if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
+ {
+ ret = true;
+ }
+ break;
+ }
+ else
+ {
+ // Maybe the caller is in one of the sub-regions
+ foreach (RegionData childRegion in rootRegion.ConnectedRegions)
+ {
+ if (currentRegion == childRegion.RegionId)
+ {
+ // This is a child. Diddle the offsets and check if in
+ Vector3 positionInMegaregion = childRegion.Offset;
+ positionInMegaregion.X += xx;
+ positionInMegaregion.Y += yy;
+ if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
+ {
+ ret = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
private void NewPresence(ScenePresence presence)
{
if (presence.IsChildAgent)
@@ -220,27 +263,6 @@ namespace OpenSim.Region.RegionCombinerModule
//
*/
- // Give each region a standard set of non-infinite borders
- Border northBorder = new Border();
- northBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
- northBorder.CrossDirection = Cardinals.N;
- scene.NorthBorders[0] = northBorder;
-
- Border southBorder = new Border();
- southBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
- southBorder.CrossDirection = Cardinals.S;
- scene.SouthBorders[0] = southBorder;
-
- Border eastBorder = new Border();
- eastBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
- eastBorder.CrossDirection = Cardinals.E;
- scene.EastBorders[0] = eastBorder;
-
- Border westBorder = new Border();
- westBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
- westBorder.CrossDirection = Cardinals.W;
- scene.WestBorders[0] = westBorder;
-
RegionConnections newConn = new RegionConnections();
newConn.ConnectedRegions = new List();
newConn.RegionScene = scene;
@@ -248,8 +270,8 @@ namespace OpenSim.Region.RegionCombinerModule
newConn.RegionId = scene.RegionInfo.originRegionID;
newConn.X = scene.RegionInfo.RegionLocX;
newConn.Y = scene.RegionInfo.RegionLocY;
- newConn.XEnd = (int)Constants.RegionSize;
- newConn.YEnd = (int)Constants.RegionSize;
+ newConn.XEnd = scene.RegionInfo.RegionSizeX;
+ newConn.YEnd = scene.RegionInfo.RegionSizeX;
lock (m_regions)
{
@@ -415,6 +437,11 @@ namespace OpenSim.Region.RegionCombinerModule
*/
#endregion
+
+ // Check to see if this new region is adjacent to the root region.
+ // Note that we expect the regions to be combined from the root region outward
+ // thus the requirement for the ordering in the configuration files.
+
// If we're one region over +x y (i.e. root region is to the west)
//xxx
//xxy
@@ -431,7 +458,7 @@ namespace OpenSim.Region.RegionCombinerModule
//xxx
if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
{
- connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene);
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
break;
}
@@ -441,9 +468,8 @@ namespace OpenSim.Region.RegionCombinerModule
//xxx
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
{
- connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene);
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
break;
-
}
}
@@ -453,20 +479,20 @@ namespace OpenSim.Region.RegionCombinerModule
DoWorkForRootRegion(newConn, scene);
}
}
-
- // Set up infinite borders around the entire AABB of the combined ConnectedRegions
- AdjustLargeRegionBounds();
}
private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
{
+ // Offset (in meters) from the base of this region to the base of the root region.
Vector3 offset = Vector3.Zero;
offset.X = newConn.PosX - rootConn.PosX;
offset.Y = newConn.PosY - rootConn.PosY;
+ // The new total size of the region (in meters)
+ // We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
Vector3 extents = Vector3.Zero;
- extents.Y = rootConn.YEnd;
- extents.X = rootConn.XEnd + newConn.XEnd;
+ extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
+ extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
rootConn.UpdateExtents(extents);
@@ -475,9 +501,6 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.RegionInfo.RegionName,
newConn.RegionScene.RegionInfo.RegionName, offset, extents);
- scene.BordersLocked = true;
- rootConn.RegionScene.BordersLocked = true;
-
RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -490,34 +513,10 @@ namespace OpenSim.Region.RegionCombinerModule
// Inform Child region that it needs to forward it's terrain to the root region
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
- // Extend the borders as appropriate
- lock (rootConn.RegionScene.EastBorders)
- rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.NorthBorders)
- rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.SouthBorders)
- rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (scene.WestBorders)
- {
- scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
-
- // Trigger auto teleport to root region
- scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
// Reset Terrain.. since terrain loads before we get here, we need to load
// it again so it loads in the root region
-
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
- // Unlock borders
- rootConn.RegionScene.BordersLocked = false;
- scene.BordersLocked = false;
-
// Create a client event forwarder and add this region's events to the root region.
if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -525,6 +524,9 @@ namespace OpenSim.Region.RegionCombinerModule
return true;
}
+ /*
+ * 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
+ * was generalized. These functions are not needed for the generalized solution but left for reference.
private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
{
Vector3 offset = Vector3.Zero;
@@ -536,9 +538,6 @@ namespace OpenSim.Region.RegionCombinerModule
extents.X = rootConn.XEnd;
rootConn.UpdateExtents(extents);
- scene.BordersLocked = true;
- rootConn.RegionScene.BordersLocked = true;
-
RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -553,30 +552,11 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
- lock (rootConn.RegionScene.NorthBorders)
- rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.EastBorders)
- rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.WestBorders)
- rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (scene.SouthBorders)
- {
- scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
- scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
// Reset Terrain.. since terrain normally loads first.
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
- scene.BordersLocked = false;
- rootConn.RegionScene.BordersLocked = false;
-
if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -600,9 +580,6 @@ namespace OpenSim.Region.RegionCombinerModule
extents.Y = rootConn.YEnd;
extents.X = rootConn.XEnd;
- scene.BordersLocked = true;
- rootConn.RegionScene.BordersLocked = true;
-
RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -618,67 +595,10 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
- lock (rootConn.RegionScene.NorthBorders)
- {
- if (rootConn.RegionScene.NorthBorders.Count == 1)// && 2)
- {
- //compound border
- // already locked above
- rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.EastBorders)
- rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.WestBorders)
- rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- }
- }
-
- lock (scene.SouthBorders)
- {
- scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
- scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
- lock (rootConn.RegionScene.EastBorders)
- {
- if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
- {
- rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.NorthBorders)
- rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.SouthBorders)
- rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- }
- }
-
- lock (scene.WestBorders)
- {
- scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
- scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
- /*
- else
- {
- conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
- conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
- }
- */
-
-
// Reset Terrain.. since terrain normally loads first.
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
- scene.BordersLocked = false;
- rootConn.RegionScene.BordersLocked = false;
if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -687,6 +607,7 @@ namespace OpenSim.Region.RegionCombinerModule
//scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
}
+ */
private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
{
@@ -885,125 +806,6 @@ namespace OpenSim.Region.RegionCombinerModule
// }
// }
- // Create a set of infinite borders around the whole aabb of the combined island.
- private void AdjustLargeRegionBounds()
- {
- lock (m_regions)
- {
- foreach (RegionConnections rconn in m_regions.Values)
- {
- Vector3 offset = Vector3.Zero;
- rconn.RegionScene.BordersLocked = true;
- foreach (RegionData rdata in rconn.ConnectedRegions)
- {
- if (rdata.Offset.X > offset.X) offset.X = rdata.Offset.X;
- if (rdata.Offset.Y > offset.Y) offset.Y = rdata.Offset.Y;
- }
-
- lock (rconn.RegionScene.NorthBorders)
- {
- Border northBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.NorthBorders, out northBorder))
- {
- northBorder = new Border();
- rconn.RegionScene.NorthBorders.Add(northBorder);
- }
-
- northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,
- offset.Y + (int) Constants.RegionSize); //<---
- northBorder.CrossDirection = Cardinals.N;
- }
-
- lock (rconn.RegionScene.SouthBorders)
- {
- Border southBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.SouthBorders, out southBorder))
- {
- southBorder = new Border();
- rconn.RegionScene.SouthBorders.Add(southBorder);
- }
- southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
- southBorder.CrossDirection = Cardinals.S;
- }
-
- lock (rconn.RegionScene.EastBorders)
- {
- Border eastBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.EastBorders, out eastBorder))
- {
- eastBorder = new Border();
- rconn.RegionScene.EastBorders.Add(eastBorder);
- }
- eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, offset.X + (int)Constants.RegionSize);
- //<---
- eastBorder.CrossDirection = Cardinals.E;
- }
-
- lock (rconn.RegionScene.WestBorders)
- {
- Border westBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.WestBorders, out westBorder))
- {
- westBorder = new Border();
- rconn.RegionScene.WestBorders.Add(westBorder);
-
- }
- westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
- westBorder.CrossDirection = Cardinals.W;
- }
-
- rconn.RegionScene.BordersLocked = false;
- }
- }
- }
-
- ///
- /// Try and get an Infinite border out of a listT of borders
- ///
- ///
- ///
- ///
- public static bool TryGetInfiniteBorder(List borders, out Border oborder)
- {
- // Warning! Should be locked before getting here!
- foreach (Border b in borders)
- {
- if (b.BorderLine.X == float.MinValue && b.BorderLine.Y == float.MaxValue)
- {
- oborder = b;
- return true;
- }
- }
-
- oborder = null;
- return false;
- }
-
- public RegionData GetRegionFromPosition(Vector3 pPosition)
- {
- pPosition = pPosition/(int) Constants.RegionSize;
- int OffsetX = (int) pPosition.X;
- int OffsetY = (int) pPosition.Y;
-
- lock (m_regions)
- {
- foreach (RegionConnections regConn in m_regions.Values)
- {
- foreach (RegionData reg in regConn.ConnectedRegions)
- {
- if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY)
- return reg;
- }
- }
- }
-
- return new RegionData();
- }
-
public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
{
if (BigRegion.PermissionModule == null)