aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs170
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs164
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs14
4 files changed, 219 insertions, 134 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e2eb89e..30b44b1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3179,6 +3179,11 @@ namespace OpenSim.Region.Framework.Scenes
3179 return m_sceneGridService.CrossToNeighbouringRegion(regionHandle, agentID, position, isFlying); 3179 return m_sceneGridService.CrossToNeighbouringRegion(regionHandle, agentID, position, isFlying);
3180 } 3180 }
3181 3181
3182 public void CrossAgentToNewRegion(ScenePresence agent, bool isFlying)
3183 {
3184 m_sceneGridService.CrossAgentToNewRegion(this, agent, isFlying);
3185 }
3186
3182 public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence) 3187 public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence)
3183 { 3188 {
3184 m_sceneGridService.SendChildAgentDataUpdate(cadu, presence); 3189 m_sceneGridService.SendChildAgentDataUpdate(cadu, presence);
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index bef57a0..98b0f97 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -35,6 +35,7 @@ using OpenMetaverse.StructuredData;
35using log4net; 35using log4net;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
38using OpenSim.Framework.Communications.Cache;
38using OpenSim.Framework.Communications.Capabilities; 39using OpenSim.Framework.Communications.Capabilities;
39using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
40using OSD = OpenMetaverse.StructuredData.OSD; 41using OSD = OpenMetaverse.StructuredData.OSD;
@@ -1018,6 +1019,175 @@ namespace OpenSim.Region.Framework.Scenes
1018 return m_commsProvider.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position, isFlying); 1019 return m_commsProvider.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position, isFlying);
1019 } 1020 }
1020 1021
1022 public void CrossAgentToNewRegion(Scene scene, ScenePresence agent, bool isFlying)
1023 {
1024 Vector3 pos = agent.AbsolutePosition;
1025 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
1026 uint neighbourx = m_regionInfo.RegionLocX;
1027 uint neighboury = m_regionInfo.RegionLocY;
1028
1029 // distance to edge that will trigger crossing
1030 const float boundaryDistance = 1.7f;
1031
1032 // distance into new region to place avatar
1033 const float enterDistance = 0.1f;
1034
1035 if (pos.X < boundaryDistance)
1036 {
1037 neighbourx--;
1038 newpos.X = Constants.RegionSize - enterDistance;
1039 }
1040 else if (pos.X > Constants.RegionSize - boundaryDistance)
1041 {
1042 neighbourx++;
1043 newpos.X = enterDistance;
1044 }
1045
1046 if (pos.Y < boundaryDistance)
1047 {
1048 neighboury--;
1049 newpos.Y = Constants.RegionSize - enterDistance;
1050 }
1051 else if (pos.Y > Constants.RegionSize - boundaryDistance)
1052 {
1053 neighboury++;
1054 newpos.Y = enterDistance;
1055 }
1056
1057 Vector3 vel = agent.Velocity;
1058
1059 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
1060 d.BeginInvoke(agent, newpos, neighbourx, neighboury, isFlying, CrossAgentToNewRegionCompleted, d);
1061
1062
1063 }
1064
1065 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying);
1066
1067 /// <summary>
1068 /// This Closes child agents on neighboring regions
1069 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1070 /// </summary>
1071 protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying)
1072 {
1073 m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
1074
1075 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
1076 SimpleRegionInfo neighbourRegion = RequestNeighbouringRegionInfo(neighbourHandle);
1077 if (neighbourRegion != null && agent.ValidateAttachments())
1078 {
1079 pos = pos + (agent.Velocity);
1080
1081 CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
1082 if (userInfo != null)
1083 {
1084 userInfo.DropInventory();
1085 }
1086 else
1087 {
1088 m_log.WarnFormat("[SCENE COMM]: No cached user info found for {0} {1} on leaving region {2}",
1089 agent.Name, agent.UUID, agent.Scene.RegionInfo.RegionName);
1090 }
1091
1092 bool crossingSuccessful =
1093 CrossToNeighbouringRegion(neighbourHandle, agent.ControllingClient.AgentId, pos,
1094 isFlying);
1095 if (crossingSuccessful)
1096 {
1097 // Next, let's close the child agent connections that are too far away.
1098 agent.CloseChildAgents(neighbourx, neighboury);
1099
1100 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
1101 agent.ControllingClient.RequestClientInfo();
1102
1103 //Console.WriteLine("BEFORE CROSS");
1104 //Scene.DumpChildrenSeeds(UUID);
1105 //DumpKnownRegions();
1106 string agentcaps;
1107 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
1108 {
1109 m_log.ErrorFormat("[SCENE COMM]: No CAPS information for region handle {0}, exiting CrossToNewRegion.",
1110 neighbourRegion.RegionHandle);
1111 return agent;
1112 }
1113 // TODO Should construct this behind a method
1114 string capsPath =
1115 "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
1116 + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
1117
1118 m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
1119
1120 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
1121 if (eq != null)
1122 {
1123 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
1124 capsPath, agent.UUID, agent.ControllingClient.SessionId);
1125 }
1126 else
1127 {
1128 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
1129 capsPath);
1130 }
1131
1132 agent.MakeChildAgent();
1133 // now we have a child agent in this region. Request all interesting data about other (root) agents
1134 agent.SendInitialFullUpdateToAllClients();
1135
1136 agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true);
1137
1138 // m_scene.SendKillObject(m_localId);
1139
1140 agent.Scene.NotifyMyCoarseLocationChange();
1141 // the user may change their profile information in other region,
1142 // so the userinfo in UserProfileCache is not reliable any more, delete it
1143 if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1144 {
1145 agent.Scene.CommsManager.UserProfileCacheService.RemoveUser(agent.UUID);
1146 m_log.DebugFormat(
1147 "[SCENE COMM]: User {0} is going to another region, profile cache removed", agent.UUID);
1148 }
1149 }
1150 else
1151 {
1152 //// Restore the user structures that we needed to delete before asking the receiving region
1153 //// to complete the crossing
1154 //userInfo.FetchInventory();
1155 //agent.Scene.CapsModule.AddCapsHandler(agent.UUID);
1156 }
1157 }
1158
1159 //Console.WriteLine("AFTER CROSS");
1160 //Scene.DumpChildrenSeeds(UUID);
1161 //DumpKnownRegions();
1162 return agent;
1163 }
1164
1165 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
1166 {
1167 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
1168 ScenePresence agent = icon.EndInvoke(iar);
1169
1170 // If the cross was successful, this agent is a child agent
1171 if (agent.IsChildAgent)
1172 {
1173 // Put the child agent back at the center
1174 agent.AbsolutePosition = new Vector3(128, 128, 70);
1175 }
1176 else // Not successful
1177 {
1178 CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
1179 if (userInfo != null)
1180 {
1181 userInfo.FetchInventory();
1182 }
1183 agent.RestoreInCurrentScene();
1184 }
1185 agent.IsInTransit = false;
1186
1187 //m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1188 }
1189
1190
1021 public bool PrimCrossToNeighboringRegion(ulong regionhandle, UUID primID, string objData, int XMLMethod) 1191 public bool PrimCrossToNeighboringRegion(ulong regionhandle, UUID primID, string objData, int XMLMethod)
1022 { 1192 {
1023 return m_commsProvider.InterRegion.InformRegionOfPrimCrossing(regionhandle, primID, objData, XMLMethod); 1193 return m_commsProvider.InterRegion.InformRegionOfPrimCrossing(regionhandle, primID, objData, XMLMethod);
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2dd305a..f841707 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -547,6 +547,13 @@ namespace OpenSim.Region.Framework.Scenes
547 get { return m_animations; } 547 get { return m_animations; }
548 } 548 }
549 549
550 private bool m_inTransit;
551 public bool IsInTransit
552 {
553 get { return m_inTransit; }
554 set { m_inTransit = value; }
555 }
556
550 #endregion 557 #endregion
551 558
552 #region Constructor(s) 559 #region Constructor(s)
@@ -850,7 +857,7 @@ namespace OpenSim.Region.Framework.Scenes
850 857
851 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid); 858 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
852 if (userInfo != null) 859 if (userInfo != null)
853 userInfo.FetchInventory(); 860 userInfo.FetchInventory();
854 else 861 else
855 m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid); 862 m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
856 863
@@ -2377,15 +2384,31 @@ namespace OpenSim.Region.Framework.Scenes
2377 pos2.Y = pos2.Y + (vel.Y*timeStep); 2384 pos2.Y = pos2.Y + (vel.Y*timeStep);
2378 pos2.Z = pos2.Z + (vel.Z*timeStep); 2385 pos2.Z = pos2.Z + (vel.Z*timeStep);
2379 2386
2380 if ((pos2.X < 0) || (pos2.X > Constants.RegionSize)) 2387 if (!IsInTransit)
2381 { 2388 {
2382 CrossToNewRegion(); 2389 if ((pos2.X < 0) || (pos2.X > Constants.RegionSize))
2383 } 2390 {
2391 CrossToNewRegion();
2392 }
2384 2393
2385 if ((pos2.Y < 0) || (pos2.Y > Constants.RegionSize)) 2394 if ((pos2.Y < 0) || (pos2.Y > Constants.RegionSize))
2395 {
2396 CrossToNewRegion();
2397 }
2398 }
2399 else
2386 { 2400 {
2387 CrossToNewRegion(); 2401 RemoveFromPhysicalScene();
2402 // This constant has been inferred from experimentation
2403 // I'm not sure what this value should be, so I tried a few values.
2404 timeStep = 0.04f;
2405 pos2 = AbsolutePosition;
2406 pos2.X = pos2.X + (vel.X * timeStep);
2407 pos2.Y = pos2.Y + (vel.Y * timeStep);
2408 pos2.Z = pos2.Z + (vel.Z * timeStep);
2409 m_pos = pos2;
2388 } 2410 }
2411
2389 } 2412 }
2390 2413
2391 /// <summary> 2414 /// <summary>
@@ -2396,130 +2419,13 @@ namespace OpenSim.Region.Framework.Scenes
2396 /// </summary> 2419 /// </summary>
2397 protected void CrossToNewRegion() 2420 protected void CrossToNewRegion()
2398 { 2421 {
2399 Vector3 pos = AbsolutePosition; 2422 m_inTransit = true;
2400 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z); 2423 m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying);
2401 uint neighbourx = m_regionInfo.RegionLocX; 2424 }
2402 uint neighboury = m_regionInfo.RegionLocY;
2403
2404 // distance to edge that will trigger crossing
2405 const float boundaryDistance = 1.7f;
2406
2407 // distance into new region to place avatar
2408 const float enterDistance = 0.1f;
2409
2410 if (pos.X < boundaryDistance)
2411 {
2412 neighbourx--;
2413 newpos.X = Constants.RegionSize - enterDistance;
2414 }
2415 else if (pos.X > Constants.RegionSize - boundaryDistance)
2416 {
2417 neighbourx++;
2418 newpos.X = enterDistance;
2419 }
2420
2421 if (pos.Y < boundaryDistance)
2422 {
2423 neighboury--;
2424 newpos.Y = Constants.RegionSize - enterDistance;
2425 }
2426 else if (pos.Y > Constants.RegionSize - boundaryDistance)
2427 {
2428 neighboury++;
2429 newpos.Y = enterDistance;
2430 }
2431
2432 Vector3 vel = m_velocity;
2433 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
2434 SimpleRegionInfo neighbourRegion = m_scene.RequestNeighbouringRegionInfo(neighbourHandle);
2435 if (neighbourRegion != null && ValidateAttachments())
2436 {
2437 // When the neighbour is informed of the border crossing, it will set up CAPS handlers for the avatar
2438 // This means we need to remove the current caps handler here and possibly compensate later,
2439 // in case both scenes are being hosted on the same region server. Messy
2440 //m_scene.RemoveCapsHandler(UUID);
2441 newpos = newpos + (vel);
2442
2443 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(UUID);
2444 if (userInfo != null)
2445 {
2446 userInfo.DropInventory();
2447 }
2448 else
2449 {
2450 m_log.WarnFormat("[SCENE PRESENCE]: No cached user info found for {0} {1} on leaving region", Name, UUID);
2451 }
2452
2453 bool crossingSuccessful =
2454 m_scene.InformNeighbourOfCrossing(neighbourHandle, m_controllingClient.AgentId, newpos,
2455 m_physicsActor.Flying);
2456 if (crossingSuccessful)
2457 {
2458 // Next, let's close the child agent connections that are too far away.
2459 CloseChildAgents(neighbourx, neighboury);
2460
2461 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
2462 m_controllingClient.RequestClientInfo();
2463
2464 //Console.WriteLine("BEFORE CROSS");
2465 //Scene.DumpChildrenSeeds(UUID);
2466 //DumpKnownRegions();
2467 string agentcaps;
2468 if (!m_knownChildRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
2469 {
2470 m_log.ErrorFormat("[SCENE PRESENCE]: No CAPS information for region handle {0}, exiting CrossToNewRegion.",
2471 neighbourRegion.RegionHandle);
2472 return;
2473 }
2474 // TODO Should construct this behind a method
2475 string capsPath =
2476 "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
2477 + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
2478
2479 m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, m_uuid);
2480
2481 IEventQueue eq = m_scene.RequestModuleInterface<IEventQueue>();
2482 if (eq != null)
2483 {
2484 eq.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint,
2485 capsPath, UUID, ControllingClient.SessionId);
2486 }
2487 else
2488 {
2489 m_controllingClient.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint,
2490 capsPath);
2491 }
2492
2493 MakeChildAgent();
2494 // now we have a child agent in this region. Request all interesting data about other (root) agents
2495 SendInitialFullUpdateToAllClients();
2496
2497 CrossAttachmentsIntoNewRegion(neighbourHandle, true);
2498
2499 // m_scene.SendKillObject(m_localId);
2500
2501 m_scene.NotifyMyCoarseLocationChange();
2502 // the user may change their profile information in other region,
2503 // so the userinfo in UserProfileCache is not reliable any more, delete it
2504 if (m_scene.NeedSceneCacheClear(UUID))
2505 {
2506 m_scene.CommsManager.UserProfileCacheService.RemoveUser(UUID);
2507 m_log.DebugFormat(
2508 "[SCENE PRESENCE]: User {0} is going to another region, profile cache removed", UUID);
2509 }
2510 }
2511 else
2512 {
2513 // Restore the user structures that we needed to delete before asking the receiving region
2514 // to complete the crossing
2515 userInfo.FetchInventory();
2516 m_scene.CapsModule.AddCapsHandler(UUID);
2517 }
2518 }
2519 2425
2520 //Console.WriteLine("AFTER CROSS"); 2426 public void RestoreInCurrentScene()
2521 //Scene.DumpChildrenSeeds(UUID); 2427 {
2522 //DumpKnownRegions(); 2428 AddToPhysicalScene();
2523 } 2429 }
2524 2430
2525 /// <summary> 2431 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
index db88878..2f2bc19 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
@@ -66,11 +66,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
66 scene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000, cm); 66 scene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000, cm);
67 scene3 = SceneSetupHelpers.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000, cm); 67 scene3 = SceneSetupHelpers.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000, cm);
68 68
69 IRegionModule interregionComms = new RESTInterregionComms(); 69 IRegionModule interregionComms = new RESTInterregionComms();
70 interregionComms.Initialise(scene, new IniConfigSource()); 70 interregionComms.Initialise(scene, new IniConfigSource());
71 interregionComms.Initialise(scene2, new IniConfigSource()); 71 interregionComms.Initialise(scene2, new IniConfigSource());
72 interregionComms.Initialise(scene3, new IniConfigSource()); 72 interregionComms.Initialise(scene3, new IniConfigSource());
73 interregionComms.PostInitialise(); 73 interregionComms.PostInitialise();
74 SceneSetupHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); 74 SceneSetupHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms);
75 SceneSetupHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); 75 SceneSetupHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms);
76 SceneSetupHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); 76 SceneSetupHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms);
@@ -203,6 +203,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
203 scene.RegisterRegionWithGrid(); 203 scene.RegisterRegionWithGrid();
204 scene2.RegisterRegionWithGrid(); 204 scene2.RegisterRegionWithGrid();
205 presence.Update(); 205 presence.Update();
206 // Crossings are asynchronous
207 while (presence.IsInTransit) { } ;
206 208
207 Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); 209 Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected.");
208 Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); 210 Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent.");
@@ -210,6 +212,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
210 // Cross Back 212 // Cross Back
211 presence2.AbsolutePosition = new Vector3(-1, 3, 100); 213 presence2.AbsolutePosition = new Vector3(-1, 3, 100);
212 presence2.Update(); 214 presence2.Update();
215 // Crossings are asynchronous
216 while (presence.IsInTransit) { };
213 217
214 Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); 218 Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected.");
215 Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); 219 Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again.");