Rewrite of mega-region code to use new form of border checking.

This commit eliminates all of the 'border' class and list code and replaces
it with testing if in the current region.
Impacts: can make a mega-region out of varregions of the same size; and
mega-region combinations must be rectangular (not square but rectangular)
0.8.0.3
Robert Adams 2014-02-15 16:01:43 -08:00
parent bdbbeaa494
commit 877bdcdce1
7 changed files with 114 additions and 626 deletions

View File

@ -464,7 +464,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Name, position, sp.Scene.RegionInfo.RegionName); sp.Name, position, sp.Scene.RegionInfo.RegionName);
// Teleport within the same region // 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); Vector3 emergencyPos = new Vector3(128, 128, 128);
@ -580,7 +580,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
MapBlockData block = new MapBlockData(); MapBlockData block = new MapBlockData();
block.X = (ushort)regX; block.X = (ushort)regX;
block.Y = (ushort)regY; block.Y = (ushort)regY;
block.Access = 254; // == not there block.Access = (byte)SimAccess.Down;
List<MapBlockData> blocks = new List<MapBlockData>(); List<MapBlockData> blocks = new List<MapBlockData>();
blocks.Add(block); blocks.Add(block);
@ -713,10 +713,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return; return;
} }
uint newRegionX = (uint)(reg.RegionHandle >> 40); uint newRegionX, newRegionY, oldRegionX, oldRegionY;
uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
ulong destinationHandle = finalDestination.RegionHandle; ulong destinationHandle = finalDestination.RegionHandle;
@ -1333,6 +1332,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return region; 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) protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
{ {
if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
@ -1357,20 +1359,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 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 #endregion
#region Landmark Teleport #region Landmark Teleport
@ -2077,7 +2065,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public NotFoundLocationCache() public NotFoundLocationCache()
{ {
} }
// Add an area to the lost of 'not found' places. The area is the snapped region // Add an area to the list of 'not found' places. The area is the snapped region
// area around the added point. // area around the added point.
public void Add(double pX, double pY) public void Add(double pX, double pY)
{ {
@ -2305,22 +2293,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <param name='neCorner'></param> /// <param name='neCorner'></param>
private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner) private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
{ {
Border[] northBorders = Scene.NorthBorders.ToArray();
Border[] eastBorders = Scene.EastBorders.ToArray();
Vector2 extent = Vector2.Zero; Vector2 extent = Vector2.Zero;
for (int i = 0; i < eastBorders.Length; i++)
{
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;
}
// Loss of fraction on purpose if (m_regionCombinerModule != null)
extent.X = ((int)extent.X / (int)Constants.RegionSize); {
extent.Y = ((int)extent.Y / (int)Constants.RegionSize); Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
}
swCorner.X = Scene.RegionInfo.RegionLocX - 1; swCorner.X = Scene.RegionInfo.RegionLocX - 1;
swCorner.Y = Scene.RegionInfo.RegionLocY - 1; swCorner.Y = Scene.RegionInfo.RegionLocY - 1;

View File

@ -55,5 +55,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// Currently, will throw an exception if this does not match a root region. /// Currently, will throw an exception if this does not match a root region.
/// </param> /// </param>
Vector2 GetSizeOfMegaregion(UUID regionId); Vector2 GetSizeOfMegaregion(UUID regionId);
/// <summary>
/// Tests to see of position (relative to the region) is within the megaregion
/// </summary>
bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy);
} }
} }

View File

