diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
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 246b253..4ab36a5 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 = new Vector3(pos.X, pos.Y, pos.Z); | 1436 | newpos = new Vector3(pos.X, pos.Y, pos.Z); |
@@ -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 |