diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 497 |
1 files changed, 170 insertions, 327 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ef5239a..4954cd9 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
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 | 56 | ||
56 | public const int DefaultMaxTransferDistance = 4095; | 57 | public const int DefaultMaxTransferDistance = 4095; |
57 | public const bool WaitForAgentArrivedAtDestinationDefault = true; | 58 | public const bool WaitForAgentArrivedAtDestinationDefault = true; |
@@ -433,10 +434,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
433 | float posZLimit = 22; | 434 | float posZLimit = 22; |
434 | 435 | ||
435 | // TODO: Check other Scene HeightField | 436 | // TODO: Check other Scene HeightField |
436 | if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) | 437 | posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; |
437 | { | ||
438 | posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; | ||
439 | } | ||
440 | 438 | ||
441 | float newPosZ = posZLimit + localAVHeight; | 439 | float newPosZ = posZLimit + localAVHeight; |
442 | if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) | 440 | if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) |
@@ -489,9 +487,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
489 | 487 | ||
490 | if (finalDestination == null) | 488 | if (finalDestination == null) |
491 | { | 489 | { |
492 | m_log.WarnFormat( | 490 | m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}", |
493 | "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}", | 491 | LogHeader, sp.Name, sp.UUID); |
494 | sp.Name, sp.UUID); | ||
495 | 492 | ||
496 | sp.ControllingClient.SendTeleportFailed("Problem at destination"); | 493 | sp.ControllingClient.SendTeleportFailed("Problem at destination"); |
497 | return; | 494 | return; |
@@ -532,11 +529,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
532 | 529 | ||
533 | // and set the map-tile to '(Offline)' | 530 | // and set the map-tile to '(Offline)' |
534 | uint regX, regY; | 531 | uint regX, regY; |
535 | Utils.LongToUInts(regionHandle, out regX, out regY); | 532 | Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY); |
536 | 533 | ||
537 | MapBlockData block = new MapBlockData(); | 534 | MapBlockData block = new MapBlockData(); |
538 | block.X = (ushort)(regX / Constants.RegionSize); | 535 | block.X = (ushort)Util.WorldToRegionLoc(regX); |
539 | block.Y = (ushort)(regY / Constants.RegionSize); | 536 | block.Y = (ushort)Util.WorldToRegionLoc(regY); |
540 | block.Access = 254; // == not there | 537 | block.Access = 254; // == not there |
541 | 538 | ||
542 | List<MapBlockData> blocks = new List<MapBlockData>(); | 539 | List<MapBlockData> blocks = new List<MapBlockData>(); |
@@ -1342,6 +1339,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1342 | if (uinfo.HomeRegionID == UUID.Zero) | 1339 | if (uinfo.HomeRegionID == UUID.Zero) |
1343 | { | 1340 | { |
1344 | // can't find the Home region: Tell viewer and abort | 1341 | // can't find the Home region: Tell viewer and abort |
1342 | m_log.ErrorFormat("{0} No grid user info found for {1} {2}. Cannot send home.", | ||
1343 | LogHeader, client.Name, client.AgentId); | ||
1345 | client.SendTeleportFailed("You don't have a home position set."); | 1344 | client.SendTeleportFailed("You don't have a home position set."); |
1346 | return false; | 1345 | return false; |
1347 | } | 1346 | } |
@@ -1375,7 +1374,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1375 | 1374 | ||
1376 | #region Agent Crossings | 1375 | #region Agent Crossings |
1377 | 1376 | ||
1378 | public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) | 1377 | // Given a position relative to the current region (which has previously been tested to |
1378 | // see that it is actually outside the current region), find the new region that the | ||
1379 | // point is actually in. | ||
1380 | // Returns the coordinates and information of the new region or 'null' of it doesn't exist. | ||
1381 | public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos) | ||
1379 | { | 1382 | { |
1380 | version = String.Empty; | 1383 | version = String.Empty; |
1381 | newpos = new Vector3(pos.X, pos.Y, pos.Z); | 1384 | newpos = new Vector3(pos.X, pos.Y, pos.Z); |
@@ -1383,130 +1386,59 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1383 | // m_log.DebugFormat( | 1386 | // m_log.DebugFormat( |
1384 | // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); | 1387 | // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); |
1385 | 1388 | ||
1386 | uint neighbourx = scene.RegionInfo.RegionLocX; | 1389 | // Compute world location of the object's position |
1387 | uint neighboury = scene.RegionInfo.RegionLocY; | 1390 | double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X; |
1388 | const float boundaryDistance = 1.7f; | 1391 | double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y; |
1389 | Vector3 northCross = new Vector3(0, boundaryDistance, 0); | 1392 | |
1390 | Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0); | 1393 | // Call the grid service to lookup the region containing the new position. |
1391 | Vector3 eastCross = new Vector3(boundaryDistance, 0, 0); | 1394 | GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, |
1392 | Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0); | 1395 | presenceWorldX, presenceWorldY); |
1393 | 1396 | ||
1394 | // distance into new region to place avatar | 1397 | if (neighbourRegion != null) |
1395 | const float enterDistance = 0.5f; | 1398 | { |
1396 | 1399 | // Compute the entity's position relative to the new region | |
1397 | if (scene.TestBorderCross(pos + westCross, Cardinals.W)) | 1400 | newpos = new Vector3( (float)(presenceWorldX - (double)neighbourRegion.RegionLocX), |
1398 | { | 1401 | (float)(presenceWorldY - (double)neighbourRegion.RegionLocY), |
1399 | if (scene.TestBorderCross(pos + northCross, Cardinals.N)) | 1402 | pos.Z); |
1400 | { | 1403 | |
1401 | Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); | 1404 | // Check if banned from destination region. |
1402 | neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); | 1405 | ExpiringCache<ulong, DateTime> r; |
1406 | DateTime banUntil; | ||
1407 | if (m_bannedRegions.TryGetValue(agentID, out r)) | ||
1408 | { | ||
1409 | if (r.TryGetValue(neighbourRegion.RegionHandle, out banUntil)) | ||
1410 | { | ||
1411 | if (DateTime.Now < banUntil) | ||
1412 | { | ||
1413 | // If we're banned from the destination, we just can't go there. | ||
1414 | neighbourRegion = null; | ||
1415 | } | ||
1416 | r.Remove(neighbourRegion.RegionHandle); | ||
1417 | } | ||
1418 | } | ||
1419 | else | ||
1420 | { | ||
1421 | r = null; | ||
1403 | } | 1422 | } |
1404 | else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) | ||
1405 | { | ||
1406 | neighboury--; | ||
1407 | newpos.Y = Constants.RegionSize - enterDistance; | ||
1408 | } | ||
1409 | |||
1410 | neighbourx--; | ||
1411 | newpos.X = Constants.RegionSize - enterDistance; | ||
1412 | } | ||
1413 | else if (scene.TestBorderCross(pos + eastCross, Cardinals.E)) | ||
1414 | { | ||
1415 | Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E); | ||
1416 | neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); | ||
1417 | newpos.X = enterDistance; | ||
1418 | 1423 | ||
1419 | if (scene.TestBorderCross(pos + southCross, Cardinals.S)) | 1424 | // Check to see if we have access to the target region. |
1425 | string reason; | ||
1426 | if (neighbourRegion != null | ||
1427 | && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) | ||
1420 | { | 1428 | { |
1421 | neighboury--; | 1429 | if (r == null) |
1422 | newpos.Y = Constants.RegionSize - enterDistance; | 1430 | { |
1423 | } | 1431 | r = new ExpiringCache<ulong, DateTime>(); |
1424 | else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) | 1432 | r.Add(neighbourRegion.RegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); |
1425 | { | ||
1426 | Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N); | ||
1427 | neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize); | ||
1428 | newpos.Y = enterDistance; | ||
1429 | } | ||
1430 | } | ||
1431 | else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) | ||
1432 | { | ||
1433 | Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); | ||
1434 | neighboury--; | ||
1435 | newpos.Y = Constants.RegionSize - enterDistance; | ||
1436 | } | ||
1437 | else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) | ||
1438 | { | ||
1439 | Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); | ||
1440 | neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); | ||
1441 | newpos.Y = enterDistance; | ||
1442 | } | ||
1443 | |||
1444 | /* | ||
1445 | |||
1446 | if (pos.X < boundaryDistance) //West | ||
1447 | { | ||
1448 | neighbourx--; | ||
1449 | newpos.X = Constants.RegionSize - enterDistance; | ||
1450 | } | ||
1451 | else if (pos.X > Constants.RegionSize - boundaryDistance) // East | ||
1452 | { | ||
1453 | neighbourx++; | ||
1454 | newpos.X = enterDistance; | ||
1455 | } | ||
1456 | |||
1457 | if (pos.Y < boundaryDistance) // South | ||
1458 | { | ||
1459 | neighboury--; | ||
1460 | newpos.Y = Constants.RegionSize - enterDistance; | ||
1461 | } | ||
1462 | else if (pos.Y > Constants.RegionSize - boundaryDistance) // North | ||
1463 | { | ||
1464 | neighboury++; | ||
1465 | newpos.Y = enterDistance; | ||
1466 | } | ||
1467 | */ | ||
1468 | |||
1469 | xDest = neighbourx; | ||
1470 | yDest = neighboury; | ||
1471 | |||
1472 | int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); | ||
1473 | |||
1474 | ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y); | ||
1475 | |||
1476 | ExpiringCache<ulong, DateTime> r; | ||
1477 | DateTime banUntil; | ||
1478 | |||
1479 | if (m_bannedRegions.TryGetValue(agentID, out r)) | ||
1480 | { | ||
1481 | if (r.TryGetValue(neighbourHandle, out banUntil)) | ||
1482 | { | ||
1483 | if (DateTime.Now < banUntil) | ||
1484 | return null; | ||
1485 | r.Remove(neighbourHandle); | ||
1486 | } | ||
1487 | } | ||
1488 | else | ||
1489 | { | ||
1490 | r = null; | ||
1491 | } | ||
1492 | |||
1493 | GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); | ||
1494 | |||
1495 | string reason; | ||
1496 | if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) | ||
1497 | { | ||
1498 | if (r == null) | ||
1499 | { | ||
1500 | r = new ExpiringCache<ulong, DateTime>(); | ||
1501 | r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); | ||
1502 | 1433 | ||
1503 | m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45)); | 1434 | m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45)); |
1504 | } | 1435 | } |
1505 | else | 1436 | else |
1506 | { | 1437 | { |
1507 | r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); | 1438 | r.Add(neighbourRegion.RegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); |
1508 | } | 1439 | } |
1509 | return null; | 1440 | neighbourRegion = null; |
1441 | } | ||
1510 | } | 1442 | } |
1511 | 1443 | ||
1512 | return neighbourRegion; | 1444 | return neighbourRegion; |
@@ -1519,7 +1451,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1519 | Vector3 newpos; | 1451 | Vector3 newpos; |
1520 | string version; | 1452 | string version; |
1521 | 1453 | ||
1522 | GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos); | 1454 | GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out version, out newpos); |
1523 | if (neighbourRegion == null) | 1455 | if (neighbourRegion == null) |
1524 | { | 1456 | { |
1525 | agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); | 1457 | agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); |
@@ -2028,15 +1960,80 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2028 | } | 1960 | } |
2029 | } | 1961 | } |
2030 | 1962 | ||
1963 | // Computes the difference between two region bases. | ||
1964 | // Returns a vector of world coordinates (meters) from base of first region to the second. | ||
1965 | // The first region is the home region of the passed scene presence. | ||
2031 | Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) | 1966 | Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) |
2032 | { | 1967 | { |
2033 | int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX; | 1968 | /* |
2034 | int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY; | 1969 | int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX; |
1970 | int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY; | ||
2035 | int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize; | 1971 | int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize; |
2036 | int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize; | 1972 | int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize; |
2037 | int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize; | 1973 | int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize; |
2038 | int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize; | 1974 | int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize; |
2039 | return new Vector3(shiftx, shifty, 0f); | 1975 | return new Vector3(shiftx, shifty, 0f); |
1976 | */ | ||
1977 | return new Vector3(sp.Scene.RegionInfo.RegionLocX - neighbour.RegionLocX, | ||
1978 | sp.Scene.RegionInfo.RegionLocY - neighbour.RegionLocY, | ||
1979 | 0f); | ||
1980 | } | ||
1981 | |||
1982 | // Given a world position (fractional meter coordinate), get the GridRegion info for | ||
1983 | // the region containing that point. | ||
1984 | // Return 'null' if no such region exists. | ||
1985 | private GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py) | ||
1986 | { | ||
1987 | m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py); | ||
1988 | GridRegion ret = null; | ||
1989 | |||
1990 | // As an optimization, since most regions will be legacy sized regions (256x256), first try to get | ||
1991 | // the region at the appropriate legacy region location. | ||
1992 | uint possibleX = (uint)Math.Floor(px); | ||
1993 | possibleX -= possibleX % Constants.RegionSize; | ||
1994 | uint possibleY = (uint)Math.Floor(py); | ||
1995 | possibleY -= possibleY % Constants.RegionSize; | ||
1996 | ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY); | ||
1997 | if (ret != null) | ||
1998 | { | ||
1999 | m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}", | ||
2000 | LogHeader, possibleX, possibleY, ret.RegionName); | ||
2001 | } | ||
2002 | |||
2003 | if (ret == null) | ||
2004 | { | ||
2005 | // If the simple lookup failed, search the larger area for a region that contains this point | ||
2006 | double range = (double)Constants.RegionSize * 2 + 2; | ||
2007 | while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize)) | ||
2008 | { | ||
2009 | // Get from the grid service a list of regions that might contain this point | ||
2010 | List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID, | ||
2011 | (int)(px - range), (int)(px + range), | ||
2012 | (int)(py - range), (int)(py + range)); | ||
2013 | m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}", | ||
2014 | LogHeader, possibleRegions.Count, range); | ||
2015 | if (possibleRegions != null && possibleRegions.Count > 0) | ||
2016 | { | ||
2017 | // If we found some regions, check to see if the point is within | ||
2018 | foreach (GridRegion gr in possibleRegions) | ||
2019 | { | ||
2020 | m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>", | ||
2021 | LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY); | ||
2022 | if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX) | ||
2023 | && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY)) | ||
2024 | { | ||
2025 | // Found a region that contains the point | ||
2026 | ret = gr; | ||
2027 | m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName); | ||
2028 | break; | ||
2029 | } | ||
2030 | } | ||
2031 | } | ||
2032 | // Larger search area for next time around if not found | ||
2033 | range *= 2; | ||
2034 | } | ||
2035 | } | ||
2036 | return ret; | ||
2040 | } | 2037 | } |
2041 | 2038 | ||
2042 | private void InformClientOfNeighbourCompleted(IAsyncResult iar) | 2039 | private void InformClientOfNeighbourCompleted(IAsyncResult iar) |
@@ -2245,10 +2242,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2245 | /// Move the given scene object into a new region depending on which region its absolute position has moved | 2242 | /// Move the given scene object into a new region depending on which region its absolute position has moved |
2246 | /// into. | 2243 | /// into. |
2247 | /// | 2244 | /// |
2248 | /// This method locates the new region handle and offsets the prim position for the new region | 2245 | /// Using the objects new world location, ask the grid service for a the new region and adjust the prim |
2246 | /// position to be relative to the new region. | ||
2249 | /// </summary> | 2247 | /// </summary> |
2250 | /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> | ||
2251 | /// <param name="grp">the scene object that we're crossing</param> | 2248 | /// <param name="grp">the scene object that we're crossing</param> |
2249 | /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is | ||
2250 | /// relative to the region the object currently is in.</param> | ||
2251 | /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param> | ||
2252 | public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) | 2252 | public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) |
2253 | { | 2253 | { |
2254 | if (grp == null) | 2254 | if (grp == null) |
@@ -2274,208 +2274,51 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2274 | return; | 2274 | return; |
2275 | } | 2275 | } |
2276 | 2276 | ||
2277 | int thisx = (int)scene.RegionInfo.RegionLocX; | 2277 | // Remember the old group position in case the region lookup fails so position can be restored. |
2278 | int thisy = (int)scene.RegionInfo.RegionLocY; | 2278 | Vector3 oldGroupPosition = grp.RootPart.GroupPosition; |
2279 | Vector3 EastCross = new Vector3(0.1f, 0, 0); | ||
2280 | Vector3 WestCross = new Vector3(-0.1f, 0, 0); | ||
2281 | Vector3 NorthCross = new Vector3(0, 0.1f, 0); | ||
2282 | Vector3 SouthCross = new Vector3(0, -0.1f, 0); | ||
2283 | |||
2284 | |||
2285 | // use this if no borders were crossed! | ||
2286 | ulong newRegionHandle | ||
2287 | = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize), | ||
2288 | (uint)((thisy) * Constants.RegionSize)); | ||
2289 | |||
2290 | Vector3 pos = attemptedPosition; | ||
2291 | |||
2292 | int changeX = 1; | ||
2293 | int changeY = 1; | ||
2294 | |||
2295 | if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W)) | ||
2296 | { | ||
2297 | if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) | ||
2298 | { | ||
2299 | |||
2300 | Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); | ||
2301 | |||
2302 | if (crossedBorderx.BorderLine.Z > 0) | ||
2303 | { | ||
2304 | pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); | ||
2305 | changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); | ||
2306 | } | ||
2307 | else | ||
2308 | pos.X = ((pos.X + Constants.RegionSize)); | ||
2309 | |||
2310 | Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); | ||
2311 | //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) | ||
2312 | |||
2313 | if (crossedBordery.BorderLine.Z > 0) | ||
2314 | { | ||
2315 | pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); | ||
2316 | changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); | ||
2317 | } | ||
2318 | else | ||
2319 | pos.Y = ((pos.Y + Constants.RegionSize)); | ||
2320 | |||
2321 | |||
2322 | |||
2323 | newRegionHandle | ||
2324 | = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), | ||
2325 | (uint)((thisy - changeY) * Constants.RegionSize)); | ||
2326 | // x - 1 | ||
2327 | // y - 1 | ||
2328 | } | ||
2329 | else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) | ||
2330 | { | ||
2331 | Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); | ||
2332 | |||
2333 | if (crossedBorderx.BorderLine.Z > 0) | ||
2334 | { | ||
2335 | pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); | ||
2336 | changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); | ||
2337 | } | ||
2338 | else | ||
2339 | pos.X = ((pos.X + Constants.RegionSize)); | ||
2340 | |||
2341 | |||
2342 | Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); | ||
2343 | //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) | ||
2344 | |||
2345 | if (crossedBordery.BorderLine.Z > 0) | ||
2346 | { | ||
2347 | pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); | ||
2348 | changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); | ||
2349 | } | ||
2350 | else | ||
2351 | pos.Y = ((pos.Y + Constants.RegionSize)); | ||
2352 | 2279 | ||
2353 | newRegionHandle | 2280 | // Compute the absolute position of the object. |
2354 | = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), | 2281 | double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X; |
2355 | (uint)((thisy + changeY) * Constants.RegionSize)); | 2282 | double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y; |
2356 | // x - 1 | ||
2357 | // y + 1 | ||
2358 | } | ||
2359 | else | ||
2360 | { | ||
2361 | Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); | ||
2362 | 2283 | ||
2363 | if (crossedBorderx.BorderLine.Z > 0) | 2284 | // Ask the grid service for the region that contains the passed address |
2364 | { | 2285 | GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, objectWorldLocX, objectWorldLocY); |
2365 | pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); | ||
2366 | changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); | ||
2367 | } | ||
2368 | else | ||
2369 | pos.X = ((pos.X + Constants.RegionSize)); | ||
2370 | 2286 | ||
2371 | newRegionHandle | 2287 | Vector3 pos = Vector3.Zero; |
2372 | = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), | 2288 | if (destination != null) |
2373 | (uint)(thisy * Constants.RegionSize)); | ||
2374 | // x - 1 | ||
2375 | } | ||
2376 | } | ||
2377 | else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E)) | ||
2378 | { | 2289 | { |
2379 | if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) | 2290 | // Adjust the object's relative position from the old region (attemptedPosition) |
2380 | { | 2291 | // to be relative to the new region (pos). |
2381 | 2292 | pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX), | |
2382 | pos.X = ((pos.X - Constants.RegionSize)); | 2293 | (float)(objectWorldLocY - (double)destination.RegionLocY), |
2383 | Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); | 2294 | attemptedPosition.Z); |
2384 | //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) | ||
2385 | |||
2386 | if (crossedBordery.BorderLine.Z > 0) | ||
2387 | { | ||
2388 | pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); | ||
2389 | changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); | ||
2390 | } | ||
2391 | else | ||
2392 | pos.Y = ((pos.Y + Constants.RegionSize)); | ||
2393 | |||
2394 | |||
2395 | newRegionHandle | ||
2396 | = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), | ||
2397 | (uint)((thisy - changeY) * Constants.RegionSize)); | ||
2398 | // x + 1 | ||
2399 | // y - 1 | ||
2400 | } | ||
2401 | else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) | ||
2402 | { | ||
2403 | pos.X = ((pos.X - Constants.RegionSize)); | ||
2404 | pos.Y = ((pos.Y - Constants.RegionSize)); | ||
2405 | newRegionHandle | ||
2406 | = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), | ||
2407 | (uint)((thisy + changeY) * Constants.RegionSize)); | ||
2408 | // x + 1 | ||
2409 | // y + 1 | ||
2410 | } | ||
2411 | else | ||
2412 | { | ||
2413 | pos.X = ((pos.X - Constants.RegionSize)); | ||
2414 | newRegionHandle | ||
2415 | = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), | ||
2416 | (uint)(thisy * Constants.RegionSize)); | ||
2417 | // x + 1 | ||
2418 | } | ||
2419 | } | 2295 | } |
2420 | else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) | ||
2421 | { | ||
2422 | Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); | ||
2423 | //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) | ||
2424 | 2296 | ||
2425 | if (crossedBordery.BorderLine.Z > 0) | 2297 | if (destination != null) |
2298 | { | ||
2299 | if (!CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) | ||
2426 | { | 2300 | { |
2427 | pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); | 2301 | m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID); |
2428 | changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); | 2302 | |
2303 | // We are going to move the object back to the old position so long as the old position | ||
2304 | // is in the region | ||
2305 | oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1)); | ||
2306 | oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1)); | ||
2307 | oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight); | ||
2308 | |||
2309 | grp.AbsolutePosition = oldGroupPosition; | ||
2310 | grp.Velocity = Vector3.Zero; | ||
2311 | if (grp.RootPart.PhysActor != null) | ||
2312 | grp.RootPart.PhysActor.CrossingFailure(); | ||
2313 | |||
2314 | if (grp.RootPart.KeyframeMotion != null) | ||
2315 | grp.RootPart.KeyframeMotion.CrossingFailure(); | ||
2316 | |||
2317 | grp.ScheduleGroupForFullUpdate(); | ||
2429 | } | 2318 | } |
2430 | else | ||
2431 | pos.Y = ((pos.Y + Constants.RegionSize)); | ||
2432 | |||
2433 | newRegionHandle | ||
2434 | = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); | ||
2435 | // y - 1 | ||
2436 | } | 2319 | } |
2437 | else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) | ||
2438 | { | ||
2439 | |||
2440 | pos.Y = ((pos.Y - Constants.RegionSize)); | ||
2441 | newRegionHandle | ||
2442 | = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); | ||
2443 | // y + 1 | ||
2444 | } | ||
2445 | |||
2446 | // Offset the positions for the new region across the border | ||
2447 | Vector3 oldGroupPosition = grp.RootPart.GroupPosition; | ||
2448 | |||
2449 | // If we fail to cross the border, then reset the position of the scene object on that border. | ||
2450 | uint x = 0, y = 0; | ||
2451 | Utils.LongToUInts(newRegionHandle, out x, out y); | ||
2452 | GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); | ||
2453 | |||
2454 | if (destination != null) | ||
2455 | { | ||
2456 | if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) | ||
2457 | return; // we did it | ||
2458 | } | ||
2459 | |||
2460 | // no one or failed lets go back and tell physics to go on | ||
2461 | oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f); | ||
2462 | oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f); | ||
2463 | oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f); | ||
2464 | |||
2465 | grp.AbsolutePosition = oldGroupPosition; | ||
2466 | grp.Velocity = Vector3.Zero; | ||
2467 | |||
2468 | if (grp.RootPart.PhysActor != null) | ||
2469 | grp.RootPart.PhysActor.CrossingFailure(); | ||
2470 | |||
2471 | if (grp.RootPart.KeyframeMotion != null) | ||
2472 | grp.RootPart.KeyframeMotion.CrossingFailure(); | ||
2473 | |||
2474 | grp.ScheduleGroupForFullUpdate(); | ||
2475 | } | 2320 | } |
2476 | 2321 | ||
2477 | |||
2478 | |||
2479 | /// <summary> | 2322 | /// <summary> |
2480 | /// Move the given scene object into a new region | 2323 | /// Move the given scene object into a new region |
2481 | /// </summary> | 2324 | /// </summary> |