@ -160,11 +160,6 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public SimStatsReporter StatsReporter { get; private set; } public SimStatsReporter StatsReporter { get; private set; }
public List<Border> NorthBorders = new List<Border>();
public List<Border> EastBorders = new List<Border>();
public List<Border> SouthBorders = new List<Border>();
public List<Border> WestBorders = new List<Border>();
/// <summary> /// <summary>
/// Controls whether physics can be applied to prims. Even if false, prims still have entries in a /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
/// PhysicsScene in order to perform collision detection /// PhysicsScene in order to perform collision detection
@ -349,7 +344,6 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: Possibly stop other classes being able to manipulate this directly. // TODO: Possibly stop other classes being able to manipulate this directly.
private SceneGraph m_sceneGraph; private SceneGraph m_sceneGraph;
private volatile int m_bordersLocked;
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
private volatile bool m_backingup; private volatile bool m_backingup;
private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
@ -426,18 +420,6 @@ namespace OpenSim.Region.Framework.Scenes
set { m_splitRegionID = value; } 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 public new float TimeDilation
{ {
get { return m_sceneGraph.PhysicsScene.TimeDilation; } get { return m_sceneGraph.PhysicsScene.TimeDilation; }
@ -1031,28 +1013,6 @@ namespace OpenSim.Region.Framework.Scenes
PeriodicBackup = true; PeriodicBackup = true;
UseBackup = true; UseBackup = true;
BordersLocked = true;
Border northBorder = new Border();
northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)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, (float)RegionInfo.RegionSizeY); //<---
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_eventManager = new EventManager();
m_permissions = new ScenePermissions(this); m_permissions = new ScenePermissions(this);
@ -2445,201 +2405,34 @@ namespace OpenSim.Region.Framework.Scenes
} }
// Simple test to see if a position is in the current region. // Simple test to see if a position is in the current region.
// Resuming the position is relative to the region so anything outside its bounds. // 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. // Return 'true' if position inside region.
public bool PositionIsInCurrentRegion(Vector3 pos) public bool PositionIsInCurrentRegion(Vector3 pos)
{ {
bool ret = true; bool ret = false;
int xx = (int)Math.Floor(pos.X); int xx = (int)Math.Floor(pos.X);
int yy = (int)Math.Floor(pos.Y); int yy = (int)Math.Floor(pos.Y);
if (xx < 0 if (xx < 0 || yy < 0)
|| xx >= RegionInfo.RegionSizeX return false;
|| yy < 0
|| yy >= RegionInfo.RegionSizeY) IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>();
ret = false; if (regionCombinerModule == null)
{
// Regular region. Just check for region size
if (xx < RegionInfo.RegionSizeX || yy < RegionInfo.RegionSizeY )
ret = true;
}
else
{
// 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 ret; return ret;
} }
public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
{
if (BordersLocked)
{
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;
}
}
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;
}
}
return null;
}
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;
}
/// <summary> /// <summary>
/// Called when objects or attachments cross the border, or teleport, between regions. /// Called when objects or attachments cross the border, or teleport, between regions.
/// </summary> /// </summary>
@ -3874,61 +3667,11 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// CleanDroppedAttachments(); // CleanDroppedAttachments();
if (TestBorderCross(acd.startpos, Cardinals.E)) // 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;
Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
acd.startpos.X = crossedBorder.BorderLine.Z - 1; if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
m_log.DebugFormat("{0} NewUserConnection Adjusted border E. startpos={1}", LogHeader, acd.startpos); if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
}
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;
}
}
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", // "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",

View File

