aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/RegionInfo.cs31
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs840
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs325
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs60
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs33
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs320
9 files changed, 526 insertions, 1103 deletions
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index ae2ff63..90188d2 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -149,11 +149,32 @@ namespace OpenSim.Framework
149 public uint WorldLocX = 0; 149 public uint WorldLocX = 0;
150 public uint WorldLocY = 0; 150 public uint WorldLocY = 0;
151 public uint WorldLocZ = 0; 151 public uint WorldLocZ = 0;
152
153 /// <summary>
154 /// X dimension of the region.
155 /// </summary>
156 /// <remarks>
157 /// If this is a varregion then the default size set here will be replaced when we load the region config.
158 /// </remarks>
152 public uint RegionSizeX = Constants.RegionSize; 159 public uint RegionSizeX = Constants.RegionSize;
160
161 /// <summary>
162 /// X dimension of the region.
163 /// </summary>
164 /// <remarks>
165 /// If this is a varregion then the default size set here will be replaced when we load the region config.
166 /// </remarks>
153 public uint RegionSizeY = Constants.RegionSize; 167 public uint RegionSizeY = Constants.RegionSize;
168
169 /// <summary>
170 /// Z dimension of the region.
171 /// </summary>
172 /// <remarks>
173 /// XXX: Unknown if this accounts for regions with negative Z.
174 /// </remarks>
154 public uint RegionSizeZ = Constants.RegionHeight; 175 public uint RegionSizeZ = Constants.RegionHeight;
155 176
156 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>(); 177 private Dictionary<String, String> m_extraSettings = new Dictionary<string, string>();
157 178
158 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. 179 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
159 180
@@ -506,16 +527,16 @@ namespace OpenSim.Framework
506 { 527 {
507 string val; 528 string val;
508 string keylower = key.ToLower(); 529 string keylower = key.ToLower();
509 if (m_otherSettings.TryGetValue(keylower, out val)) 530 if (m_extraSettings.TryGetValue(keylower, out val))
510 return val; 531 return val;
511 m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key); 532 m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key);
512 return null; 533 return null;
513 } 534 }
514 535
515 public void SetOtherSetting(string key, string value) 536 public void SetExtraSetting(string key, string value)
516 { 537 {
517 string keylower = key.ToLower(); 538 string keylower = key.ToLower();
518 m_otherSettings[keylower] = value; 539 m_extraSettings[keylower] = value;
519 } 540 }
520 541
521 private void ReadNiniConfig(IConfigSource source, string name) 542 private void ReadNiniConfig(IConfigSource source, string name)
@@ -733,7 +754,7 @@ namespace OpenSim.Framework
733 754
734 foreach (String s in allKeys) 755 foreach (String s in allKeys)
735 { 756 {
736 SetOtherSetting(s, config.GetString(s)); 757 SetExtraSetting(s, config.GetString(s));
737 } 758 }
738 } 759 }
739 760
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index b32a169..0f6c507 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
121 /// </summary> 121 /// </summary>
122 private EntityTransferStateMachine m_entityTransferStateMachine; 122 private EntityTransferStateMachine m_entityTransferStateMachine;
123 123
124 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = 124 // For performance, we keed a cached of banned regions so we don't keep going
125 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 125 // to the grid service.
126 private class BannedRegionCache
127 {
128 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
129 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
130 ExpiringCache<ulong, DateTime> m_idCache;
131 DateTime m_banUntil;
132 public BannedRegionCache()
133 {
134 }
135 // Return 'true' if there is a valid ban entry for this agent in this region
136 public bool IfBanned(ulong pRegionHandle, UUID pAgentID)
137 {
138 bool ret = false;
139 if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
140 {
141 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
142 {
143 if (DateTime.Now < m_banUntil)
144 {
145 ret = true;
146 }
147 }
148 }
149 return ret;
150 }
151 // Add this agent in this region as a banned person
152 public void Add(ulong pRegionHandle, UUID pAgentID)
153 {
154 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
155 {
156 m_idCache = new ExpiringCache<ulong, DateTime>();
157 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45));
158 }
159 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
160 }
161 // Remove the agent from the region's banned list
162 public void Remove(ulong pRegionHandle, UUID pAgentID)
163 {
164 if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
165 {
166 m_idCache.Remove(pRegionHandle);
167 }
168 }
169 }
170 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
126 171
127 private IEventQueue m_eqModule; 172 private IEventQueue m_eqModule;
128 private IRegionCombinerModule m_regionCombinerModule; 173 private IRegionCombinerModule m_regionCombinerModule;
@@ -337,6 +382,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
337 "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name); 382 "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
338 } 383 }
339 384
385 // Attempt to teleport the ScenePresence to the specified position in the specified region (spec'ed by its handle).
340 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) 386 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
341 { 387 {
342 if (sp.Scene.Permissions.IsGridGod(sp.UUID)) 388 if (sp.Scene.Permissions.IsGridGod(sp.UUID))
@@ -418,7 +464,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
418 sp.Name, position, sp.Scene.RegionInfo.RegionName); 464 sp.Name, position, sp.Scene.RegionInfo.RegionName);
419 465
420 // Teleport within the same region 466 // Teleport within the same region
421 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) 467 if (!sp.Scene.PositionIsInCurrentRegion(position) || position.Z < 0)
422 { 468 {
423 Vector3 emergencyPos = new Vector3(128, 128, 128); 469 Vector3 emergencyPos = new Vector3(128, 128, 128);
424 470
@@ -437,10 +483,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
437 float posZLimit = 22; 483 float posZLimit = 22;
438 484
439 // TODO: Check other Scene HeightField 485 // TODO: Check other Scene HeightField
440 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) 486 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
441 {
442 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
443 }
444 487
445 posZLimit += localHalfAVHeight + 0.1f; 488 posZLimit += localHalfAVHeight + 0.1f;
446 489
@@ -484,9 +527,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
484 ScenePresence sp, ulong regionHandle, Vector3 position, 527 ScenePresence sp, ulong regionHandle, Vector3 position,
485 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination) 528 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
486 { 529 {
487 uint x = 0, y = 0; 530 // Get destination region taking into account that the address could be an offset
488 Utils.LongToUInts(regionHandle, out x, out y); 531 // region inside a varregion.
489 GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); 532 GridRegion reg = GetTeleportDestinationRegion(sp.Scene.GridService, sp.Scene.RegionInfo.ScopeID, regionHandle, ref position);
490 533
491 if (reg != null) 534 if (reg != null)
492 { 535 {
@@ -537,12 +580,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
537 580
538 // and set the map-tile to '(Offline)' 581 // and set the map-tile to '(Offline)'
539 uint regX, regY; 582 uint regX, regY;
540 Utils.LongToUInts(regionHandle, out regX, out regY); 583 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
541 584
542 MapBlockData block = new MapBlockData(); 585 MapBlockData block = new MapBlockData();
543 block.X = (ushort)(regX / Constants.RegionSize); 586 block.X = (ushort)(regX / Constants.RegionSize);
544 block.Y = (ushort)(regY / Constants.RegionSize); 587 block.Y = (ushort)(regY / Constants.RegionSize);
545 block.Access = 254; // == not there 588 block.Access = (byte)SimAccess.Down; // == not there
546 589
547 List<MapBlockData> blocks = new List<MapBlockData>(); 590 List<MapBlockData> blocks = new List<MapBlockData>();
548 blocks.Add(block); 591 blocks.Add(block);
@@ -550,6 +593,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
550 } 593 }
551 } 594 }
552 595
596 // The teleport address could be an address in a subregion of a larger varregion.
597 // Find the real base region and adjust the teleport location to account for the
598 // larger region.
599 private GridRegion GetTeleportDestinationRegion(IGridService gridService, UUID scope, ulong regionHandle, ref Vector3 position)
600 {
601 uint x = 0, y = 0;
602 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
603
604 // Compute the world location we're teleporting to
605 double worldX = (double)x + position.X;
606 double worldY = (double)y + position.Y;
607
608 // Find the region that contains the position
609 GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
610
611 if (reg != null)
612 {
613 // modify the position for the offset into the actual region returned
614 position.X += x - reg.RegionLocX;
615 position.Y += y - reg.RegionLocY;
616 }
617
618 return reg;
619 }
620
553 // Nothing to validate here 621 // Nothing to validate here
554 protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) 622 protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
555 { 623 {
@@ -650,10 +718,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
650 return; 718 return;
651 } 719 }
652 720
653 uint newRegionX = (uint)(reg.RegionHandle >> 40); 721 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
654 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); 722 Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
655 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); 723 Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
656 uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
657 724
658 ulong destinationHandle = finalDestination.RegionHandle; 725 ulong destinationHandle = finalDestination.RegionHandle;
659 726
@@ -675,8 +742,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
675 742
676 string reason; 743 string reason;
677 string version; 744 string version;
745 string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
678 if (!Scene.SimulationService.QueryAccess( 746 if (!Scene.SimulationService.QueryAccess(
679 finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) 747 finalDestination, sp.ControllingClient.AgentId, position, out version, out reason))
680 { 748 {
681 sp.ControllingClient.SendTeleportFailed(reason); 749 sp.ControllingClient.SendTeleportFailed(reason);
682 750
@@ -1274,6 +1342,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1274 return region; 1342 return region;
1275 } 1343 }
1276 1344
1345 // This returns 'true' if the new region already has a child agent for our
1346 // incoming agent. The implication is that, if 'false', we have to create the
1347 // child and then teleport into the region.
1277 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1348 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
1278 { 1349 {
1279 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 1350 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
@@ -1298,20 +1369,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1298 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1369 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
1299 } 1370 }
1300 1371
1301 protected virtual bool IsOutsideRegion(Scene s, Vector3 pos)
1302 {
1303 if (s.TestBorderCross(pos, Cardinals.N))
1304 return true;
1305 if (s.TestBorderCross(pos, Cardinals.S))
1306 return true;
1307 if (s.TestBorderCross(pos, Cardinals.E))
1308 return true;
1309 if (s.TestBorderCross(pos, Cardinals.W))
1310 return true;
1311
1312 return false;
1313 }
1314
1315 #endregion 1372 #endregion
1316 1373
1317 #region Landmark Teleport 1374 #region Landmark Teleport
@@ -1390,214 +1447,80 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1390 1447
1391 #region Agent Crossings 1448 #region Agent Crossings
1392 1449
1393 public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason)
1394 {
1395 reason = String.Empty;
1396 version = String.Empty;
1397
1398 UUID agentID = agent.UUID;
1399 ulong destinyHandle = destiny.RegionHandle;
1400
1401 ExpiringCache<ulong, DateTime> r;
1402 DateTime banUntil;
1403 if (m_bannedRegions.TryGetValue(agentID, out r))
1404 {
1405 if (r.TryGetValue(destinyHandle, out banUntil))
1406 {
1407 if (DateTime.Now < banUntil)
1408 {
1409 reason = "Cannot connect to region";
1410 return false;
1411 }
1412 r.Remove(destinyHandle);
1413 }
1414 }
1415 else
1416 {
1417 r = null;
1418 }
1419
1420 Scene ascene = agent.Scene;
1421
1422 if (!ascene.SimulationService.QueryAccess(destiny, agentID, position, out version, out reason))
1423 {
1424 if (r == null)
1425 {
1426 r = new ExpiringCache<ulong, DateTime>();
1427 r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
1428
1429 m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(30));
1430 }
1431 else
1432 {
1433 r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
1434 }
1435 return false;
1436 }
1437 return true;
1438 }
1439
1440 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos) 1450 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
1441 { 1451 {
1442 string r = String.Empty; 1452 string r = String.Empty;
1443 return GetDestination(scene, agentID, pos, out version, out newpos, out r); 1453 return GetDestination(scene, agentID, pos, out version, out newpos, out r);
1444 } 1454 }
1445 1455
1446 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos, out string reason) 1456 // Given a position relative to the current region (which has previously been tested to
1457 // see that it is actually outside the current region), find the new region that the
1458 // point is actually in.
1459 // Returns the coordinates and information of the new region or 'null' of it doesn't exist.
1460 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
1461 out string version, out Vector3 newpos, out string failureReason)
1447 { 1462 {
1448 version = String.Empty; 1463 version = String.Empty;
1449 reason = String.Empty;
1450 newpos = pos; 1464 newpos = pos;
1465 failureReason = string.Empty;
1451 1466
1452// m_log.DebugFormat( 1467// m_log.DebugFormat(
1453// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1468// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1454 1469
1455 RegionInfo regInfo = scene.RegionInfo; 1470 // Compute world location of the object's position
1471 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1472 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1456 1473
1457 uint neighbourx = regInfo.RegionLocX; 1474 // Call the grid service to lookup the region containing the new position.
1458 uint neighboury = regInfo.RegionLocY; 1475 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
1459 const float boundaryDistance = 0.7f; 1476 presenceWorldX, presenceWorldY,
1460 1477 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1461/*
1462 Vector3 northCross = new Vector3(0, boundaryDistance, 0);
1463 Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
1464 Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
1465 Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
1466 1478
1467 // distance into new region to place avatar 1479 if (neighbourRegion != null)
1468 const float enterDistance = 0.5f;
1469 const float maxX = Constants.RegionSize - enterDistance;
1470 const float maxY = Constants.RegionSize - enterDistance;
1471
1472 if (scene.TestBorderCross(pos + westCross, Cardinals.W))
1473 { 1480 {
1474 if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1481 // Compute the entity's position relative to the new region
1475 { 1482 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1476 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); 1483 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1477 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); 1484 pos.Z);
1478 newpos.Y -= Constants.RegionSize;
1479 }
1480 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1481 {
1482 neighboury--;
1483 newpos.Y += Constants.RegionSize;
1484 }
1485
1486 neighbourx--;
1487 newpos.X += Constants.RegionSize;
1488 }
1489 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
1490 {
1491 Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
1492 neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
1493 newpos.X -= Constants.RegionSize;
1494 1485
1495 if (scene.TestBorderCross(pos + southCross, Cardinals.S)) 1486 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1496 { 1487 {
1497 neighboury--; 1488 failureReason = "Cannot region cross into banned parcel";
1498 newpos.Y += Constants.RegionSize; 1489 neighbourRegion = null;
1499 } 1490 }
1500 else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1491 else
1501 { 1492 {
1502 Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N); 1493 // If not banned, make sure this agent is not in the list.
1503 neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize); 1494 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1504 newpos.Y -= Constants.RegionSize;
1505 } 1495 }
1506 }
1507 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1508 {
1509 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
1510 neighboury--;
1511 newpos.Y += Constants.RegionSize;
1512 }
1513 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
1514 {
1515 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
1516 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
1517 newpos.Y -= Constants.RegionSize;
1518 }
1519 1496
1520 newpos.X = Util.Clamp(newpos.X, enterDistance, maxX); 1497 // Check to see if we have access to the target region.
1521 newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY); 1498 string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
1522*/ 1499 if (neighbourRegion != null
1523 float regionSizeX = regInfo.RegionSizeX; 1500 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out failureReason))
1524 float regionSizeY = regInfo.RegionSizeY;
1525
1526 if (pos.X < boundaryDistance)
1527 neighbourx--;
1528 else if (pos.X > regionSizeX - boundaryDistance)
1529 neighbourx += (uint)(regionSizeX / Constants.RegionSize);
1530
1531 if (pos.Y < boundaryDistance)
1532 neighboury--;
1533 else if (pos.Y > regionSizeY - boundaryDistance)
1534 neighboury += (uint)(regionSizeY / Constants.RegionSize);
1535
1536 int x = (int)(neighbourx * Constants.RegionSize);
1537 int y = (int)(neighboury * Constants.RegionSize);
1538
1539 ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y);
1540
1541 ExpiringCache<ulong, DateTime> r;
1542 DateTime banUntil;
1543
1544 if (m_bannedRegions.TryGetValue(agentID, out r))
1545 {
1546 if (r.TryGetValue(neighbourHandle, out banUntil))
1547 { 1501 {
1548 if (DateTime.Now < banUntil) 1502 // remember banned
1549 return null; 1503 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1550 r.Remove(neighbourHandle); 1504 neighbourRegion = null;
1551 } 1505 }
1552 } 1506 }
1553 else 1507 else
1554 { 1508 {
1555 r = null; 1509 // The destination region just doesn't exist
1510 failureReason = "Cannot cross into non-existent region";
1556 } 1511 }
1557 1512
1558 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
1559 if (neighbourRegion == null) 1513 if (neighbourRegion == null)
1560 { 1514 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1561 reason = ""; 1515 LogHeader, scene.RegionInfo.RegionName,
1562 return null; 1516 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1563 } 1517 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1564 1518 pos);
1565 float newRegionSizeX = neighbourRegion.RegionSizeX; 1519 else
1566 float newRegionSizeY = neighbourRegion.RegionSizeY; 1520 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
1567 if (newRegionSizeX == 0) 1521 LogHeader, neighbourRegion.RegionName,
1568 newRegionSizeX = Constants.RegionSize; 1522 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1569 if (newRegionSizeY == 0) 1523 newpos.X, newpos.Y);
1570 newRegionSizeY = Constants.RegionSize;
1571
1572 if (pos.X < boundaryDistance)
1573 newpos.X += newRegionSizeX;
1574 else if (pos.X > regionSizeX - boundaryDistance)
1575 newpos.X -= regionSizeX;
1576
1577 if (pos.Y < boundaryDistance)
1578 newpos.Y += newRegionSizeY;
1579 else if (pos.Y > regionSizeY - boundaryDistance)
1580 newpos.Y -= regionSizeY;
1581
1582 const float enterDistance = 0.5f;
1583 newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
1584 newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
1585
1586 if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
1587 {
1588 if (r == null)
1589 {
1590 r = new ExpiringCache<ulong, DateTime>();
1591 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
1592
1593 m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45));
1594 }
1595 else
1596 {
1597 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
1598 }
1599 return null;
1600 }
1601 1524
1602 return neighbourRegion; 1525 return neighbourRegion;
1603 } 1526 }
@@ -1632,15 +1555,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1632 uint y; 1555 uint y;
1633 Vector3 newpos; 1556 Vector3 newpos;
1634 string version; 1557 string version;
1635 string reason; 1558 string failureReason;
1636 1559
1637 Vector3 pos = agent.AbsolutePosition + agent.Velocity; 1560 Vector3 pos = agent.AbsolutePosition + agent.Velocity;
1638 1561
1639 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out version, out newpos, out reason); 1562 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
1563 out version, out newpos, out failureReason);
1640 if (neighbourRegion == null) 1564 if (neighbourRegion == null)
1641 { 1565 {
1642 if (reason != String.Empty) 1566 if (failureReason != String.Empty)
1643 agent.ControllingClient.SendAlertMessage("Cannot cross to region"); 1567 agent.ControllingClient.SendAlertMessage(failureReason);
1644 return agent; 1568 return agent;
1645 } 1569 }
1646 1570
@@ -1678,7 +1602,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1678 1602
1679 agent.Scene.RequestTeleportLocation( 1603 agent.Scene.RequestTeleportLocation(
1680 agent.ControllingClient, 1604 agent.ControllingClient,
1681 Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize), 1605 Util.RegionLocToHandle(regionX, regionY),
1682 position, 1606 position,
1683 agent.Lookat, 1607 agent.Lookat,
1684 (uint)Constants.TeleportFlags.ViaLocation); 1608 (uint)Constants.TeleportFlags.ViaLocation);
@@ -1688,11 +1612,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1688 if (im != null) 1612 if (im != null)
1689 { 1613 {
1690 UUID gotoLocation = Util.BuildFakeParcelID( 1614 UUID gotoLocation = Util.BuildFakeParcelID(
1691 Util.UIntsToLong( 1615 Util.RegionLocToHandle(regionX, regionY),
1692 (regionX *
1693 (uint)Constants.RegionSize),
1694 (regionY *
1695 (uint)Constants.RegionSize)),
1696 (uint)(int)position.X, 1616 (uint)(int)position.X,
1697 (uint)(int)position.Y, 1617 (uint)(int)position.Y,
1698 (uint)(int)position.Z); 1618 (uint)(int)position.Z);
@@ -1745,8 +1665,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1745 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1665 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1746 /// </summary> 1666 /// </summary>
1747 public ScenePresence CrossAgentToNewRegionAsync( 1667 public ScenePresence CrossAgentToNewRegionAsync(
1748 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, 1668 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1749 bool isFlying, string version) 1669 bool isFlying, string version)
1750 { 1670 {
1751 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) 1671 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
1752 { 1672 {
@@ -1893,11 +1813,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1893 // Next, let's close the child agent connections that are too far away. 1813 // Next, let's close the child agent connections that are too far away.
1894 uint neighbourx; 1814 uint neighbourx;
1895 uint neighboury; 1815 uint neighboury;
1896 1816 Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1897 Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1898
1899 neighbourx /= Constants.RegionSize;
1900 neighboury /= Constants.RegionSize;
1901 1817
1902 agent.CloseChildAgents(neighbourx, neighboury); 1818 agent.CloseChildAgents(neighbourx, neighboury);
1903 1819
@@ -2059,7 +1975,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2059 1975
2060 if (m_regionInfo != null) 1976 if (m_regionInfo != null)
2061 { 1977 {
2062 neighbours = RequestNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); 1978 neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
2063 } 1979 }
2064 else 1980 else
2065 { 1981 {
@@ -2216,15 +2132,195 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2216 } 2132 }
2217 } 2133 }
2218 2134
2135 // Computes the difference between two region bases.
2136 // Returns a vector of world coordinates (meters) from base of first region to the second.
2137 // The first region is the home region of the passed scene presence.
2219 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2138 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2220 { 2139 {
2221 int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX; 2140 /*
2222 int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY; 2141 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2142 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2223 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize; 2143 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2224 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize; 2144 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2225 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize; 2145 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2226 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize; 2146 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2227 return new Vector3(shiftx, shifty, 0f); 2147 return new Vector3(shiftx, shifty, 0f);
2148 */
2149 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2150 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2151 0f);
2152 }
2153
2154 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2155 {
2156 // Since we don't know how big the regions could be, we have to search a very large area
2157 // to find possible regions.
2158 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2159 }
2160
2161 #region NotFoundLocationCache class
2162 // A collection of not found locations to make future lookups 'not found' lookups quick.
2163 // A simple expiring cache that keeps not found locations for some number of seconds.
2164 // A 'not found' location is presumed to be anywhere in the minimum sized region that
2165 // contains that point. A conservitive estimate.
2166 private class NotFoundLocationCache
2167 {
2168 private struct NotFoundLocation
2169 {
2170 public double minX, maxX, minY, maxY;
2171 public DateTime expireTime;
2172 }
2173 private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
2174 public NotFoundLocationCache()
2175 {
2176 }
2177 // Add an area to the list of 'not found' places. The area is the snapped region
2178 // area around the added point.
2179 public void Add(double pX, double pY)
2180 {
2181 lock (m_notFoundLocations)
2182 {
2183 if (!LockedContains(pX, pY))
2184 {
2185 NotFoundLocation nfl = new NotFoundLocation();
2186 // A not found location is not found for at least a whole region sized area
2187 nfl.minX = pX - (pX % (double)Constants.RegionSize);
2188 nfl.minY = pY - (pY % (double)Constants.RegionSize);
2189 nfl.maxX = nfl.minX + (double)Constants.RegionSize;
2190 nfl.maxY = nfl.minY + (double)Constants.RegionSize;
2191 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2192 m_notFoundLocations.Add(nfl);
2193 }
2194 }
2195
2196 }
2197 // Test to see of this point is in any of the 'not found' areas.
2198 // Return 'true' if the point is found inside the 'not found' areas.
2199 public bool Contains(double pX, double pY)
2200 {
2201 bool ret = false;
2202 lock (m_notFoundLocations)
2203 ret = LockedContains(pX, pY);
2204 return ret;
2205 }
2206 private bool LockedContains(double pX, double pY)
2207 {
2208 bool ret = false;
2209 this.DoExpiration();
2210 foreach (NotFoundLocation nfl in m_notFoundLocations)
2211 {
2212 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
2213 {
2214 ret = true;
2215 break;
2216 }
2217 }
2218 return ret;
2219 }
2220 private void DoExpiration()
2221 {
2222 List<NotFoundLocation> m_toRemove = null;
2223 DateTime now = DateTime.Now;
2224 foreach (NotFoundLocation nfl in m_notFoundLocations)
2225 {
2226 if (nfl.expireTime < now)
2227 {
2228 if (m_toRemove == null)
2229 m_toRemove = new List<NotFoundLocation>();
2230 m_toRemove.Add(nfl);
2231 }
2232 }
2233 if (m_toRemove != null)
2234 {
2235 foreach (NotFoundLocation nfl in m_toRemove)
2236 m_notFoundLocations.Remove(nfl);
2237 m_toRemove.Clear();
2238 }
2239 }
2240 }
2241 #endregion // NotFoundLocationCache class
2242 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2243
2244 // Given a world position (fractional meter coordinate), get the GridRegion info for
2245 // the region containing that point.
2246 // Someday this should be a method on GridService.
2247 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
2248 // the size of the target region is unknown thus the search area might have to be very large.
2249 // Return 'null' if no such region exists.
2250 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2251 double px, double py, uint pSizeHint)
2252 {
2253 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2254 GridRegion ret = null;
2255 const double fudge = 2.0;
2256
2257 // One problem with this routine is negative results. That is, this can be called lots of times
2258 // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
2259 // will be quick 'not found's next time.
2260 // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
2261 // thus re-ask the GridService about the location.
2262 if (m_notFoundLocationCache.Contains(px, py))
2263 {
2264 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2265 return null;
2266 }
2267
2268 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
2269 // the region at the appropriate legacy region location.
2270 uint possibleX = (uint)Math.Floor(px);
2271 possibleX -= possibleX % Constants.RegionSize;
2272 uint possibleY = (uint)Math.Floor(py);
2273 possibleY -= possibleY % Constants.RegionSize;
2274 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
2275 if (ret != null)
2276 {
2277 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2278 LogHeader, possibleX, possibleY, ret.RegionName);
2279 }
2280
2281 if (ret == null)
2282 {
2283 // If the simple lookup failed, search the larger area for a region that contains this point
2284 double range = (double)pSizeHint + fudge;
2285 while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
2286 {
2287 // Get from the grid service a list of regions that might contain this point.
2288 // The region origin will be in the zero direction so only subtract the range.
2289 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2290 (int)(px - range), (int)(px),
2291 (int)(py - range), (int)(py));
2292 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2293 LogHeader, possibleRegions.Count, range);
2294 if (possibleRegions != null && possibleRegions.Count > 0)
2295 {
2296 // If we found some regions, check to see if the point is within
2297 foreach (GridRegion gr in possibleRegions)
2298 {
2299 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2300 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2301 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2302 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
2303 {
2304 // Found a region that contains the point
2305 ret = gr;
2306 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2307 break;
2308 }
2309 }
2310 }
2311 // Larger search area for next time around if not found
2312 range *= 2;
2313 }
2314 }
2315
2316 if (ret == null)
2317 {
2318 // remember this location was not found so we can quickly not find it next time
2319 m_notFoundLocationCache.Add(px, py);
2320 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2321 }
2322
2323 return ret;
2228 } 2324 }
2229 2325
2230 private void InformClientOfNeighbourCompleted(IAsyncResult iar) 2326 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2310,22 +2406,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2310 /// <param name='neCorner'></param> 2406 /// <param name='neCorner'></param>
2311 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner) 2407 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
2312 { 2408 {
2313 Border[] northBorders = Scene.NorthBorders.ToArray();
2314 Border[] eastBorders = Scene.EastBorders.ToArray();
2315
2316 Vector2 extent = Vector2.Zero; 2409 Vector2 extent = Vector2.Zero;
2317 for (int i = 0; i < eastBorders.Length; i++) 2410
2318 { 2411 if (m_regionCombinerModule != null)
2319 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
2320 }
2321 for (int i = 0; i < northBorders.Length; i++)
2322 { 2412 {
2323 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; 2413 Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
2414 extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
2415 extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
2324 } 2416 }
2325 2417
2326 // Loss of fraction on purpose
2327 extent.X = ((int)extent.X / (int)Constants.RegionSize);
2328 extent.Y = ((int)extent.Y / (int)Constants.RegionSize);
2329 2418
2330 swCorner.X = Scene.RegionInfo.RegionLocX - 1; 2419 swCorner.X = Scene.RegionInfo.RegionLocX - 1;
2331 swCorner.Y = Scene.RegionInfo.RegionLocY - 1; 2420 swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
@@ -2340,56 +2429,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2340 /// <param name="pRegionLocX"></param> 2429 /// <param name="pRegionLocX"></param>
2341 /// <param name="pRegionLocY"></param> 2430 /// <param name="pRegionLocY"></param>
2342 /// <returns></returns> 2431 /// <returns></returns>
2343 protected List<GridRegion> RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) 2432 protected List<GridRegion> GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
2344 { 2433 {
2345 Scene pScene = avatar.Scene; 2434 Scene pScene = avatar.Scene;
2346 RegionInfo m_regionInfo = pScene.RegionInfo; 2435 RegionInfo m_regionInfo = pScene.RegionInfo;
2436 List<GridRegion> neighbours;
2347 2437
2348 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't 2438 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
2349 // clear what should be done with a "far view" given that megaregions already extended the 2439 // clear what should be done with a "far view" given that megaregions already extended the
2350 // view to include everything in the megaregion 2440 // view to include everything in the megaregion
2351 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 2441 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2352 { 2442 {
2353 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; 2443 // The area to check is as big as the current region.
2444 // We presume all adjacent regions are the same size as this region.
2445 uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
2446 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2354 2447
2355 dd--; 2448 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
2449 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2;
2356 2450
2357 // region center 2451 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
2358 int endX = (int)pRegionLocX * (int)Constants.RegionSize + (int)(Constants.RegionSize / 2); 2452 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
2359 int endY = (int)pRegionLocY * (int)Constants.RegionSize + (int)(Constants.RegionSize / 2);
2360
2361 int startX = endX - dd;
2362 int startY = endY - dd;
2363
2364 endX += dd;
2365 endY += dd;
2366 2453
2367 if (startX < 0) startX = 0; 2454 neighbours
2368 if (startY < 0) startY = 0; 2455 = avatar.Scene.GridService.GetRegionRange(
2456 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2369 2457
2370 List<GridRegion> neighbours =
2371 avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
2372
2373 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
2374 return neighbours;
2375 } 2458 }
2376 else 2459 else
2377 { 2460 {
2378 Vector2 swCorner, neCorner; 2461 Vector2 swCorner, neCorner;
2379 GetMegaregionViewRange(out swCorner, out neCorner); 2462 GetMegaregionViewRange(out swCorner, out neCorner);
2380 2463
2381 List<GridRegion> neighbours 2464 neighbours
2382 = pScene.GridService.GetRegionRange( 2465 = pScene.GridService.GetRegionRange(
2383 m_regionInfo.ScopeID, 2466 m_regionInfo.ScopeID,
2384 (int)swCorner.X * (int)Constants.RegionSize, 2467 (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
2385 (int)neCorner.X * (int)Constants.RegionSize, 2468 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
2386 (int)swCorner.Y * (int)Constants.RegionSize, 2469 }
2387 (int)neCorner.Y * (int)Constants.RegionSize);
2388 2470
2389 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 2471 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
2472 neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
2390 2473
2391 return neighbours; 2474 return neighbours;
2392 }
2393 } 2475 }
2394/* not in use 2476/* not in use
2395 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2477 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
@@ -2509,8 +2591,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2509 /// 2591 ///
2510 /// This method locates the new region handle and offsets the prim position for the new region 2592 /// This method locates the new region handle and offsets the prim position for the new region
2511 /// </summary> 2593 /// </summary>
2512 /// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
2513 /// <param name="grp">the scene object that we're crossing</param> 2594 /// <param name="grp">the scene object that we're crossing</param>
2595 /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is
2596 /// relative to the region the object currently is in.</param>
2597 /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param>
2514 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) 2598 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
2515 { 2599 {
2516 if (grp == null) 2600 if (grp == null)
@@ -2522,209 +2606,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2522 if (scene == null) 2606 if (scene == null)
2523 return; 2607 return;
2524 2608
2609 // Remember the old group position in case the region lookup fails so position can be restored.
2610 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2525 2611
2526 int thisx = (int)scene.RegionInfo.RegionLocX; 2612 // Compute the absolute position of the object.
2527 int thisy = (int)scene.RegionInfo.RegionLocY; 2613 double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
2528 Vector3 EastCross = new Vector3(0.1f, 0, 0); 2614 double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
2529 Vector3 WestCross = new Vector3(-0.1f, 0, 0);
2530 Vector3 NorthCross = new Vector3(0, 0.1f, 0);
2531 Vector3 SouthCross = new Vector3(0, -0.1f, 0);
2532
2533
2534 // use this if no borders were crossed!
2535 ulong newRegionHandle
2536 = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
2537 (uint)((thisy) * Constants.RegionSize));
2538
2539 Vector3 pos = attemptedPosition;
2540
2541 int changeX = 1;
2542 int changeY = 1;
2543
2544 if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
2545 {
2546 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
2547 {
2548
2549 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2550
2551 if (crossedBorderx.BorderLine.Z > 0)
2552 {
2553 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2554 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2555 }
2556 else
2557 pos.X = ((pos.X + Constants.RegionSize));
2558
2559 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2560 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2561
2562 if (crossedBordery.BorderLine.Z > 0)
2563 {
2564 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2565 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2566 }
2567 else
2568 pos.Y = ((pos.Y + Constants.RegionSize));
2569
2570
2571
2572 newRegionHandle
2573 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
2574 (uint)((thisy - changeY) * Constants.RegionSize));
2575 // x - 1
2576 // y - 1
2577 }
2578 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2579 {
2580 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2581
2582 if (crossedBorderx.BorderLine.Z > 0)
2583 {
2584 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2585 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2586 }
2587 else
2588 pos.X = ((pos.X + Constants.RegionSize));
2589
2590
2591 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2592 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2593
2594 if (crossedBordery.BorderLine.Z > 0)
2595 {
2596 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2597 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2598 }
2599 else
2600 pos.Y = ((pos.Y + Constants.RegionSize));
2601
2602 newRegionHandle
2603 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
2604 (uint)((thisy + changeY) * Constants.RegionSize));
2605 // x - 1
2606 // y + 1
2607 }
2608 else
2609 {
2610 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2611 2615
2612 if (crossedBorderx.BorderLine.Z > 0) 2616 // Ask the grid service for the region that contains the passed address
2613 { 2617 GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
2614 pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); 2618 objectWorldLocX, objectWorldLocY);
2615 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2616 }
2617 else
2618 pos.X = ((pos.X + Constants.RegionSize));
2619 2619
2620 newRegionHandle 2620 Vector3 pos = Vector3.Zero;
2621 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), 2621 if (destination != null)
2622 (uint)(thisy * Constants.RegionSize));
2623 // x - 1
2624 }
2625 }
2626 else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
2627 { 2622 {
2628 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) 2623 // Adjust the object's relative position from the old region (attemptedPosition)
2629 { 2624 // to be relative to the new region (pos).
2630 2625 pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
2631 pos.X = ((pos.X - Constants.RegionSize)); 2626 (float)(objectWorldLocY - (double)destination.RegionLocY),
2632 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); 2627 attemptedPosition.Z);
2633 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2634
2635 if (crossedBordery.BorderLine.Z > 0)
2636 {
2637 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2638 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2639 }
2640 else
2641 pos.Y = ((pos.Y + Constants.RegionSize));
2642
2643
2644 newRegionHandle
2645 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2646 (uint)((thisy - changeY) * Constants.RegionSize));
2647 // x + 1
2648 // y - 1
2649 }
2650 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2651 {
2652 pos.X = ((pos.X - Constants.RegionSize));
2653 pos.Y = ((pos.Y - Constants.RegionSize));
2654 newRegionHandle
2655 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2656 (uint)((thisy + changeY) * Constants.RegionSize));
2657 // x + 1
2658 // y + 1
2659 }
2660 else
2661 {
2662 pos.X = ((pos.X - Constants.RegionSize));
2663 newRegionHandle
2664 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2665 (uint)(thisy * Constants.RegionSize));
2666 // x + 1
2667 }
2668 } 2628 }
2669 else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
2670 {
2671 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2672 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2673 2629
2674 if (crossedBordery.BorderLine.Z > 0) 2630 if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2675 {
2676 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2677 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2678 }
2679 else
2680 pos.Y = ((pos.Y + Constants.RegionSize));
2681
2682 newRegionHandle
2683 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
2684 // y - 1
2685 }
2686 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2687 { 2631 {
2632 m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
2688 2633
2689 pos.Y = ((pos.Y - Constants.RegionSize)); 2634 // We are going to move the object back to the old position so long as the old position
2690 newRegionHandle 2635 // is in the region
2691 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); 2636 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
2692 // y + 1 2637 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
2693 } 2638 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
2694 2639
2695 // Offset the positions for the new region across the border 2640 grp.AbsolutePosition = oldGroupPosition;
2696 Vector3 oldGroupPosition = grp.RootPart.GroupPosition; 2641 grp.Velocity = Vector3.Zero;
2642 if (grp.RootPart.PhysActor != null)
2643 grp.RootPart.PhysActor.CrossingFailure();
2697 2644
2698 // If we fail to cross the border, then reset the position of the scene object on that border. 2645 if (grp.RootPart.KeyframeMotion != null)
2699 uint x = 0, y = 0; 2646 grp.RootPart.KeyframeMotion.CrossingFailure();
2700 Utils.LongToUInts(newRegionHandle, out x, out y);
2701 GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
2702 2647
2703 if (destination != null) 2648 grp.ScheduleGroupForFullUpdate();
2704 {
2705 if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2706 return; // we did it
2707 } 2649 }
2708
2709 // no one or failed lets go back and tell physics to go on
2710 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
2711 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
2712// oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f);
2713
2714 grp.AbsolutePosition = oldGroupPosition;
2715 grp.Velocity = Vector3.Zero;
2716
2717 if (grp.RootPart.PhysActor != null)
2718 grp.RootPart.PhysActor.CrossingFailure();
2719
2720 if (grp.RootPart.KeyframeMotion != null)
2721 grp.RootPart.KeyframeMotion.CrossingFailure();
2722
2723 grp.ScheduleGroupForFullUpdate();
2724 } 2650 }
2725 2651
2726
2727
2728 /// <summary> 2652 /// <summary>
2729 /// Move the given scene object into a new region 2653 /// Move the given scene object into a new region
2730 /// </summary> 2654 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
index e03ac5a..c6f531e 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
@@ -55,5 +55,10 @@ namespace OpenSim.Region.Framework.Interfaces
55 /// Currently, will throw an exception if this does not match a root region. 55 /// Currently, will throw an exception if this does not match a root region.
56 /// </param> 56 /// </param>
57 Vector2 GetSizeOfMegaregion(UUID regionId); 57 Vector2 GetSizeOfMegaregion(UUID regionId);
58
59 /// <summary>
60 /// Tests to see of position (relative to the region) is within the megaregion
61 /// </summary>
62 bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy);
58 } 63 }
59} \ No newline at end of file 64} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index eb34f55..03270d7 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -160,11 +160,6 @@ namespace OpenSim.Region.Framework.Scenes
160 /// </summary> 160 /// </summary>
161 public SimStatsReporter StatsReporter { get; private set; } 161 public SimStatsReporter StatsReporter { get; private set; }
162 162
163 public List<Border> NorthBorders = new List<Border>();
164 public List<Border> EastBorders = new List<Border>();
165 public List<Border> SouthBorders = new List<Border>();
166 public List<Border> WestBorders = new List<Border>();
167
168 /// <summary> 163 /// <summary>
169 /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a 164 /// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
170 /// PhysicsScene in order to perform collision detection 165 /// PhysicsScene in order to perform collision detection
@@ -364,7 +359,6 @@ namespace OpenSim.Region.Framework.Scenes
364 359
365 // TODO: Possibly stop other classes being able to manipulate this directly. 360 // TODO: Possibly stop other classes being able to manipulate this directly.
366 private SceneGraph m_sceneGraph; 361 private SceneGraph m_sceneGraph;
367 private volatile int m_bordersLocked;
368 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 362 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
369 private volatile bool m_backingup; 363 private volatile bool m_backingup;
370 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 364 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
@@ -446,18 +440,6 @@ namespace OpenSim.Region.Framework.Scenes
446 set { m_splitRegionID = value; } 440 set { m_splitRegionID = value; }
447 } 441 }
448 442
449 public bool BordersLocked
450 {
451 get { return m_bordersLocked == 1; }
452 set
453 {
454 if (value == true)
455 m_bordersLocked = 1;
456 else
457 m_bordersLocked = 0;
458 }
459 }
460
461 public new float TimeDilation 443 public new float TimeDilation
462 { 444 {
463 get { return m_sceneGraph.PhysicsScene.TimeDilation; } 445 get { return m_sceneGraph.PhysicsScene.TimeDilation; }
@@ -1075,28 +1057,6 @@ namespace OpenSim.Region.Framework.Scenes
1075 PeriodicBackup = true; 1057 PeriodicBackup = true;
1076 UseBackup = true; 1058 UseBackup = true;
1077 1059
1078 BordersLocked = true;
1079 Border northBorder = new Border();
1080 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeY); //<---
1081 northBorder.CrossDirection = Cardinals.N;
1082 NorthBorders.Add(northBorder);
1083
1084 Border southBorder = new Border();
1085 southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
1086 southBorder.CrossDirection = Cardinals.S;
1087 SouthBorders.Add(southBorder);
1088
1089 Border eastBorder = new Border();
1090 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeX); //<---
1091 eastBorder.CrossDirection = Cardinals.E;
1092 EastBorders.Add(eastBorder);
1093
1094 Border westBorder = new Border();
1095 westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
1096 westBorder.CrossDirection = Cardinals.W;
1097 WestBorders.Add(westBorder);
1098 BordersLocked = false;
1099
1100 m_eventManager = new EventManager(); 1060 m_eventManager = new EventManager();
1101 1061
1102 m_permissions = new ScenePermissions(this); 1062 m_permissions = new ScenePermissions(this);
@@ -2611,185 +2571,35 @@ namespace OpenSim.Region.Framework.Scenes
2611 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2571 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2612 } 2572 }
2613 2573
2614 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2574 // Simple test to see if a position is in the current region.
2575 // This test is mostly used to see if a region crossing is necessary.
2576 // Assuming the position is relative to the region so anything outside its bounds.
2577 // Return 'true' if position inside region.
2578 public bool PositionIsInCurrentRegion(Vector3 pos)
2615 { 2579 {
2616 if (BordersLocked) 2580 bool ret = false;
2617 { 2581 int xx = (int)Math.Floor(pos.X);
2618 switch (gridline) 2582 int yy = (int)Math.Floor(pos.Y);
2619 { 2583 if (xx < 0 || yy < 0)
2620 case Cardinals.N: 2584 return false;
2621 lock (NorthBorders)
2622 {
2623 foreach (Border b in NorthBorders)
2624 {
2625 if (b.TestCross(position))
2626 return b;
2627 }
2628 }
2629 break;
2630 case Cardinals.S:
2631 lock (SouthBorders)
2632 {
2633 foreach (Border b in SouthBorders)
2634 {
2635 if (b.TestCross(position))
2636 return b;
2637 }
2638 }
2639
2640 break;
2641 case Cardinals.E:
2642 lock (EastBorders)
2643 {
2644 foreach (Border b in EastBorders)
2645 {
2646 if (b.TestCross(position))
2647 return b;
2648 }
2649 }
2650
2651 break;
2652 case Cardinals.W:
2653
2654 lock (WestBorders)
2655 {
2656 foreach (Border b in WestBorders)
2657 {
2658 if (b.TestCross(position))
2659 return b;
2660 }
2661 }
2662 break;
2663 2585
2664 } 2586 IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>();
2587 if (regionCombinerModule == null)
2588 {
2589 // Regular region. Just check for region size
2590 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
2591 ret = true;
2665 } 2592 }
2666 else 2593 else
2667 { 2594 {
2668 switch (gridline) 2595 // We're in a mega-region so see if we are still in that larger region
2669 { 2596 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2670 case Cardinals.N:
2671 foreach (Border b in NorthBorders)
2672 {
2673 if (b.TestCross(position))
2674 return b;
2675 }
2676
2677 break;
2678 case Cardinals.S:
2679 foreach (Border b in SouthBorders)
2680 {
2681 if (b.TestCross(position))
2682 return b;
2683 }
2684 break;
2685 case Cardinals.E:
2686 foreach (Border b in EastBorders)
2687 {
2688 if (b.TestCross(position))
2689 return b;
2690 }
2691
2692 break;
2693 case Cardinals.W:
2694 foreach (Border b in WestBorders)
2695 {
2696 if (b.TestCross(position))
2697 return b;
2698 }
2699 break;
2700
2701 }
2702 } 2597 }
2703 2598
2704 return null; 2599 return ret;
2705 }
2706 2600
2707 public bool TestBorderCross(Vector3 position, Cardinals border)
2708 {
2709 if (BordersLocked)
2710 {
2711 switch (border)
2712 {
2713 case Cardinals.N:
2714 lock (NorthBorders)
2715 {
2716 foreach (Border b in NorthBorders)
2717 {
2718 if (b.TestCross(position))
2719 return true;
2720 }
2721 }
2722 break;
2723 case Cardinals.E:
2724 lock (EastBorders)
2725 {
2726 foreach (Border b in EastBorders)
2727 {
2728 if (b.TestCross(position))
2729 return true;
2730 }
2731 }
2732 break;
2733 case Cardinals.S:
2734 lock (SouthBorders)
2735 {
2736 foreach (Border b in SouthBorders)
2737 {
2738 if (b.TestCross(position))
2739 return true;
2740 }
2741 }
2742 break;
2743 case Cardinals.W:
2744 lock (WestBorders)
2745 {
2746 foreach (Border b in WestBorders)
2747 {
2748 if (b.TestCross(position))
2749 return true;
2750 }
2751 }
2752 break;
2753 }
2754 }
2755 else
2756 {
2757 switch (border)
2758 {
2759 case Cardinals.N:
2760 foreach (Border b in NorthBorders)
2761 {
2762 if (b.TestCross(position))
2763 return true;
2764 }
2765 break;
2766 case Cardinals.E:
2767 foreach (Border b in EastBorders)
2768 {
2769 if (b.TestCross(position))
2770 return true;
2771 }
2772 break;
2773 case Cardinals.S:
2774 foreach (Border b in SouthBorders)
2775 {
2776 if (b.TestCross(position))
2777 return true;
2778 }
2779 break;
2780 case Cardinals.W:
2781 foreach (Border b in WestBorders)
2782 {
2783 if (b.TestCross(position))
2784 return true;
2785 }
2786 break;
2787 }
2788 }
2789 return false;
2790 } 2601 }
2791 2602
2792
2793 /// <summary> 2603 /// <summary>
2794 /// Called when objects or attachments cross the border, or teleport, between regions. 2604 /// Called when objects or attachments cross the border, or teleport, between regions.
2795 /// </summary> 2605 /// </summary>
@@ -4116,60 +3926,11 @@ namespace OpenSim.Region.Framework.Scenes
4116 { 3926 {
4117// CleanDroppedAttachments(); 3927// CleanDroppedAttachments();
4118 3928
4119 if (TestBorderCross(acd.startpos, Cardinals.E)) 3929 // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
4120 { 3930 if (acd.startpos.X < 0) acd.startpos.X = 1f;
4121 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); 3931 if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
4122 acd.startpos.X = crossedBorder.BorderLine.Z - 1; 3932 if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
4123 } 3933 if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
4124
4125 if (TestBorderCross(acd.startpos, Cardinals.N))
4126 {
4127 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
4128 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
4129 }
4130
4131 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
4132 // Check if start position is outside of region
4133 // If it is, check the Z start position also.. if not, leave it alone.
4134 if (BordersLocked)
4135 {
4136 lock (EastBorders)
4137 {
4138 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4139 {
4140 m_log.Warn("FIX AGENT POSITION");
4141 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4142 if (acd.startpos.Z > 720)
4143 acd.startpos.Z = 720;
4144 }
4145 }
4146 lock (NorthBorders)
4147 {
4148 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4149 {
4150 m_log.Warn("FIX Agent POSITION");
4151 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4152 if (acd.startpos.Z > 720)
4153 acd.startpos.Z = 720;
4154 }
4155 }
4156 } else
4157 {
4158 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4159 {
4160 m_log.Warn("FIX AGENT POSITION");
4161 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4162 if (acd.startpos.Z > 720)
4163 acd.startpos.Z = 720;
4164 }
4165 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4166 {
4167 m_log.Warn("FIX Agent POSITION");
4168 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4169 if (acd.startpos.Z > 720)
4170 acd.startpos.Z = 720;
4171 }
4172 }
4173 3934
4174// m_log.DebugFormat( 3935// m_log.DebugFormat(
4175// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", 3936// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
@@ -4883,44 +4644,6 @@ namespace OpenSim.Region.Framework.Scenes
4883 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4644 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4884 if (sp != null) 4645 if (sp != null)
4885 { 4646 {
4886 uint regionX = RegionInfo.RegionLocX;
4887 uint regionY = RegionInfo.RegionLocY;
4888
4889 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4890
4891 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
4892 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
4893
4894 position.X += shiftx;
4895 position.Y += shifty;
4896
4897 bool result = false;
4898
4899 if (TestBorderCross(position,Cardinals.N))
4900 result = true;
4901
4902 if (TestBorderCross(position, Cardinals.S))
4903 result = true;
4904
4905 if (TestBorderCross(position, Cardinals.E))
4906 result = true;
4907
4908 if (TestBorderCross(position, Cardinals.W))
4909 result = true;
4910
4911 // bordercross if position is outside of region
4912
4913 if (!result)
4914 {
4915 regionHandle = RegionInfo.RegionHandle;
4916 }
4917 else
4918 {
4919 // not in this region, undo the shift!
4920 position.X -= shiftx;
4921 position.Y -= shifty;
4922 }
4923
4924 if (EntityTransferModule != null) 4647 if (EntityTransferModule != null)
4925 { 4648 {
4926 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); 4649 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 89c7a1a..a99e469 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -529,12 +529,10 @@ namespace OpenSim.Region.Framework.Scenes
529 set 529 set
530 { 530 {
531 Vector3 val = value; 531 Vector3 val = value;
532 if (Scene != null && !IsAttachmentCheckFull() 532 if (Scene != null
533 && !Scene.LoadingPrims && 533 && Scene.PositionIsInCurrentRegion(val)
534 (Scene.TestBorderCross(val, Cardinals.E) || 534 && !IsAttachmentCheckFull()
535 Scene.TestBorderCross(val, Cardinals.W) || 535 && !Scene.LoadingPrims
536 Scene.TestBorderCross(val, Cardinals.N) ||
537 Scene.TestBorderCross(val, Cardinals.S))
538 ) 536 )
539 { 537 {
540 if (!inTransit) 538 if (!inTransit)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 91293c4..8979659 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2979,10 +2979,7 @@ namespace OpenSim.Region.Framework.Scenes
2979 { 2979 {
2980 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2980 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2981 2981
2982 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2982 if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
2983 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2984 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2985 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2986 { 2983 {
2987 ParentGroup.AbsolutePosition = newpos; 2984 ParentGroup.AbsolutePosition = newpos;
2988 return; 2985 return;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cd9dcf5..2965903 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1170,18 +1170,6 @@ namespace OpenSim.Region.Framework.Scenes
1170 1170
1171 if (ParentID == 0) 1171 if (ParentID == 0)
1172 { 1172 {
1173 if (m_scene.TestBorderCross(pos, Cardinals.E))
1174 {
1175 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
1176 pos.X = crossedBorder.BorderLine.Z - 1;
1177 }
1178
1179 if (m_scene.TestBorderCross(pos, Cardinals.N))
1180 {
1181 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
1182 pos.Y = crossedBorder.BorderLine.Z - 1;
1183 }
1184
1185 CheckAndAdjustLandingPoint(ref pos); 1173 CheckAndAdjustLandingPoint(ref pos);
1186 1174
1187 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1175 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -3867,32 +3855,28 @@ namespace OpenSim.Region.Framework.Scenes
3867// m_log.DebugFormat( 3855// m_log.DebugFormat(
3868// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", 3856// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3869// pos2, Name, Scene.Name); 3857// pos2, Name, Scene.Name);
3870 3858
3871 if( Scene.TestBorderCross(pos2, Cardinals.E) || 3859 if (Scene.PositionIsInCurrentRegion(pos2))
3872 Scene.TestBorderCross(pos2, Cardinals.W) || 3860 return;
3873 Scene.TestBorderCross(pos2, Cardinals.N) || 3861
3874 Scene.TestBorderCross(pos2, Cardinals.S) 3862 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3875 ) 3863 {
3876 { 3864 // we don't have entity transfer module
3877 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero) 3865 Vector3 pos = AbsolutePosition;
3878 { 3866 float px = pos.X;
3879 // we don't have entity transfer module 3867 if (px < 0)
3880 Vector3 pos = AbsolutePosition; 3868 pos.X += Velocity.X * 2;
3881 float px = pos.X; 3869 else if (px > m_scene.RegionInfo.RegionSizeX)
3882 if (px < 0) 3870 pos.X -= Velocity.X * 2;
3883 pos.X += Velocity.X * 2; 3871
3884 else if (px > m_scene.RegionInfo.RegionSizeX) 3872 float py = pos.Y;
3885 pos.X -= Velocity.X * 2; 3873 if (py < 0)
3886 3874 pos.Y += Velocity.Y * 2;
3887 float py = pos.Y; 3875 else if (py > m_scene.RegionInfo.RegionSizeY)
3888 if (py < 0) 3876 pos.Y -= Velocity.Y * 2;
3889 pos.Y += Velocity.Y * 2; 3877
3890 else if (py > m_scene.RegionInfo.RegionSizeY) 3878 Velocity = Vector3.Zero;
3891 pos.Y -= Velocity.Y * 2; 3879 AbsolutePosition = pos;
3892
3893 Velocity = Vector3.Zero;
3894 AbsolutePosition = pos;
3895 }
3896 } 3880 }
3897 } 3881 }
3898 3882
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 29b39e0..6cbccc0 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
116 + "If teleport is true then some extra teleport debug information is logged.\n" 116 + "If teleport is true then some extra teleport debug information is logged.\n"
117 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.", 117 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
118 HandleDebugSceneSetCommand); 118 HandleDebugSceneSetCommand);
119
120 scene.AddCommand(
121 "Regions",
122 this, "show borders", "show borders", "Show border information for regions", HandleShowBordersCommand);
123 }
124
125 private void HandleShowBordersCommand(string module, string[] args)
126 {
127 StringBuilder sb = new StringBuilder();
128 sb.AppendFormat("Borders for {0}:\n", m_scene.Name);
129
130 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
131 cdt.AddColumn("Cross Direction", 15);
132 cdt.AddColumn("Line", 34);
133 cdt.AddColumn("Trigger Region", 14);
134
135 foreach (Border b in m_scene.NorthBorders)
136 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
137
138 foreach (Border b in m_scene.EastBorders)
139 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
140
141 foreach (Border b in m_scene.SouthBorders)
142 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
143
144 foreach (Border b in m_scene.WestBorders)
145 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
146
147 cdt.AddToStringBuilder(sb);
148
149 MainConsole.Instance.Output(sb.ToString());
150 } 119 }
151 120
152 private void HandleDebugSceneGetCommand(string module, string[] args) 121 private void HandleDebugSceneGetCommand(string module, string[] args)
@@ -263,4 +232,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
263 } 232 }
264 } 233 }
265 } 234 }
266} \ No newline at end of file 235}
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 7127c73..341c8f8 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -134,6 +134,49 @@ namespace OpenSim.Region.RegionCombinerModule
134 throw new Exception(string.Format("Region with id {0} not found", regionId)); 134 throw new Exception(string.Format("Region with id {0} not found", regionId));
135 } 135 }
136 136
137 // Test to see if this postiion (relative to the region) is within the area covered
138 // by this megaregion.
139 public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
140 {
141 bool ret = false;
142 if (xx < 0 || yy < 0)
143 return ret;
144
145 foreach (RegionConnections rootRegion in m_regions.Values)
146 {
147 if (currentRegion == rootRegion.RegionId)
148 {
149 // The caller is in the root region so this is an easy test
150 if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
151 {
152 ret = true;
153 }
154 break;
155 }
156 else
157 {
158 // Maybe the caller is in one of the sub-regions
159 foreach (RegionData childRegion in rootRegion.ConnectedRegions)
160 {
161 if (currentRegion == childRegion.RegionId)
162 {
163 // This is a child. Diddle the offsets and check if in
164 Vector3 positionInMegaregion = childRegion.Offset;
165 positionInMegaregion.X += xx;
166 positionInMegaregion.Y += yy;
167 if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
168 {
169 ret = true;
170 }
171 break;
172 }
173 }
174 }
175 }
176
177 return ret;
178 }
179
137 private void NewPresence(ScenePresence presence) 180 private void NewPresence(ScenePresence presence)
138 { 181 {
139 if (presence.IsChildAgent) 182 if (presence.IsChildAgent)
@@ -220,27 +263,6 @@ namespace OpenSim.Region.RegionCombinerModule
220 // 263 //
221*/ 264*/
222 265
223 // Give each region a standard set of non-infinite borders
224 Border northBorder = new Border();
225 northBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
226 northBorder.CrossDirection = Cardinals.N;
227 scene.NorthBorders[0] = northBorder;
228
229 Border southBorder = new Border();
230 southBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
231 southBorder.CrossDirection = Cardinals.S;
232 scene.SouthBorders[0] = southBorder;
233
234 Border eastBorder = new Border();
235 eastBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
236 eastBorder.CrossDirection = Cardinals.E;
237 scene.EastBorders[0] = eastBorder;
238
239 Border westBorder = new Border();
240 westBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
241 westBorder.CrossDirection = Cardinals.W;
242 scene.WestBorders[0] = westBorder;
243
244 RegionConnections newConn = new RegionConnections(); 266 RegionConnections newConn = new RegionConnections();
245 newConn.ConnectedRegions = new List<RegionData>(); 267 newConn.ConnectedRegions = new List<RegionData>();
246 newConn.RegionScene = scene; 268 newConn.RegionScene = scene;
@@ -248,8 +270,8 @@ namespace OpenSim.Region.RegionCombinerModule
248 newConn.RegionId = scene.RegionInfo.originRegionID; 270 newConn.RegionId = scene.RegionInfo.originRegionID;
249 newConn.X = scene.RegionInfo.RegionLocX; 271 newConn.X = scene.RegionInfo.RegionLocX;
250 newConn.Y = scene.RegionInfo.RegionLocY; 272 newConn.Y = scene.RegionInfo.RegionLocY;
251 newConn.XEnd = (int)Constants.RegionSize; 273 newConn.XEnd = scene.RegionInfo.RegionSizeX;
252 newConn.YEnd = (int)Constants.RegionSize; 274 newConn.YEnd = scene.RegionInfo.RegionSizeX;
253 275
254 lock (m_regions) 276 lock (m_regions)
255 { 277 {
@@ -415,6 +437,11 @@ namespace OpenSim.Region.RegionCombinerModule
415 */ 437 */
416 #endregion 438 #endregion
417 439
440
441 // Check to see if this new region is adjacent to the root region.
442 // Note that we expect the regions to be combined from the root region outward
443 // thus the requirement for the ordering in the configuration files.
444
418 // If we're one region over +x y (i.e. root region is to the west) 445 // If we're one region over +x y (i.e. root region is to the west)
419 //xxx 446 //xxx
420 //xxy 447 //xxy
@@ -431,7 +458,7 @@ namespace OpenSim.Region.RegionCombinerModule
431 //xxx 458 //xxx
432 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY) 459 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
433 { 460 {
434 connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene); 461 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
435 break; 462 break;
436 } 463 }
437 464
@@ -441,9 +468,8 @@ namespace OpenSim.Region.RegionCombinerModule
441 //xxx 468 //xxx
442 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY) 469 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
443 { 470 {
444 connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene); 471 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
445 break; 472 break;
446
447 } 473 }
448 } 474 }
449 475
@@ -453,20 +479,20 @@ namespace OpenSim.Region.RegionCombinerModule
453 DoWorkForRootRegion(newConn, scene); 479 DoWorkForRootRegion(newConn, scene);
454 } 480 }
455 } 481 }
456
457 // Set up infinite borders around the entire AABB of the combined ConnectedRegions
458 AdjustLargeRegionBounds();
459 } 482 }
460 483
461 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene) 484 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
462 { 485 {
486 // Offset (in meters) from the base of this region to the base of the root region.
463 Vector3 offset = Vector3.Zero; 487 Vector3 offset = Vector3.Zero;
464 offset.X = newConn.PosX - rootConn.PosX; 488 offset.X = newConn.PosX - rootConn.PosX;
465 offset.Y = newConn.PosY - rootConn.PosY; 489 offset.Y = newConn.PosY - rootConn.PosY;
466 490
491 // The new total size of the region (in meters)
492 // We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
467 Vector3 extents = Vector3.Zero; 493 Vector3 extents = Vector3.Zero;
468 extents.Y = rootConn.YEnd; 494 extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
469 extents.X = rootConn.XEnd + newConn.XEnd; 495 extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
470 496
471 rootConn.UpdateExtents(extents); 497 rootConn.UpdateExtents(extents);
472 498
@@ -475,9 +501,6 @@ namespace OpenSim.Region.RegionCombinerModule
475 rootConn.RegionScene.RegionInfo.RegionName, 501 rootConn.RegionScene.RegionInfo.RegionName,
476 newConn.RegionScene.RegionInfo.RegionName, offset, extents); 502 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
477 503
478 scene.BordersLocked = true;
479 rootConn.RegionScene.BordersLocked = true;
480
481 RegionData ConnectedRegion = new RegionData(); 504 RegionData ConnectedRegion = new RegionData();
482 ConnectedRegion.Offset = offset; 505 ConnectedRegion.Offset = offset;
483 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 506 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -490,34 +513,10 @@ namespace OpenSim.Region.RegionCombinerModule
490 // Inform Child region that it needs to forward it's terrain to the root region 513 // Inform Child region that it needs to forward it's terrain to the root region
491 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 514 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
492 515
493 // Extend the borders as appropriate
494 lock (rootConn.RegionScene.EastBorders)
495 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
496
497 lock (rootConn.RegionScene.NorthBorders)
498 rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
499
500 lock (rootConn.RegionScene.SouthBorders)
501 rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
502
503 lock (scene.WestBorders)
504 {
505 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
506
507 // Trigger auto teleport to root region
508 scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
509 scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
510 }
511
512 // Reset Terrain.. since terrain loads before we get here, we need to load 516 // Reset Terrain.. since terrain loads before we get here, we need to load
513 // it again so it loads in the root region 517 // it again so it loads in the root region
514
515 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 518 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
516 519
517 // Unlock borders
518 rootConn.RegionScene.BordersLocked = false;
519 scene.BordersLocked = false;
520
521 // Create a client event forwarder and add this region's events to the root region. 520 // Create a client event forwarder and add this region's events to the root region.
522 if (rootConn.ClientEventForwarder != null) 521 if (rootConn.ClientEventForwarder != null)
523 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); 522 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -525,6 +524,9 @@ namespace OpenSim.Region.RegionCombinerModule
525 return true; 524 return true;
526 } 525 }
527 526
527 /*
528 * 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
529 * was generalized. These functions are not needed for the generalized solution but left for reference.
528 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene) 530 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
529 { 531 {
530 Vector3 offset = Vector3.Zero; 532 Vector3 offset = Vector3.Zero;
@@ -536,9 +538,6 @@ namespace OpenSim.Region.RegionCombinerModule
536 extents.X = rootConn.XEnd; 538 extents.X = rootConn.XEnd;
537 rootConn.UpdateExtents(extents); 539 rootConn.UpdateExtents(extents);
538 540
539 scene.BordersLocked = true;
540 rootConn.RegionScene.BordersLocked = true;
541
542 RegionData ConnectedRegion = new RegionData(); 541 RegionData ConnectedRegion = new RegionData();
543 ConnectedRegion.Offset = offset; 542 ConnectedRegion.Offset = offset;
544 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 543 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -553,30 +552,11 @@ namespace OpenSim.Region.RegionCombinerModule
553 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 552 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
554 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 553 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
555 554
556 lock (rootConn.RegionScene.NorthBorders)
557 rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
558
559 lock (rootConn.RegionScene.EastBorders)
560 rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
561
562 lock (rootConn.RegionScene.WestBorders)
563 rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
564
565 lock (scene.SouthBorders)
566 {
567 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
568 scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
569 scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
570 }
571
572 // Reset Terrain.. since terrain normally loads first. 555 // Reset Terrain.. since terrain normally loads first.
573 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 556 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
574 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 557 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
575 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 558 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
576 559
577 scene.BordersLocked = false;
578 rootConn.RegionScene.BordersLocked = false;
579
580 if (rootConn.ClientEventForwarder != null) 560 if (rootConn.ClientEventForwarder != null)
581 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); 561 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
582 562
@@ -600,9 +580,6 @@ namespace OpenSim.Region.RegionCombinerModule
600 extents.Y = rootConn.YEnd; 580 extents.Y = rootConn.YEnd;
601 extents.X = rootConn.XEnd; 581 extents.X = rootConn.XEnd;
602 582
603 scene.BordersLocked = true;
604 rootConn.RegionScene.BordersLocked = true;
605
606 RegionData ConnectedRegion = new RegionData(); 583 RegionData ConnectedRegion = new RegionData();
607 ConnectedRegion.Offset = offset; 584 ConnectedRegion.Offset = offset;
608 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID; 585 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -618,67 +595,10 @@ namespace OpenSim.Region.RegionCombinerModule
618 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents); 595 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
619 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero); 596 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
620 597
621 lock (rootConn.RegionScene.NorthBorders)
622 {
623 if (rootConn.RegionScene.NorthBorders.Count == 1)// && 2)
624 {
625 //compound border
626 // already locked above
627 rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
628
629 lock (rootConn.RegionScene.EastBorders)
630 rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
631
632 lock (rootConn.RegionScene.WestBorders)
633 rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
634 }
635 }
636
637 lock (scene.SouthBorders)
638 {
639 scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
640 scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
641 scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
642 }
643
644 lock (rootConn.RegionScene.EastBorders)
645 {
646 if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
647 {
648 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
649
650 lock (rootConn.RegionScene.NorthBorders)
651 rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
652
653 lock (rootConn.RegionScene.SouthBorders)
654 rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
655 }
656 }
657
658 lock (scene.WestBorders)
659 {
660 scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
661 scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
662 scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
663 }
664
665 /*
666 else
667 {
668 conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
669 conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
670 conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
671 scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
672 }
673 */
674
675
676 // Reset Terrain.. since terrain normally loads first. 598 // Reset Terrain.. since terrain normally loads first.
677 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 599 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
678 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 600 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
679 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised()); 601 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
680 scene.BordersLocked = false;
681 rootConn.RegionScene.BordersLocked = false;
682 602
683 if (rootConn.ClientEventForwarder != null) 603 if (rootConn.ClientEventForwarder != null)
684 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene); 604 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -687,6 +607,7 @@ namespace OpenSim.Region.RegionCombinerModule
687 607
688 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents); 608 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
689 } 609 }
610 */
690 611
691 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene) 612 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
692 { 613 {
@@ -885,125 +806,6 @@ namespace OpenSim.Region.RegionCombinerModule
885// } 806// }
886// } 807// }
887 808
888 // Create a set of infinite borders around the whole aabb of the combined island.
889 private void AdjustLargeRegionBounds()
890 {
891 lock (m_regions)
892 {
893 foreach (RegionConnections rconn in m_regions.Values)
894 {
895 Vector3 offset = Vector3.Zero;
896 rconn.RegionScene.BordersLocked = true;
897 foreach (RegionData rdata in rconn.ConnectedRegions)
898 {
899 if (rdata.Offset.X > offset.X) offset.X = rdata.Offset.X;
900 if (rdata.Offset.Y > offset.Y) offset.Y = rdata.Offset.Y;
901 }
902
903 lock (rconn.RegionScene.NorthBorders)
904 {
905 Border northBorder = null;
906 // If we don't already have an infinite border, create one.
907 if (!TryGetInfiniteBorder(rconn.RegionScene.NorthBorders, out northBorder))
908 {
909 northBorder = new Border();
910 rconn.RegionScene.NorthBorders.Add(northBorder);
911 }
912
913 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,
914 offset.Y + (int) Constants.RegionSize); //<---
915 northBorder.CrossDirection = Cardinals.N;
916 }
917
918 lock (rconn.RegionScene.SouthBorders)
919 {
920 Border southBorder = null;
921 // If we don't already have an infinite border, create one.
922 if (!TryGetInfiniteBorder(rconn.RegionScene.SouthBorders, out southBorder))
923 {
924 southBorder = new Border();
925 rconn.RegionScene.SouthBorders.Add(southBorder);
926 }
927 southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
928 southBorder.CrossDirection = Cardinals.S;
929 }
930
931 lock (rconn.RegionScene.EastBorders)
932 {
933 Border eastBorder = null;
934 // If we don't already have an infinite border, create one.
935 if (!TryGetInfiniteBorder(rconn.RegionScene.EastBorders, out eastBorder))
936 {
937 eastBorder = new Border();
938 rconn.RegionScene.EastBorders.Add(eastBorder);
939 }
940 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, offset.X + (int)Constants.RegionSize);
941 //<---
942 eastBorder.CrossDirection = Cardinals.E;
943 }
944
945 lock (rconn.RegionScene.WestBorders)
946 {
947 Border westBorder = null;
948 // If we don't already have an infinite border, create one.
949 if (!TryGetInfiniteBorder(rconn.RegionScene.WestBorders, out westBorder))
950 {
951 westBorder = new Border();
952 rconn.RegionScene.WestBorders.Add(westBorder);
953
954 }
955 westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
956 westBorder.CrossDirection = Cardinals.W;
957 }
958
959 rconn.RegionScene.BordersLocked = false;
960 }
961 }
962 }
963
964 /// <summary>
965 /// Try and get an Infinite border out of a listT of borders
966 /// </summary>
967 /// <param name="borders"></param>
968 /// <param name="oborder"></param>
969 /// <returns></returns>
970 public static bool TryGetInfiniteBorder(List<Border> borders, out Border oborder)
971 {
972 // Warning! Should be locked before getting here!
973 foreach (Border b in borders)
974 {
975 if (b.BorderLine.X == float.MinValue && b.BorderLine.Y == float.MaxValue)
976 {
977 oborder = b;
978 return true;
979 }
980 }
981
982 oborder = null;
983 return false;
984 }
985
986 public RegionData GetRegionFromPosition(Vector3 pPosition)
987 {
988 pPosition = pPosition/(int) Constants.RegionSize;
989 int OffsetX = (int) pPosition.X;
990 int OffsetY = (int) pPosition.Y;
991
992 lock (m_regions)
993 {
994 foreach (RegionConnections regConn in m_regions.Values)
995 {
996 foreach (RegionData reg in regConn.ConnectedRegions)
997 {
998 if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY)
999 return reg;
1000 }
1001 }
1002 }
1003
1004 return new RegionData();
1005 }
1006
1007 public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion) 809 public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
1008 { 810 {
1009 if (BigRegion.PermissionModule == null) 811 if (BigRegion.PermissionModule == null)