aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework/EntityTransfer
diff options
context:
space:
mode:
authorRobert Adams2015-03-22 21:53:02 -0700
committerRobert Adams2015-03-22 21:53:02 -0700
commit9f18e3ba80a6469b7ff03c7cca595a0a3b999592 (patch)
treec2ace74c3ffc6eab80b94bfbe4e6a2d37197eb28 /OpenSim/Region/CoreModules/Framework/EntityTransfer
parentAllow setting the size of the wearables array from config, for core compatibi... (diff)
downloadopensim-SC_OLD-9f18e3ba80a6469b7ff03c7cca595a0a3b999592.zip
opensim-SC_OLD-9f18e3ba80a6469b7ff03c7cca595a0a3b999592.tar.gz
opensim-SC_OLD-9f18e3ba80a6469b7ff03c7cca595a0a3b999592.tar.bz2
opensim-SC_OLD-9f18e3ba80a6469b7ff03c7cca595a0a3b999592.tar.xz
Varregion: first cut at removing Border class checks for region crossings.
Added Scene.PositionIsInCurrentRegion(pos) to sense when new position needs some crossing work. Many changes made to EntityTransferModule to accomodate new crossing sense logic.
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/EntityTransfer')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs840
1 files changed, 382 insertions, 458 deletions
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>