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)