diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 210 |
1 files changed, 116 insertions, 94 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 538dd5f..486f9d2 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
220 | /// <param name="sp"></param> | 220 | /// <param name="sp"></param> |
221 | /// <param name="position"></param> | 221 | /// <param name="position"></param> |
222 | /// <param name="lookAt"></param> | 222 | /// <param name="lookAt"></param> |
223 | /// <param name="teleportFlags"></param | 223 | /// <param name="teleportFlags"></param> |
224 | private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags) | 224 | private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags) |
225 | { | 225 | { |
226 | m_log.DebugFormat( | 226 | m_log.DebugFormat( |
@@ -264,6 +264,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
264 | position.Z = newPosZ; | 264 | position.Z = newPosZ; |
265 | } | 265 | } |
266 | 266 | ||
267 | if (sp.Flying) | ||
268 | teleportFlags |= (uint)TeleportFlags.IsFlying; | ||
269 | |||
267 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 270 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
268 | 271 | ||
269 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 272 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
@@ -471,6 +474,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
471 | if (sp.ParentID != (uint)0) | 474 | if (sp.ParentID != (uint)0) |
472 | sp.StandUp(); | 475 | sp.StandUp(); |
473 | 476 | ||
477 | else if (sp.Flying) | ||
478 | teleportFlags |= (uint)TeleportFlags.IsFlying; | ||
479 | |||
474 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 480 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
475 | 481 | ||
476 | // the avatar.Close below will clear the child region list. We need this below for (possibly) | 482 | // the avatar.Close below will clear the child region list. We need this below for (possibly) |
@@ -982,7 +988,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
982 | agent.IsInTransit = true; | 988 | agent.IsInTransit = true; |
983 | 989 | ||
984 | CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; | 990 | CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; |
985 | d.BeginInvoke(agent, newpos, x, y, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); | 991 | d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); |
986 | 992 | ||
987 | return true; | 993 | return true; |
988 | } | 994 | } |
@@ -1039,42 +1045,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1039 | icon.EndInvoke(iar); | 1045 | icon.EndInvoke(iar); |
1040 | } | 1046 | } |
1041 | 1047 | ||
1048 | public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion) | ||
1049 | { | ||
1050 | if (neighbourRegion == null) | ||
1051 | return false; | ||
1052 | |||
1053 | m_entityTransferStateMachine.SetInTransit(agent.UUID); | ||
1054 | |||
1055 | agent.RemoveFromPhysicalScene(); | ||
1056 | |||
1057 | return true; | ||
1058 | } | ||
1059 | |||
1042 | /// <summary> | 1060 | /// <summary> |
1043 | /// This Closes child agents on neighbouring regions | 1061 | /// This Closes child agents on neighbouring regions |
1044 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 1062 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
1045 | /// </summary> | 1063 | /// </summary> |
1046 | public ScenePresence CrossAgentToNewRegionAsync( | 1064 | public ScenePresence CrossAgentToNewRegionAsync( |
1047 | ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, | 1065 | ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, |
1048 | bool isFlying, string version) | 1066 | bool isFlying, string version) |
1049 | { | 1067 | { |
1050 | if (neighbourRegion == null) | 1068 | if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) |
1051 | return agent; | 1069 | return agent; |
1052 | 1070 | ||
1053 | try | 1071 | if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) |
1054 | { | 1072 | return agent; |
1055 | m_entityTransferStateMachine.SetInTransit(agent.UUID); | ||
1056 | |||
1057 | ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); | ||
1058 | |||
1059 | m_log.DebugFormat( | ||
1060 | "[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", | ||
1061 | agent.Firstname, agent.Lastname, neighbourx, neighboury, version); | ||
1062 | |||
1063 | Scene m_scene = agent.Scene; | ||
1064 | |||
1065 | if (!agent.ValidateAttachments()) | ||
1066 | m_log.DebugFormat( | ||
1067 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", | ||
1068 | agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); | ||
1069 | |||
1070 | pos = pos + agent.Velocity; | ||
1071 | Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); | ||
1072 | 1073 | ||
1073 | agent.RemoveFromPhysicalScene(); | 1074 | CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); |
1075 | return agent; | ||
1076 | } | ||
1074 | 1077 | ||
1078 | public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) | ||
1079 | { | ||
1080 | try | ||
1081 | { | ||
1075 | AgentData cAgent = new AgentData(); | 1082 | AgentData cAgent = new AgentData(); |
1076 | agent.CopyTo(cAgent); | 1083 | agent.CopyTo(cAgent); |
1077 | cAgent.Position = pos; | 1084 | cAgent.Position = pos + agent.Velocity; |
1078 | if (isFlying) | 1085 | if (isFlying) |
1079 | cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; | 1086 | cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; |
1080 | 1087 | ||
@@ -1084,7 +1091,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1084 | // Beyond this point, extra cleanup is needed beyond removing transit state | 1091 | // Beyond this point, extra cleanup is needed beyond removing transit state |
1085 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); | 1092 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); |
1086 | 1093 | ||
1087 | if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) | 1094 | if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) |
1088 | { | 1095 | { |
1089 | // region doesn't take it | 1096 | // region doesn't take it |
1090 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | 1097 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
@@ -1093,93 +1100,108 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1093 | agent.AddToPhysicalScene(isFlying); | 1100 | agent.AddToPhysicalScene(isFlying); |
1094 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | 1101 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); |
1095 | 1102 | ||
1096 | return agent; | 1103 | return false; |
1097 | } | 1104 | } |
1098 | 1105 | ||
1099 | //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo(); | 1106 | } |
1100 | agent.ControllingClient.RequestClientInfo(); | 1107 | catch (Exception e) |
1108 | { | ||
1109 | m_log.ErrorFormat( | ||
1110 | "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", | ||
1111 | agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); | ||
1112 | |||
1113 | // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. | ||
1114 | return false; | ||
1115 | } | ||
1116 | |||
1117 | return true; | ||
1118 | } | ||
1101 | 1119 | ||
1102 | //m_log.Debug("BEFORE CROSS"); | 1120 | public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, |
1103 | //Scene.DumpChildrenSeeds(UUID); | 1121 | bool isFlying, string version) |
1104 | //DumpKnownRegions(); | 1122 | { |
1105 | string agentcaps; | 1123 | agent.ControllingClient.RequestClientInfo(); |
1106 | if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) | ||
1107 | { | ||
1108 | m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", | ||
1109 | neighbourRegion.RegionHandle); | ||
1110 | return agent; | ||
1111 | } | ||
1112 | // No turning back | ||
1113 | agent.IsChildAgent = true; | ||
1114 | 1124 | ||
1115 | string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); | 1125 | string agentcaps; |
1126 | if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) | ||
1127 | { | ||
1128 | m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", | ||
1129 | neighbourRegion.RegionHandle); | ||
1130 | return; | ||
1131 | } | ||
1116 | 1132 | ||
1117 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); | 1133 | // No turning back |
1134 | agent.IsChildAgent = true; | ||
1118 | 1135 | ||
1119 | if (m_eqModule != null) | 1136 | string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); |
1120 | { | ||
1121 | m_eqModule.CrossRegion( | ||
1122 | neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, | ||
1123 | capsPath, agent.UUID, agent.ControllingClient.SessionId); | ||
1124 | } | ||
1125 | else | ||
1126 | { | ||
1127 | agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, | ||
1128 | capsPath); | ||
1129 | } | ||
1130 | 1137 | ||
1131 | // SUCCESS! | 1138 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); |
1132 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); | ||
1133 | 1139 | ||
1134 | // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. | 1140 | Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); |
1135 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | ||
1136 | 1141 | ||
1137 | agent.MakeChildAgent(); | 1142 | if (m_eqModule != null) |
1143 | { | ||
1144 | m_eqModule.CrossRegion( | ||
1145 | neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, | ||
1146 | capsPath, agent.UUID, agent.ControllingClient.SessionId); | ||
1147 | } | ||
1148 | else | ||
1149 | { | ||
1150 | agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, | ||
1151 | capsPath); | ||
1152 | } | ||
1138 | 1153 | ||
1139 | // FIXME: Possibly this should occur lower down after other commands to close other agents, | 1154 | // SUCCESS! |
1140 | // but not sure yet what the side effects would be. | 1155 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); |
1141 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1142 | 1156 | ||
1143 | // now we have a child agent in this region. Request all interesting data about other (root) agents | 1157 | // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. |
1144 | agent.SendOtherAgentsAvatarDataToMe(); | 1158 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
1145 | agent.SendOtherAgentsAppearanceToMe(); | ||
1146 | 1159 | ||
1147 | // Backwards compatibility. Best effort | 1160 | agent.MakeChildAgent(); |
1148 | if (version == "Unknown" || version == string.Empty) | ||
1149 | { | ||
1150 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); | ||
1151 | Thread.Sleep(3000); // wait a little now that we're not waiting for the callback | ||
1152 | CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); | ||
1153 | } | ||
1154 | 1161 | ||
1155 | // Next, let's close the child agent connections that are too far away. | 1162 | // FIXME: Possibly this should occur lower down after other commands to close other agents, |
1156 | agent.CloseChildAgents(neighbourx, neighboury); | 1163 | // but not sure yet what the side effects would be. |
1164 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1157 | 1165 | ||
1158 | AgentHasMovedAway(agent, false); | 1166 | // now we have a child agent in this region. Request all interesting data about other (root) agents |
1167 | agent.SendOtherAgentsAvatarDataToMe(); | ||
1168 | agent.SendOtherAgentsAppearanceToMe(); | ||
1159 | 1169 | ||
1160 | // the user may change their profile information in other region, | 1170 | // Backwards compatibility. Best effort |
1161 | // so the userinfo in UserProfileCache is not reliable any more, delete it | 1171 | if (version == "Unknown" || version == string.Empty) |
1162 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | ||
1163 | if (agent.Scene.NeedSceneCacheClear(agent.UUID)) | ||
1164 | { | ||
1165 | m_log.DebugFormat( | ||
1166 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); | ||
1167 | } | ||
1168 | |||
1169 | //m_log.Debug("AFTER CROSS"); | ||
1170 | //Scene.DumpChildrenSeeds(UUID); | ||
1171 | //DumpKnownRegions(); | ||
1172 | } | ||
1173 | catch (Exception e) | ||
1174 | { | 1172 | { |
1175 | m_log.ErrorFormat( | 1173 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); |
1176 | "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", | 1174 | Thread.Sleep(3000); // wait a little now that we're not waiting for the callback |
1177 | agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); | 1175 | CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); |
1176 | } | ||
1178 | 1177 | ||
1179 | // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. | 1178 | // Next, let's close the child agent connections that are too far away. |
1179 | uint neighbourx; | ||
1180 | uint neighboury; | ||
1181 | |||
1182 | Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury); | ||
1183 | |||
1184 | neighbourx /= Constants.RegionSize; | ||
1185 | neighboury /= Constants.RegionSize; | ||
1186 | |||
1187 | agent.CloseChildAgents(neighbourx, neighboury); | ||
1188 | |||
1189 | AgentHasMovedAway(agent, false); | ||
1190 | |||
1191 | // the user may change their profile information in other region, | ||
1192 | // so the userinfo in UserProfileCache is not reliable any more, delete it | ||
1193 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | ||
1194 | if (agent.Scene.NeedSceneCacheClear(agent.UUID)) | ||
1195 | { | ||
1196 | m_log.DebugFormat( | ||
1197 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); | ||
1180 | } | 1198 | } |
1181 | 1199 | ||
1182 | return agent; | 1200 | //m_log.Debug("AFTER CROSS"); |
1201 | //Scene.DumpChildrenSeeds(UUID); | ||
1202 | //DumpKnownRegions(); | ||
1203 | |||
1204 | return; | ||
1183 | } | 1205 | } |
1184 | 1206 | ||
1185 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) | 1207 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) |