diff options
author | Melanie | 2012-09-04 03:14:39 +0200 |
---|---|---|
committer | Melanie | 2012-09-04 03:14:39 +0200 |
commit | 056e66b3dec555613bd96b153ba03a124863dbf2 (patch) | |
tree | 83a095370983d9e5d295a5dc539acc2989d3b94b /OpenSim/Region | |
parent | Prevent a nullref if SimStatsReporter tries to report on a sim where psysics are (diff) | |
download | opensim-SC-056e66b3dec555613bd96b153ba03a124863dbf2.zip opensim-SC-056e66b3dec555613bd96b153ba03a124863dbf2.tar.gz opensim-SC-056e66b3dec555613bd96b153ba03a124863dbf2.tar.bz2 opensim-SC-056e66b3dec555613bd96b153ba03a124863dbf2.tar.xz |
Refactor avatar transfer so that the heavy (UpdateAgent) part is separated into
it's own sub-method
Diffstat (limited to 'OpenSim/Region')
3 files changed, 113 insertions, 97 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 9ffb851..1f884c8 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( |
@@ -982,7 +982,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
982 | agent.IsInTransit = true; | 982 | agent.IsInTransit = true; |
983 | 983 | ||
984 | CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; | 984 | CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; |
985 | d.BeginInvoke(agent, newpos, x, y, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); | 985 | d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); |
986 | 986 | ||
987 | return true; | 987 | return true; |
988 | } | 988 | } |
@@ -1039,42 +1039,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1039 | icon.EndInvoke(iar); | 1039 | icon.EndInvoke(iar); |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion) | ||
1043 | { | ||
1044 | if (neighbourRegion == null) | ||
1045 | return false; | ||
1046 | |||
1047 | m_entityTransferStateMachine.SetInTransit(agent.UUID); | ||
1048 | |||
1049 | agent.RemoveFromPhysicalScene(); | ||
1050 | |||
1051 | return true; | ||
1052 | } | ||
1053 | |||
1042 | /// <summary> | 1054 | /// <summary> |
1043 | /// This Closes child agents on neighbouring regions | 1055 | /// This Closes child agents on neighbouring regions |
1044 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 1056 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
1045 | /// </summary> | 1057 | /// </summary> |
1046 | public ScenePresence CrossAgentToNewRegionAsync( | 1058 | public ScenePresence CrossAgentToNewRegionAsync( |
1047 | ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, | 1059 | ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, |
1048 | bool isFlying, string version) | 1060 | bool isFlying, string version) |
1049 | { | 1061 | { |
1050 | if (neighbourRegion == null) | 1062 | if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) |
1051 | return agent; | 1063 | return agent; |
1052 | 1064 | ||
1053 | try | 1065 | if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) |
1054 | { | 1066 | 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 | 1067 | ||
1073 | agent.RemoveFromPhysicalScene(); | 1068 | CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); |
1069 | return agent; | ||
1070 | } | ||
1074 | 1071 | ||
1072 | public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) | ||
1073 | { | ||
1074 | try | ||
1075 | { | ||
1075 | AgentData cAgent = new AgentData(); | 1076 | AgentData cAgent = new AgentData(); |
1076 | agent.CopyTo(cAgent); | 1077 | agent.CopyTo(cAgent); |
1077 | cAgent.Position = pos; | 1078 | cAgent.Position = pos + agent.Velocity; |
1078 | if (isFlying) | 1079 | if (isFlying) |
1079 | cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; | 1080 | cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; |
1080 | 1081 | ||
@@ -1084,7 +1085,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1084 | // Beyond this point, extra cleanup is needed beyond removing transit state | 1085 | // Beyond this point, extra cleanup is needed beyond removing transit state |
1085 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); | 1086 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); |
1086 | 1087 | ||
1087 | if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) | 1088 | if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) |
1088 | { | 1089 | { |
1089 | // region doesn't take it | 1090 | // region doesn't take it |
1090 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | 1091 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
@@ -1093,93 +1094,108 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1093 | agent.AddToPhysicalScene(isFlying); | 1094 | agent.AddToPhysicalScene(isFlying); |
1094 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | 1095 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); |
1095 | 1096 | ||
1096 | return agent; | 1097 | return false; |
1097 | } | 1098 | } |
1098 | 1099 | ||
1099 | //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo(); | 1100 | } |
1100 | agent.ControllingClient.RequestClientInfo(); | 1101 | catch (Exception e) |
1102 | { | ||
1103 | m_log.ErrorFormat( | ||
1104 | "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", | ||
1105 | agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); | ||
1101 | 1106 | ||
1102 | //m_log.Debug("BEFORE CROSS"); | 1107 | // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. |
1103 | //Scene.DumpChildrenSeeds(UUID); | 1108 | return false; |
1104 | //DumpKnownRegions(); | 1109 | } |
1105 | string agentcaps; | ||
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 | 1110 | ||
1115 | string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); | 1111 | return true; |
1112 | } | ||
1116 | 1113 | ||
1117 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); | 1114 | public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, |
1115 | bool isFlying, string version) | ||
1116 | { | ||
1117 | agent.ControllingClient.RequestClientInfo(); | ||
1118 | 1118 | ||
1119 | if (m_eqModule != null) | 1119 | string agentcaps; |
1120 | { | 1120 | if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) |
1121 | m_eqModule.CrossRegion( | 1121 | { |
1122 | neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, | 1122 | m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", |
1123 | capsPath, agent.UUID, agent.ControllingClient.SessionId); | 1123 | neighbourRegion.RegionHandle); |
1124 | } | 1124 | return; |
1125 | else | 1125 | } |
1126 | { | ||
1127 | agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, | ||
1128 | capsPath); | ||
1129 | } | ||
1130 | 1126 | ||
1131 | // SUCCESS! | 1127 | // No turning back |
1132 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); | 1128 | agent.IsChildAgent = true; |
1133 | 1129 | ||
1134 | // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. | 1130 | string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); |
1135 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | ||
1136 | 1131 | ||
1137 | agent.MakeChildAgent(); | 1132 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); |
1138 | 1133 | ||
1139 | // FIXME: Possibly this should occur lower down after other commands to close other agents, | 1134 | Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); |
1140 | // but not sure yet what the side effects would be. | ||
1141 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1142 | 1135 | ||
1143 | // now we have a child agent in this region. Request all interesting data about other (root) agents | 1136 | if (m_eqModule != null) |
1144 | agent.SendOtherAgentsAvatarDataToMe(); | 1137 | { |
1145 | agent.SendOtherAgentsAppearanceToMe(); | 1138 | m_eqModule.CrossRegion( |
1139 | neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, | ||
1140 | capsPath, agent.UUID, agent.ControllingClient.SessionId); | ||
1141 | } | ||
1142 | else | ||
1143 | { | ||
1144 | agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, | ||
1145 | capsPath); | ||
1146 | } | ||
1146 | 1147 | ||
1147 | // Backwards compatibility. Best effort | 1148 | // SUCCESS! |
1148 | if (version == "Unknown" || version == string.Empty) | 1149 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); |
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 | 1150 | ||
1155 | // Next, let's close the child agent connections that are too far away. | 1151 | // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. |
1156 | agent.CloseChildAgents(neighbourx, neighboury); | 1152 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
1157 | 1153 | ||
1158 | AgentHasMovedAway(agent, false); | 1154 | agent.MakeChildAgent(); |
1159 | 1155 | ||
1160 | // the user may change their profile information in other region, | 1156 | // FIXME: Possibly this should occur lower down after other commands to close other agents, |
1161 | // so the userinfo in UserProfileCache is not reliable any more, delete it | 1157 | // but not sure yet what the side effects would be. |
1162 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | 1158 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); |
1163 | if (agent.Scene.NeedSceneCacheClear(agent.UUID)) | 1159 | |
1164 | { | 1160 | // now we have a child agent in this region. Request all interesting data about other (root) agents |
1165 | m_log.DebugFormat( | 1161 | agent.SendOtherAgentsAvatarDataToMe(); |
1166 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); | 1162 | agent.SendOtherAgentsAppearanceToMe(); |
1167 | } | 1163 | |
1168 | 1164 | // Backwards compatibility. Best effort | |
1169 | //m_log.Debug("AFTER CROSS"); | 1165 | if (version == "Unknown" || version == string.Empty) |
1170 | //Scene.DumpChildrenSeeds(UUID); | ||
1171 | //DumpKnownRegions(); | ||
1172 | } | ||
1173 | catch (Exception e) | ||
1174 | { | 1166 | { |
1175 | m_log.ErrorFormat( | 1167 | 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}", | 1168 | 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); | 1169 | CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); |
1170 | } | ||
1178 | 1171 | ||
1179 | // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. | 1172 | // Next, let's close the child agent connections that are too far away. |
1173 | uint neighbourx; | ||
1174 | uint neighboury; | ||
1175 | |||
1176 | Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury); | ||
1177 | |||
1178 | neighbourx /= Constants.RegionSize; | ||
1179 | neighboury /= Constants.RegionSize; | ||
1180 | |||
1181 | agent.CloseChildAgents(neighbourx, neighboury); | ||
1182 | |||
1183 | AgentHasMovedAway(agent, false); | ||
1184 | |||
1185 | // the user may change their profile information in other region, | ||
1186 | // so the userinfo in UserProfileCache is not reliable any more, delete it | ||
1187 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | ||
1188 | if (agent.Scene.NeedSceneCacheClear(agent.UUID)) | ||
1189 | { | ||
1190 | m_log.DebugFormat( | ||
1191 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); | ||
1180 | } | 1192 | } |
1181 | 1193 | ||
1182 | return agent; | 1194 | //m_log.Debug("AFTER CROSS"); |
1195 | //Scene.DumpChildrenSeeds(UUID); | ||
1196 | //DumpKnownRegions(); | ||
1197 | |||
1198 | return; | ||
1183 | } | 1199 | } |
1184 | 1200 | ||
1185 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) | 1201 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) |
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 5bc8e51..1949a90 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs | |||
@@ -35,7 +35,7 @@ using OpenSim.Region.Framework.Scenes; | |||
35 | 35 | ||
36 | namespace OpenSim.Region.Framework.Interfaces | 36 | namespace OpenSim.Region.Framework.Interfaces |
37 | { | 37 | { |
38 | public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); | 38 | public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); |
39 | 39 | ||
40 | public interface IEntityTransferModule | 40 | public interface IEntityTransferModule |
41 | { | 41 | { |
@@ -76,7 +76,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
76 | 76 | ||
77 | void Cross(SceneObjectGroup sog, Vector3 position, bool silent); | 77 | void Cross(SceneObjectGroup sog, Vector3 position, bool silent); |
78 | 78 | ||
79 | ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); | 79 | ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); |
80 | 80 | ||
81 | } | 81 | } |
82 | 82 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index bc0f5b6..4798481 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -581,7 +581,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
581 | av.IsInTransit = true; | 581 | av.IsInTransit = true; |
582 | 582 | ||
583 | CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | 583 | CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; |
584 | d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | 584 | d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); |
585 | } | 585 | } |
586 | else | 586 | else |
587 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); | 587 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); |