@ -429,7 +429,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns></returns> /// <returns></returns>
public bool IsAttachmentCheckFull() public bool IsAttachmentCheckFull()
{ {
return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); return (IsAttachment || (m_rootPart.Shape.PCode == (byte)PCodeEnum.Primitive && m_rootPart.Shape.State != 0));
} }
private struct avtocrossInfo private struct avtocrossInfo
@ -451,19 +451,10 @@ namespace OpenSim.Region.Framework.Scenes
if (Scene != null) if (Scene != null)
{ {
if ( if (
// (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) !Scene.PositionIsInCurrentRegion(val)
// || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) && !IsAttachmentCheckFull()
// || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) && (!Scene.LoadingPrims)
// || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) )
// Experimental change for better border crossings.
// The commented out original lines above would, it seems, trigger
// a border crossing a little early or late depending on which
// direction the object was moving.
(Scene.TestBorderCross(val, Cardinals.E)
|| Scene.TestBorderCross(val, Cardinals.W)
|| Scene.TestBorderCross(val, Cardinals.N)
|| Scene.TestBorderCross(val, Cardinals.S))
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
{ {
IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
string version = String.Empty; string version = String.Empty;

View File

@ -2479,13 +2479,10 @@ namespace OpenSim.Region.Framework.Scenes
if (pa != null) if (pa != null)
{ {
Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); Vector3 newpos = pa.Position;
if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
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))
{ {
// Setting position outside current region will start region crossing
ParentGroup.AbsolutePosition = newpos; ParentGroup.AbsolutePosition = newpos;
return; return;
} }

View File

@ -116,37 +116,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
+ "If teleport is true then some extra teleport debug information is logged.\n" + "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.", + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
HandleDebugSceneSetCommand); 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) private void HandleDebugSceneGetCommand(string module, string[] args)

View File

@ -44,6 +44,7 @@ namespace OpenSim.Region.RegionCombinerModule
public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[REGION COMBINER MODULE]";
public string Name public string Name
{ {
@ -134,6 +135,49 @@ namespace OpenSim.Region.RegionCombinerModule
throw new Exception(string.Format("Region with id {0} not found", regionId)); 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) private void NewPresence(ScenePresence presence)
{ {
if (presence.IsChildAgent) if (presence.IsChildAgent)
@ -220,27 +264,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(); RegionConnections newConn = new RegionConnections();
newConn.ConnectedRegions = new List<RegionData>(); newConn.ConnectedRegions = new List<RegionData>();
newConn.RegionScene = scene; newConn.RegionScene = scene;
@ -248,8 +271,8 @@ namespace OpenSim.Region.RegionCombinerModule
newConn.RegionId = scene.RegionInfo.originRegionID; newConn.RegionId = scene.RegionInfo.originRegionID;
newConn.X = scene.RegionInfo.RegionLocX; newConn.X = scene.RegionInfo.RegionLocX;
newConn.Y = scene.RegionInfo.RegionLocY; newConn.Y = scene.RegionInfo.RegionLocY;
newConn.XEnd = (int)Constants.RegionSize; newConn.XEnd = scene.RegionInfo.RegionSizeX;
newConn.YEnd = (int)Constants.RegionSize; newConn.YEnd = scene.RegionInfo.RegionSizeX;
lock (m_regions) lock (m_regions)
{ {
@ -415,6 +438,11 @@ namespace OpenSim.Region.RegionCombinerModule
*/ */
#endregion #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) // If we're one region over +x y (i.e. root region is to the west)
//xxx //xxx
//xxy //xxy
@ -431,7 +459,7 @@ namespace OpenSim.Region.RegionCombinerModule
//xxx //xxx
if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY) if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
{ {
connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene); connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
break; break;
} }
@ -441,9 +469,8 @@ namespace OpenSim.Region.RegionCombinerModule
//xxx //xxx
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY) if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
{ {
connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene); connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
break; break;
} }
} }
@ -453,20 +480,20 @@ namespace OpenSim.Region.RegionCombinerModule
DoWorkForRootRegion(newConn, scene); 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) 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; Vector3 offset = Vector3.Zero;
offset.X = newConn.PosX - rootConn.PosX; offset.X = newConn.PosX - rootConn.PosX;
offset.Y = newConn.PosY - rootConn.PosY; 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; Vector3 extents = Vector3.Zero;
extents.Y = rootConn.YEnd; extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
extents.X = rootConn.XEnd + newConn.XEnd; extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
rootConn.UpdateExtents(extents); rootConn.UpdateExtents(extents);
@ -475,9 +502,6 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.RegionInfo.RegionName, rootConn.RegionScene.RegionInfo.RegionName,
newConn.RegionScene.RegionInfo.RegionName, offset, extents); newConn.RegionScene.RegionInfo.RegionName, offset, extents);
scene.BordersLocked = true;
rootConn.RegionScene.BordersLocked = true;
RegionData ConnectedRegion = new RegionData(); RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset; ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@ -490,34 +514,10 @@ namespace OpenSim.Region.RegionCombinerModule
// Inform Child region that it needs to forward it's terrain to the root region // Inform Child region that it needs to forward it's terrain to the root region
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 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 // Reset Terrain.. since terrain loads before we get here, we need to load
// it again so it loads in the root region // it again so it loads in the root region
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 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. // Create a client event forwarder and add this region's events to the root region.
if (rootConn.ClientEventForwarder != null) if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@ -525,6 +525,9 @@ namespace OpenSim.Region.RegionCombinerModule
return true; 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) private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
{ {
Vector3 offset = Vector3.Zero; Vector3 offset = Vector3.Zero;
@ -536,9 +539,6 @@ namespace OpenSim.Region.RegionCombinerModule
extents.X = rootConn.XEnd; extents.X = rootConn.XEnd;
rootConn.UpdateExtents(extents); rootConn.UpdateExtents(extents);
scene.BordersLocked = true;
rootConn.RegionScene.BordersLocked = true;
RegionData ConnectedRegion = new RegionData(); RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset; ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@ -553,30 +553,11 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 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. // Reset Terrain.. since terrain normally loads first.
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
scene.BordersLocked = false;
rootConn.RegionScene.BordersLocked = false;
if (rootConn.ClientEventForwarder != null) if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@ -600,9 +581,6 @@ namespace OpenSim.Region.RegionCombinerModule
extents.Y = rootConn.YEnd; extents.Y = rootConn.YEnd;
extents.X = rootConn.XEnd; extents.X = rootConn.XEnd;
scene.BordersLocked = true;
rootConn.RegionScene.BordersLocked = true;
RegionData ConnectedRegion = new RegionData(); RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset; ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@ -618,67 +596,10 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 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. // Reset Terrain.. since terrain normally loads first.
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
//conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
scene.BordersLocked = false;
rootConn.RegionScene.BordersLocked = false;
if (rootConn.ClientEventForwarder != null) if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@ -687,6 +608,7 @@ namespace OpenSim.Region.RegionCombinerModule
//scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents); //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
} }
*/
private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene) private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
{ {
@ -885,125 +807,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;
}
}
}
/// <summary>
/// Try and get an Infinite border out of a listT of borders
/// </summary>
/// <param name="borders"></param>
/// <param name="oborder"></param>
/// <returns></returns>
public static bool TryGetInfiniteBorder(List<Border> 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) public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
{ {
if (BigRegion.PermissionModule == null) if (BigRegion.PermissionModule == null)