aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs673
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs5
3 files changed, 341 insertions, 341 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 6545a99..13cc99a 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -269,9 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework
269 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID]) 269 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
270 { 270 {
271 uint x, y; 271 uint x, y;
272 Utils.LongToUInts(kvp.Key, out x, out y); 272 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
273 x = x / Constants.RegionSize;
274 y = y / Constants.RegionSize;
275 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 273 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
276 } 274 }
277 } 275 }
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 5fea0cf..85e8159 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")]
52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule 52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]"; 55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
56 56
57 public const int DefaultMaxTransferDistance = 4095; 57 public const int DefaultMaxTransferDistance = 4095;
@@ -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))
@@ -434,10 +480,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
434 float posZLimit = 22; 480 float posZLimit = 22;
435 481
436 // TODO: Check other Scene HeightField 482 // TODO: Check other Scene HeightField
437 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) 483 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
438 {
439 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
440 }
441 484
442 float newPosZ = posZLimit + localAVHeight; 485 float newPosZ = posZLimit + localAVHeight;
443 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 486 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
@@ -481,7 +524,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
481 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination) 524 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
482 { 525 {
483 uint x = 0, y = 0; 526 uint x = 0, y = 0;
484 Utils.LongToUInts(regionHandle, out x, out y); 527 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
485 GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); 528 GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
486 529
487 if (reg != null) 530 if (reg != null)
@@ -490,9 +533,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
490 533
491 if (finalDestination == null) 534 if (finalDestination == null)
492 { 535 {
493 m_log.WarnFormat( 536 m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}",
494 "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}", 537 LogHeader, sp.Name, sp.UUID);
495 sp.Name, sp.UUID);
496 538
497 sp.ControllingClient.SendTeleportFailed("Problem at destination"); 539 sp.ControllingClient.SendTeleportFailed("Problem at destination");
498 return; 540 return;
@@ -533,11 +575,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
533 575
534 // and set the map-tile to '(Offline)' 576 // and set the map-tile to '(Offline)'
535 uint regX, regY; 577 uint regX, regY;
536 Utils.LongToUInts(regionHandle, out regX, out regY); 578 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
537 579
538 MapBlockData block = new MapBlockData(); 580 MapBlockData block = new MapBlockData();
539 block.X = (ushort)(regX / Constants.RegionSize); 581 block.X = (ushort)regX;
540 block.Y = (ushort)(regY / Constants.RegionSize); 582 block.Y = (ushort)regY;
541 block.Access = 254; // == not there 583 block.Access = 254; // == not there
542 584
543 List<MapBlockData> blocks = new List<MapBlockData>(); 585 List<MapBlockData> blocks = new List<MapBlockData>();
@@ -1349,6 +1391,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1349 if (uinfo.HomeRegionID == UUID.Zero) 1391 if (uinfo.HomeRegionID == UUID.Zero)
1350 { 1392 {
1351 // can't find the Home region: Tell viewer and abort 1393 // can't find the Home region: Tell viewer and abort
1394 m_log.ErrorFormat("{0} No grid user info found for {1} {2}. Cannot send home.",
1395 LogHeader, client.Name, client.AgentId);
1352 client.SendTeleportFailed("You don't have a home position set."); 1396 client.SendTeleportFailed("You don't have a home position set.");
1353 return false; 1397 return false;
1354 } 1398 }
@@ -1382,7 +1426,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1382 1426
1383 #region Agent Crossings 1427 #region Agent Crossings
1384 1428
1385 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) 1429 // Given a position relative to the current region (which has previously been tested to
1430 // see that it is actually outside the current region), find the new region that the
1431 // point is actually in.
1432 // Returns the coordinates and information of the new region or 'null' of it doesn't exist.
1433 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
1386 { 1434 {
1387 version = String.Empty; 1435 version = String.Empty;
1388 newpos = pos; 1436 newpos = pos;
@@ -1390,131 +1438,54 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1390// m_log.DebugFormat( 1438// m_log.DebugFormat(
1391// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1439// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1392 1440
1393 uint neighbourx = scene.RegionInfo.RegionLocX; 1441 // Compute world location of the object's position
1394 uint neighboury = scene.RegionInfo.RegionLocY; 1442 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1395 const float boundaryDistance = 1.7f; 1443 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1396 Vector3 northCross = new Vector3(0, boundaryDistance, 0);
1397 Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
1398 Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
1399 Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
1400 1444
1401 // distance into new region to place avatar 1445 // Call the grid service to lookup the region containing the new position.
1402 const float enterDistance = 0.5f; 1446 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
1447 presenceWorldX, presenceWorldY,
1448 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1403 1449
1404 if (scene.TestBorderCross(pos + westCross, Cardinals.W)) 1450 if (neighbourRegion != null)
1405 { 1451 {
1406 if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1452 // Compute the entity's position relative to the new region
1407 { 1453 newpos = new Vector3( (float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1408 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); 1454 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1409 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); 1455 pos.Z);
1410 }
1411 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1412 {
1413 neighboury--;
1414 newpos.Y = Constants.RegionSize - enterDistance;
1415 }
1416
1417 neighbourx--;
1418 newpos.X = Constants.RegionSize - enterDistance;
1419 }
1420 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
1421 {
1422 Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
1423 neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
1424 newpos.X = enterDistance;
1425 1456
1426 if (scene.TestBorderCross(pos + southCross, Cardinals.S)) 1457 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1427 { 1458 {
1428 neighboury--; 1459 neighbourRegion = null;
1429 newpos.Y = Constants.RegionSize - enterDistance;
1430 } 1460 }
1431 else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1461 else
1432 { 1462 {
1433 Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N); 1463 // If not banned, make sure this agent is not in the list.
1434 neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize); 1464 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1435 newpos.Y = enterDistance;
1436 } 1465 }
1437 }
1438 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1439 {
1440 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
1441 neighboury--;
1442 newpos.Y = Constants.RegionSize - enterDistance;
1443 }
1444 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
1445 {
1446 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
1447 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
1448 newpos.Y = enterDistance;
1449 }
1450
1451 /*
1452
1453 if (pos.X < boundaryDistance) //West
1454 {
1455 neighbourx--;
1456 newpos.X = Constants.RegionSize - enterDistance;
1457 }
1458 else if (pos.X > Constants.RegionSize - boundaryDistance) // East
1459 {
1460 neighbourx++;
1461 newpos.X = enterDistance;
1462 }
1463
1464 if (pos.Y < boundaryDistance) // South
1465 {
1466 neighboury--;
1467 newpos.Y = Constants.RegionSize - enterDistance;
1468 }
1469 else if (pos.Y > Constants.RegionSize - boundaryDistance) // North
1470 {
1471 neighboury++;
1472 newpos.Y = enterDistance;
1473 }
1474 */
1475
1476 xDest = neighbourx;
1477 yDest = neighboury;
1478
1479 int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
1480 1466
1481 ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y); 1467 // Check to see if we have access to the target region.
1482 1468 string reason;
1483 ExpiringCache<ulong, DateTime> r; 1469 if (neighbourRegion != null
1484 DateTime banUntil; 1470 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
1485
1486 if (m_bannedRegions.TryGetValue(agentID, out r))
1487 {
1488 if (r.TryGetValue(neighbourHandle, out banUntil))
1489 { 1471 {
1490 if (DateTime.Now < banUntil) 1472 // remember banned
1491 return null; 1473 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1492 r.Remove(neighbourHandle); 1474 neighbourRegion = null;
1493 } 1475 }
1494 } 1476 }
1495 else
1496 {
1497 r = null;
1498 }
1499
1500 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
1501 1477
1502 string reason; 1478 if (neighbourRegion == null)
1503 if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) 1479 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1504 { 1480 LogHeader, scene.RegionInfo.RegionName,
1505 if (r == null) 1481 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1506 { 1482 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1507 r = new ExpiringCache<ulong, DateTime>(); 1483 pos);
1508 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 1484 else
1509 1485 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
1510 m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45)); 1486 LogHeader, neighbourRegion.RegionName,
1511 } 1487 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1512 else 1488 newpos.X, newpos.Y);
1513 {
1514 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
1515 }
1516 return null;
1517 }
1518 1489
1519 return neighbourRegion; 1490 return neighbourRegion;
1520 } 1491 }
@@ -1526,7 +1497,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1526 Vector3 newpos; 1497 Vector3 newpos;
1527 string version; 1498 string version;
1528 1499
1529 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos); 1500 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out version, out newpos);
1530 if (neighbourRegion == null) 1501 if (neighbourRegion == null)
1531 { 1502 {
1532 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); 1503 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
@@ -1568,7 +1539,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1568 1539
1569 agent.Scene.RequestTeleportLocation( 1540 agent.Scene.RequestTeleportLocation(
1570 agent.ControllingClient, 1541 agent.ControllingClient,
1571 Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize), 1542 Util.RegionLocToHandle(regionX, regionY),
1572 position, 1543 position,
1573 agent.Lookat, 1544 agent.Lookat,
1574 (uint)Constants.TeleportFlags.ViaLocation); 1545 (uint)Constants.TeleportFlags.ViaLocation);
@@ -1578,11 +1549,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1578 if (im != null) 1549 if (im != null)
1579 { 1550 {
1580 UUID gotoLocation = Util.BuildFakeParcelID( 1551 UUID gotoLocation = Util.BuildFakeParcelID(
1581 Util.UIntsToLong( 1552 Util.RegionLocToHandle(regionX, regionY),
1582 (regionX *
1583 (uint)Constants.RegionSize),
1584 (regionY *
1585 (uint)Constants.RegionSize)),
1586 (uint)(int)position.X, 1553 (uint)(int)position.X,
1587 (uint)(int)position.Y, 1554 (uint)(int)position.Y,
1588 (uint)(int)position.Z); 1555 (uint)(int)position.Z);
@@ -1635,17 +1602,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1635 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1602 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1636 /// </summary> 1603 /// </summary>
1637 public ScenePresence CrossAgentToNewRegionAsync( 1604 public ScenePresence CrossAgentToNewRegionAsync(
1638 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, 1605 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1639 bool isFlying, string version) 1606 bool isFlying, string version)
1640 { 1607 {
1608 m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}",
1609 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos);
1610
1641 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) 1611 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
1642 { 1612 {
1613 m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: prep failed. Resetting transfer state", LogHeader);
1643 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1614 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1644 return agent; 1615 return agent;
1645 } 1616 }
1646 1617
1647 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) 1618 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying))
1648 { 1619 {
1620 m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1649 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1621 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1650 return agent; 1622 return agent;
1651 } 1623 }
@@ -2038,15 +2010,195 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2038 } 2010 }
2039 } 2011 }
2040 2012
2013 // Computes the difference between two region bases.
2014 // Returns a vector of world coordinates (meters) from base of first region to the second.
2015 // The first region is the home region of the passed scene presence.
2041 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2016 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2042 { 2017 {
2043 int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX; 2018 /*
2044 int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY; 2019 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2020 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2045 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize; 2021 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2046 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize; 2022 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2047 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize; 2023 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2048 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize; 2024 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2049 return new Vector3(shiftx, shifty, 0f); 2025 return new Vector3(shiftx, shifty, 0f);
2026 */
2027 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2028 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2029 0f);
2030 }
2031
2032 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2033 {
2034 // Since we don't know how big the regions could be, we have to search a very large area
2035 // to find possible regions.
2036 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2037 }
2038
2039 #region NotFoundLocationCache class
2040 // A collection of not found locations to make future lookups 'not found' lookups quick.
2041 // A simple expiring cache that keeps not found locations for some number of seconds.
2042 // A 'not found' location is presumed to be anywhere in the minimum sized region that
2043 // contains that point. A conservitive estimate.
2044 private class NotFoundLocationCache
2045 {
2046 private struct NotFoundLocation
2047 {
2048 public double minX, maxX, minY, maxY;
2049 public DateTime expireTime;
2050 }
2051 private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
2052 public NotFoundLocationCache()
2053 {
2054 }
2055 // Add an area to the lost of 'not found' places. The area is the snapped region
2056 // area around the added point.
2057 public void Add(double pX, double pY)
2058 {
2059 lock (m_notFoundLocations)
2060 {
2061 if (!LockedContains(pX, pY))
2062 {
2063 NotFoundLocation nfl = new NotFoundLocation();
2064 // A not found location is not found for at least a whole region sized area
2065 nfl.minX = pX - (pX % (double)Constants.RegionSize);
2066 nfl.minY = pY - (pY % (double)Constants.RegionSize);
2067 nfl.maxX = nfl.minX + (double)Constants.RegionSize;
2068 nfl.maxY = nfl.minY + (double)Constants.RegionSize;
2069 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2070 m_notFoundLocations.Add(nfl);
2071 }
2072 }
2073
2074 }
2075 // Test to see of this point is in any of the 'not found' areas.
2076 // Return 'true' if the point is found inside the 'not found' areas.
2077 public bool Contains(double pX, double pY)
2078 {
2079 bool ret = false;
2080 lock (m_notFoundLocations)
2081 ret = LockedContains(pX, pY);
2082 return ret;
2083 }
2084 private bool LockedContains(double pX, double pY)
2085 {
2086 bool ret = false;
2087 this.DoExpiration();
2088 foreach (NotFoundLocation nfl in m_notFoundLocations)
2089 {
2090 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
2091 {
2092 ret = true;
2093 break;
2094 }
2095 }
2096 return ret;
2097 }
2098 private void DoExpiration()
2099 {
2100 List<NotFoundLocation> m_toRemove = null;
2101 DateTime now = DateTime.Now;
2102 foreach (NotFoundLocation nfl in m_notFoundLocations)
2103 {
2104 if (nfl.expireTime < now)
2105 {
2106 if (m_toRemove == null)
2107 m_toRemove = new List<NotFoundLocation>();
2108 m_toRemove.Add(nfl);
2109 }
2110 }
2111 if (m_toRemove != null)
2112 {
2113 foreach (NotFoundLocation nfl in m_toRemove)
2114 m_notFoundLocations.Remove(nfl);
2115 m_toRemove.Clear();
2116 }
2117 }
2118 }
2119 #endregion // NotFoundLocationCache class
2120 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2121
2122 // Given a world position (fractional meter coordinate), get the GridRegion info for
2123 // the region containing that point.
2124 // Someday this should be a method on GridService.
2125 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
2126 // the size of the target region is unknown thus the search area might have to be very large.
2127 // Return 'null' if no such region exists.
2128 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2129 double px, double py, uint pSizeHint)
2130 {
2131 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2132 GridRegion ret = null;
2133 const double fudge = 2.0;
2134
2135 // One problem with this routine is negative results. That is, this can be called lots of times
2136 // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
2137 // will be quick 'not found's next time.
2138 // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
2139 // thus re-ask the GridService about the location.
2140 if (m_notFoundLocationCache.Contains(px, py))
2141 {
2142 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2143 return null;
2144 }
2145
2146 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
2147 // the region at the appropriate legacy region location.
2148 uint possibleX = (uint)Math.Floor(px);
2149 possibleX -= possibleX % Constants.RegionSize;
2150 uint possibleY = (uint)Math.Floor(py);
2151 possibleY -= possibleY % Constants.RegionSize;
2152 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
2153 if (ret != null)
2154 {
2155 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2156 LogHeader, possibleX, possibleY, ret.RegionName);
2157 }
2158
2159 if (ret == null)
2160 {
2161 // If the simple lookup failed, search the larger area for a region that contains this point
2162 double range = (double)pSizeHint + fudge;
2163 while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
2164 {
2165 // Get from the grid service a list of regions that might contain this point.
2166 // The region origin will be in the zero direction so only subtract the range.
2167 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2168 (int)(px - range), (int)(px),
2169 (int)(py - range), (int)(py));
2170 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2171 LogHeader, possibleRegions.Count, range);
2172 if (possibleRegions != null && possibleRegions.Count > 0)
2173 {
2174 // If we found some regions, check to see if the point is within
2175 foreach (GridRegion gr in possibleRegions)
2176 {
2177 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2178 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2179 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2180 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
2181 {
2182 // Found a region that contains the point
2183 ret = gr;
2184 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2185 break;
2186 }
2187 }
2188 }
2189 // Larger search area for next time around if not found
2190 range *= 2;
2191 }
2192 }
2193
2194 if (ret == null)
2195 {
2196 // remember this location was not found so we can quickly not find it next time
2197 m_notFoundLocationCache.Add(px, py);
2198 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2199 }
2200
2201 return ret;
2050 } 2202 }
2051 2203
2052 private void InformClientOfNeighbourCompleted(IAsyncResult iar) 2204 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2168,16 +2320,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2168 // view to include everything in the megaregion 2320 // view to include everything in the megaregion
2169 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 2321 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2170 { 2322 {
2171 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; 2323 // The area to check is as big as the current region.
2324 // We presume all adjacent regions are the same size as this region.
2325 uint dd = Math.Max((uint)avatar.DrawDistance,
2326 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2172 2327
2173 int startX = (int)pRegionLocX * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2); 2328 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
2174 int startY = (int)pRegionLocY * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2); 2329 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2;
2175 2330
2176 int endX = (int)pRegionLocX * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2); 2331 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
2177 int endY = (int)pRegionLocY * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2); 2332 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
2178 2333
2179 List<GridRegion> neighbours = 2334 List<GridRegion> neighbours =
2180 avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY); 2335 avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2181 2336
2182 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 2337 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
2183 return neighbours; 2338 return neighbours;
@@ -2190,10 +2345,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2190 List<GridRegion> neighbours 2345 List<GridRegion> neighbours
2191 = pScene.GridService.GetRegionRange( 2346 = pScene.GridService.GetRegionRange(
2192 m_regionInfo.ScopeID, 2347 m_regionInfo.ScopeID,
2193 (int)swCorner.X * (int)Constants.RegionSize, 2348 (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
2194 (int)neCorner.X * (int)Constants.RegionSize, 2349 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y) );
2195 (int)swCorner.Y * (int)Constants.RegionSize,
2196 (int)neCorner.Y * (int)Constants.RegionSize);
2197 2350
2198 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 2351 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
2199 2352
@@ -2256,10 +2409,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2256 /// Move the given scene object into a new region depending on which region its absolute position has moved 2409 /// Move the given scene object into a new region depending on which region its absolute position has moved
2257 /// into. 2410 /// into.
2258 /// 2411 ///
2259 /// This method locates the new region handle and offsets the prim position for the new region 2412 /// Using the objects new world location, ask the grid service for a the new region and adjust the prim
2413 /// position to be relative to the new region.
2260 /// </summary> 2414 /// </summary>
2261 /// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
2262 /// <param name="grp">the scene object that we're crossing</param> 2415 /// <param name="grp">the scene object that we're crossing</param>
2416 /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is
2417 /// relative to the region the object currently is in.</param>
2418 /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param>
2263 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) 2419 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
2264 { 2420 {
2265 if (grp == null) 2421 if (grp == null)
@@ -2285,208 +2441,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2285 return; 2441 return;
2286 } 2442 }
2287 2443
2288 int thisx = (int)scene.RegionInfo.RegionLocX; 2444 // Remember the old group position in case the region lookup fails so position can be restored.
2289 int thisy = (int)scene.RegionInfo.RegionLocY; 2445 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2290 Vector3 EastCross = new Vector3(0.1f, 0, 0);
2291 Vector3 WestCross = new Vector3(-0.1f, 0, 0);
2292 Vector3 NorthCross = new Vector3(0, 0.1f, 0);
2293 Vector3 SouthCross = new Vector3(0, -0.1f, 0);
2294
2295
2296 // use this if no borders were crossed!
2297 ulong newRegionHandle
2298 = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
2299 (uint)((thisy) * Constants.RegionSize));
2300
2301 Vector3 pos = attemptedPosition;
2302
2303 int changeX = 1;
2304 int changeY = 1;
2305
2306 if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
2307 {
2308 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
2309 {
2310
2311 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2312
2313 if (crossedBorderx.BorderLine.Z > 0)
2314 {
2315 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2316 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2317 }
2318 else
2319 pos.X = ((pos.X + Constants.RegionSize));
2320
2321 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2322 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2323
2324 if (crossedBordery.BorderLine.Z > 0)
2325 {
2326 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2327 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2328 }
2329 else
2330 pos.Y = ((pos.Y + Constants.RegionSize));
2331
2332
2333
2334 newRegionHandle
2335 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
2336 (uint)((thisy - changeY) * Constants.RegionSize));
2337 // x - 1
2338 // y - 1
2339 }
2340 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2341 {
2342 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2343
2344 if (crossedBorderx.BorderLine.Z > 0)
2345 {
2346 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2347 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2348 }
2349 else
2350 pos.X = ((pos.X + Constants.RegionSize));
2351
2352 2446
2353 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); 2447 // Compute the absolute position of the object.
2354 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) 2448 double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
2449 double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
2355 2450
2356 if (crossedBordery.BorderLine.Z > 0) 2451 // Ask the grid service for the region that contains the passed address
2357 { 2452 GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
2358 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); 2453 objectWorldLocX, objectWorldLocY);
2359 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2360 }
2361 else
2362 pos.Y = ((pos.Y + Constants.RegionSize));
2363 2454
2364 newRegionHandle 2455 Vector3 pos = Vector3.Zero;
2365 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), 2456 if (destination != null)
2366 (uint)((thisy + changeY) * Constants.RegionSize));
2367 // x - 1
2368 // y + 1
2369 }
2370 else
2371 {
2372 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2373
2374 if (crossedBorderx.BorderLine.Z > 0)
2375 {
2376 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2377 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2378 }
2379 else
2380 pos.X = ((pos.X + Constants.RegionSize));
2381
2382 newRegionHandle
2383 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
2384 (uint)(thisy * Constants.RegionSize));
2385 // x - 1
2386 }
2387 }
2388 else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
2389 { 2457 {
2390 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) 2458 // Adjust the object's relative position from the old region (attemptedPosition)
2391 { 2459 // to be relative to the new region (pos).
2392 2460 pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
2393 pos.X = ((pos.X - Constants.RegionSize)); 2461 (float)(objectWorldLocY - (double)destination.RegionLocY),
2394 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); 2462 attemptedPosition.Z);
2395 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2396
2397 if (crossedBordery.BorderLine.Z > 0)
2398 {
2399 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2400 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2401 }
2402 else
2403 pos.Y = ((pos.Y + Constants.RegionSize));
2404
2405
2406 newRegionHandle
2407 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2408 (uint)((thisy - changeY) * Constants.RegionSize));
2409 // x + 1
2410 // y - 1
2411 }
2412 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2413 {
2414 pos.X = ((pos.X - Constants.RegionSize));
2415 pos.Y = ((pos.Y - Constants.RegionSize));
2416 newRegionHandle
2417 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2418 (uint)((thisy + changeY) * Constants.RegionSize));
2419 // x + 1
2420 // y + 1
2421 }
2422 else
2423 {
2424 pos.X = ((pos.X - Constants.RegionSize));
2425 newRegionHandle
2426 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2427 (uint)(thisy * Constants.RegionSize));
2428 // x + 1
2429 }
2430 } 2463 }
2431 else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
2432 {
2433 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2434 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2435
2436 if (crossedBordery.BorderLine.Z > 0)
2437 {
2438 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2439 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2440 }
2441 else
2442 pos.Y = ((pos.Y + Constants.RegionSize));
2443 2464
2444 newRegionHandle 2465 if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2445 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
2446 // y - 1
2447 }
2448 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2449 { 2466 {
2467 m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
2450 2468
2451 pos.Y = ((pos.Y - Constants.RegionSize)); 2469 // We are going to move the object back to the old position so long as the old position
2452 newRegionHandle 2470 // is in the region
2453 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); 2471 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
2454 // y + 1 2472 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
2455 } 2473 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
2456 2474
2457 // Offset the positions for the new region across the border 2475 grp.AbsolutePosition = oldGroupPosition;
2458 Vector3 oldGroupPosition = grp.RootPart.GroupPosition; 2476 grp.Velocity = Vector3.Zero;
2477 if (grp.RootPart.PhysActor != null)
2478 grp.RootPart.PhysActor.CrossingFailure();
2459 2479
2460 // If we fail to cross the border, then reset the position of the scene object on that border. 2480 if (grp.RootPart.KeyframeMotion != null)
2461 uint x = 0, y = 0; 2481 grp.RootPart.KeyframeMotion.CrossingFailure();
2462 Utils.LongToUInts(newRegionHandle, out x, out y);
2463 GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
2464 2482
2465 if (destination != null) 2483 grp.ScheduleGroupForFullUpdate();
2466 {
2467 if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2468 return; // we did it
2469 } 2484 }
2470
2471 // no one or failed lets go back and tell physics to go on
2472 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
2473 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
2474 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f);
2475
2476 grp.AbsolutePosition = oldGroupPosition;
2477 grp.Velocity = Vector3.Zero;
2478
2479 if (grp.RootPart.PhysActor != null)
2480 grp.RootPart.PhysActor.CrossingFailure();
2481
2482 if (grp.RootPart.KeyframeMotion != null)
2483 grp.RootPart.KeyframeMotion.CrossingFailure();
2484
2485 grp.ScheduleGroupForFullUpdate();
2486 } 2485 }
2487 2486
2488
2489
2490 /// <summary> 2487 /// <summary>
2491 /// Move the given scene object into a new region 2488 /// Move the given scene object into a new region
2492 /// </summary> 2489 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index fc02916..6a04acf 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -77,6 +77,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
77 public class EntityTransferStateMachine 77 public class EntityTransferStateMachine
78 { 78 {
79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
80 private static readonly string LogHeader = "[ENTITY TRANSFER STATE MACHINE]";
80 81
81 /// <summary> 82 /// <summary>
82 /// If true then on a teleport, the source region waits for a callback from the destination region. If 83 /// If true then on a teleport, the source region waits for a callback from the destination region. If
@@ -100,6 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
100 /// <returns>true if the agent was not already in transit, false if it was</returns> 101 /// <returns>true if the agent was not already in transit, false if it was</returns>
101 internal bool SetInTransit(UUID id) 102 internal bool SetInTransit(UUID id)
102 { 103 {
104 m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id);
103 lock (m_agentsInTransit) 105 lock (m_agentsInTransit)
104 { 106 {
105 if (!m_agentsInTransit.ContainsKey(id)) 107 if (!m_agentsInTransit.ContainsKey(id))
@@ -121,6 +123,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
121 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> 123 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
122 internal bool UpdateInTransit(UUID id, AgentTransferState newState) 124 internal bool UpdateInTransit(UUID id, AgentTransferState newState)
123 { 125 {
126 m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState);
127
124 bool transitionOkay = false; 128 bool transitionOkay = false;
125 129
126 // We don't want to throw an exception on cancel since this can come it at any time. 130 // We don't want to throw an exception on cancel since this can come it at any time.
@@ -193,6 +197,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
193 } 197 }
194 else if (failIfNotOkay) 198 else if (failIfNotOkay)
195 { 199 {
200 m_log.DebugFormat("{0} UpdateInTransit. Throwing transition failure = {1}", LogHeader, failureMessage);
196 throw new Exception(failureMessage); 201 throw new Exception(failureMessage);
197 } 202 }
198// else 203// else