aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
diff options
context:
space:
mode:
authordiva2009-02-12 23:23:44 +0000
committerdiva2009-02-12 23:23:44 +0000
commit7a274a7e1dfa651c17cb33ca1994f321ccddc005 (patch)
tree2864e53e24a97c3d77a83f2b2d852bf1119415d9 /OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
parent* Make it possible to load and save inventory archives while a user is not lo... (diff)
downloadopensim-SC_OLD-7a274a7e1dfa651c17cb33ca1994f321ccddc005.zip
opensim-SC_OLD-7a274a7e1dfa651c17cb33ca1994f321ccddc005.tar.gz
opensim-SC_OLD-7a274a7e1dfa651c17cb33ca1994f321ccddc005.tar.bz2
opensim-SC_OLD-7a274a7e1dfa651c17cb33ca1994f321ccddc005.tar.xz
Makes region crossings asynchronous. Moved the bulk of the original code out of ScenePresence and into SceneCommunicationService, where it should be (next to RequestTeleportToLocation). No changes in the crossing mechanism itself, yet. But this change opens the way to doing crossings as slowly as it needs to be, outside the simulator Update loop.
Note: weirdnesses may occur!
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs170
1 files changed, 170 insertions, 0 deletions
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);