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/Animation/AnimationSet.cs114
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs66
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs185
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs823
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs49
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs192
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs738
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs90
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs175
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs167
32 files changed, 2740 insertions, 896 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index 66edfed..b7400ea 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -28,8 +28,11 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Text;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35
33using OpenSim.Framework; 36using OpenSim.Framework;
34 37
35using Animation = OpenSim.Framework.Animation; 38using Animation = OpenSim.Framework.Animation;
@@ -60,6 +63,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
60 ResetDefaultAnimation(); 63 ResetDefaultAnimation();
61 } 64 }
62 65
66 public AnimationSet(OSDArray pArray)
67 {
68 ResetDefaultAnimation();
69 FromOSDArray(pArray);
70 }
71
63 public bool HasAnimation(UUID animID) 72 public bool HasAnimation(UUID animID)
64 { 73 {
65 if (m_defaultAnimation.AnimID == animID) 74 if (m_defaultAnimation.AnimID == animID)
@@ -218,5 +227,110 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 foreach (OpenSim.Framework.Animation anim in theArray) 227 foreach (OpenSim.Framework.Animation anim in theArray)
219 m_animations.Add(anim); 228 m_animations.Add(anim);
220 } 229 }
230
231 // Create representation of this AnimationSet as an OSDArray.
232 // First two entries in the array are the default and implicitDefault animations
233 // followed by the other animations.
234 public OSDArray ToOSDArray()
235 {
236 OSDArray ret = new OSDArray();
237 ret.Add(DefaultAnimation.PackUpdateMessage());
238 ret.Add(ImplicitDefaultAnimation.PackUpdateMessage());
239
240 foreach (OpenSim.Framework.Animation anim in m_animations)
241 ret.Add(anim.PackUpdateMessage());
242
243 return ret;
244 }
245
246 public void FromOSDArray(OSDArray pArray)
247 {
248 this.Clear();
249
250 if (pArray.Count >= 1)
251 {
252 m_defaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[0]);
253 }
254 if (pArray.Count >= 2)
255 {
256 m_implicitDefaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[1]);
257 }
258 for (int ii = 2; ii < pArray.Count; ii++)
259 {
260 m_animations.Add(new OpenSim.Framework.Animation((OSDMap)pArray[ii]));
261 }
262 }
263
264 // Compare two AnimationSets and return 'true' if the default animations are the same
265 // and all of the animations in the list are equal.
266 public override bool Equals(object obj)
267 {
268 AnimationSet other = obj as AnimationSet;
269 if (other != null)
270 {
271 if (this.DefaultAnimation.Equals(other.DefaultAnimation)
272 && this.ImplicitDefaultAnimation.Equals(other.ImplicitDefaultAnimation))
273 {
274 // The defaults are the same. Is the list of animations the same?
275 OpenSim.Framework.Animation[] thisAnims = this.ToArray();
276 OpenSim.Framework.Animation[] otherAnims = other.ToArray();
277 if (thisAnims.Length == 0 && otherAnims.Length == 0)
278 return true; // the common case
279 if (thisAnims.Length == otherAnims.Length)
280 {
281 // Do this the hard way but since the list is usually short this won't take long.
282 foreach (OpenSim.Framework.Animation thisAnim in thisAnims)
283 {
284 bool found = false;
285 foreach (OpenSim.Framework.Animation otherAnim in otherAnims)
286 {
287 if (thisAnim.Equals(otherAnim))
288 {
289 found = true;
290 break;
291 }
292 }
293 if (!found)
294 {
295 // If anything is not in the other list, these are not equal
296 return false;
297 }
298 }
299 // Found everything in the other list. Since lists are equal length, they must be equal.
300 return true;
301 }
302 }
303 return false;
304 }
305 // Don't know what was passed, but the base system will figure it out for me.
306 return base.Equals(obj);
307 }
308
309 public override string ToString()
310 {
311 StringBuilder buff = new StringBuilder();
312 buff.Append("dflt=");
313 buff.Append(DefaultAnimation.ToString());
314 buff.Append(",iDflt=");
315 if (DefaultAnimation.Equals(ImplicitDefaultAnimation))
316 buff.Append("same");
317 else
318 buff.Append(ImplicitDefaultAnimation.ToString());
319 if (m_animations.Count > 0)
320 {
321 buff.Append(",anims=");
322 bool firstTime = true;
323 foreach (OpenSim.Framework.Animation anim in m_animations)
324 {
325 if (!firstTime)
326 buff.Append(",");
327 buff.Append("<");
328 buff.Append(anim.ToString());
329 buff.Append(">");
330 firstTime = false;
331 }
332 }
333 return buff.ToString();
334 }
221 } 335 }
222} 336}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
index c2b0468..b79dd8f 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
@@ -104,5 +104,31 @@ namespace OpenSim.Region.Framework.Scenes.Animation
104 104
105 return UUID.Zero; 105 return UUID.Zero;
106 } 106 }
107
108 /// <summary>
109 /// Get the name of the animation given a UUID. If there is no matching animation
110 /// return the UUID as a string.
111 /// </summary>
112 public static string GetDefaultAnimationName(UUID uuid)
113 {
114 string ret = "unknown";
115 if (AnimsUUID.ContainsValue(uuid))
116 {
117 foreach (KeyValuePair<string, UUID> kvp in AnimsUUID)
118 {
119 if (kvp.Value == uuid)
120 {
121 ret = kvp.Key;
122 break;
123 }
124 }
125 }
126 else
127 {
128 ret = uuid.ToString();
129 }
130
131 return ret;
132 }
107 } 133 }
108} \ No newline at end of file 134} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 65c279e..c1394aa 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -93,7 +93,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
93 GetAnimName(animID), animID, m_scenePresence.Name); 93 GetAnimName(animID), animID, m_scenePresence.Name);
94 94
95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
96 {
96 SendAnimPack(); 97 SendAnimPack();
98 m_scenePresence.TriggerScenePresenceUpdated();
99 }
97 } 100 }
98 101
99 // Called from scripts 102 // Called from scripts
@@ -132,7 +135,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
132 GetAnimName(animID), animID, m_scenePresence.Name); 135 GetAnimName(animID), animID, m_scenePresence.Name);
133 136
134 if (m_animations.Remove(animID, allowNoDefault)) 137 if (m_animations.Remove(animID, allowNoDefault))
138 {
135 SendAnimPack(); 139 SendAnimPack();
140 m_scenePresence.TriggerScenePresenceUpdated();
141 }
136 } 142 }
137 143
138 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) 144 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
@@ -180,8 +186,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
180 /// The movement animation is reserved for "main" animations 186 /// The movement animation is reserved for "main" animations
181 /// that are mutually exclusive, e.g. flying and sitting. 187 /// that are mutually exclusive, e.g. flying and sitting.
182 /// </summary> 188 /// </summary>
183 public void TrySetMovementAnimation(string anim) 189 /// <returns>'true' if the animation was updated</returns>
190 public bool TrySetMovementAnimation(string anim)
184 { 191 {
192 bool ret = false;
185 if (!m_scenePresence.IsChildAgent) 193 if (!m_scenePresence.IsChildAgent)
186 { 194 {
187// m_log.DebugFormat( 195// m_log.DebugFormat(
@@ -198,6 +206,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
198 // 16384 is CHANGED_ANIMATION 206 // 16384 is CHANGED_ANIMATION
199 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 207 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION});
200 SendAnimPack(); 208 SendAnimPack();
209 ret = true;
201 } 210 }
202 } 211 }
203 else 212 else
@@ -206,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
206 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", 215 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
207 anim, m_scenePresence.Name); 216 anim, m_scenePresence.Name);
208 } 217 }
218 return ret;
209 } 219 }
210 220
211 /// <summary> 221 /// <summary>
@@ -410,11 +420,18 @@ namespace OpenSim.Region.Framework.Scenes.Animation
410 Falling = false; 420 Falling = false;
411 // Walking / crouchwalking / running 421 // Walking / crouchwalking / running
412 if (move.Z < 0f) 422 if (move.Z < 0f)
423 {
413 return "CROUCHWALK"; 424 return "CROUCHWALK";
414 else if (m_scenePresence.SetAlwaysRun) 425 }
415 return "RUN"; 426 // We need to prevent these animations if the user tries to make their avatar walk or run whilst
416 else 427 // specifying AGENT_CONTROL_STOP (pressing down space on viewers).
417 return "WALK"; 428 else if (!m_scenePresence.AgentControlStopActive)
429 {
430 if (m_scenePresence.SetAlwaysRun)
431 return "RUN";
432 else
433 return "WALK";
434 }
418 } 435 }
419 else if (!m_jumping) 436 else if (!m_jumping)
420 { 437 {
@@ -439,8 +456,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
439 /// <summary> 456 /// <summary>
440 /// Update the movement animation of this avatar according to its current state 457 /// Update the movement animation of this avatar according to its current state
441 /// </summary> 458 /// </summary>
442 public void UpdateMovementAnimations() 459 /// <returns>'true' if the animation was changed</returns>
460 public bool UpdateMovementAnimations()
443 { 461 {
462// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
463
464 bool ret = false;
444 lock (m_animations) 465 lock (m_animations)
445 { 466 {
446 string newMovementAnimation = DetermineMovementAnimation(); 467 string newMovementAnimation = DetermineMovementAnimation();
@@ -454,9 +475,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
454 475
455 // Only set it if it's actually changed, give a script 476 // Only set it if it's actually changed, give a script
456 // a chance to stop a default animation 477 // a chance to stop a default animation
457 TrySetMovementAnimation(CurrentMovementAnimation); 478 ret = TrySetMovementAnimation(CurrentMovementAnimation);
458 } 479 }
459 } 480 }
481 return ret;
460 } 482 }
461 483
462 public UUID[] GetAnimationArray() 484 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index f555b49..11a0146 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
109 foreach (SceneObjectGroup g in objectGroups) 107 foreach (SceneObjectGroup g in objectGroups)
110 { killIDs.Add(g.LocalId); 108 g.DeleteGroupFromScene(false);
111 g.DeleteGroupFromScene(true);
112 }
113
114 m_scene.SendKillObject(killIDs);
115 } 109 }
116 } 110 }
117 111
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
160 if (x.permissionToDelete) 154 if (x.permissionToDelete)
161 { 155 {
162 foreach (SceneObjectGroup g in x.objectGroups) 156 foreach (SceneObjectGroup g in x.objectGroups)
163 m_scene.DeleteSceneObject(g, false); 157 m_scene.DeleteSceneObject(g, true);
164 } 158 }
165 } 159 }
166 catch (Exception e) 160 catch (Exception e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 4733547..7f06e82 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes
148 /// Triggered when a new presence is added to the scene 148 /// Triggered when a new presence is added to the scene
149 /// </summary> 149 /// </summary>
150 /// <remarks> 150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks> 153 /// </remarks>
154 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
@@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes
159 /// Triggered when a presence is removed from the scene 159 /// Triggered when a presence is removed from the scene
160 /// </summary> 160 /// </summary>
161 /// <remarks> 161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 /// 164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please 165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
@@ -743,7 +743,7 @@ namespace OpenSim.Region.Framework.Scenes
743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; 743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject;
744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); 744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so);
745 745
746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel);
747 747
748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; 748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
749 749
@@ -974,6 +974,8 @@ namespace OpenSim.Region.Framework.Scenes
974 public delegate void RegionStarted(Scene scene); 974 public delegate void RegionStarted(Scene scene);
975 public event RegionStarted OnRegionStarted; 975 public event RegionStarted OnRegionStarted;
976 976
977 public delegate void RegionHeartbeatStart(Scene scene);
978 public event RegionHeartbeatStart OnRegionHeartbeatStart;
977 public delegate void RegionHeartbeatEnd(Scene scene); 979 public delegate void RegionHeartbeatEnd(Scene scene);
978 public event RegionHeartbeatEnd OnRegionHeartbeatEnd; 980 public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
979 981
@@ -1024,6 +1026,16 @@ namespace OpenSim.Region.Framework.Scenes
1024 /// </remarks> 1026 /// </remarks>
1025 public event TeleportFail OnTeleportFail; 1027 public event TeleportFail OnTeleportFail;
1026 1028
1029// public delegate void GatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids);
1030//
1031// /// <summary>
1032// /// Triggered when UUIDs referenced by a scene object are being gathered for archiving, hg transfer, etc.
1033// /// </summary>
1034// /// <remarks>
1035// /// The listener should add references to the IDictionary<UUID, AssetType> as appropriate.
1036// /// </remarks>
1037// public event GatherUuids OnGatherUuids;
1038
1027 public class MoneyTransferArgs : EventArgs 1039 public class MoneyTransferArgs : EventArgs
1028 { 1040 {
1029 public UUID sender; 1041 public UUID sender;
@@ -1095,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
1095 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> 1107 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1096 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> 1108 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1097 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> 1109 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1098 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> 1110 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/>
1099 /// </remarks> 1111 /// </remarks>
1100 public event MoneyTransferEvent OnMoneyTransfer; 1112 public event MoneyTransferEvent OnMoneyTransfer;
1101 1113
@@ -2160,7 +2172,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 } 2172 }
2161 } 2173 }
2162 2174
2163 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) 2175 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel)
2164 { 2176 {
2165 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2177 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2166 if (handlerNewInventoryItemUpdateComplete != null) 2178 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2169,7 +2181,7 @@ namespace OpenSim.Region.Framework.Scenes
2169 { 2181 {
2170 try 2182 try
2171 { 2183 {
2172 d(agentID, AssetID, AssetName, userlevel); 2184 d(agentID, type, AssetID, AssetName, userlevel);
2173 } 2185 }
2174 catch (Exception e) 2186 catch (Exception e)
2175 { 2187 {
@@ -3096,6 +3108,27 @@ namespace OpenSim.Region.Framework.Scenes
3096 } 3108 }
3097 } 3109 }
3098 3110
3111 public void TriggerRegionHeartbeatStart(Scene scene)
3112 {
3113 RegionHeartbeatStart handler = OnRegionHeartbeatStart;
3114
3115 if (handler != null)
3116 {
3117 foreach (RegionHeartbeatStart d in handler.GetInvocationList())
3118 {
3119 try
3120 {
3121 d(scene);
3122 }
3123 catch (Exception e)
3124 {
3125 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}",
3126 e.Message, e.StackTrace);
3127 }
3128 }
3129 }
3130 }
3131
3099 public void TriggerRegionHeartbeatEnd(Scene scene) 3132 public void TriggerRegionHeartbeatEnd(Scene scene)
3100 { 3133 {
3101 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; 3134 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd;
@@ -3251,5 +3284,26 @@ namespace OpenSim.Region.Framework.Scenes
3251 handler(scenePresence); 3284 handler(scenePresence);
3252 } 3285 }
3253 } 3286 }
3287
3288// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3289// {
3290// GatherUuids handler = OnGatherUuids;
3291//
3292// if (handler != null)
3293// {
3294// foreach (GatherUuids d in handler.GetInvocationList())
3295// {
3296// try
3297// {
3298// d(sop, assetUuids);
3299// }
3300// catch (Exception e)
3301// {
3302// m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}",
3303// e.Message, e.StackTrace);
3304// }
3305// }
3306// }
3307// }
3254 } 3308 }
3255} 3309}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 276b61f..4d153da 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -1,6 +1,29 @@
1// Proprietary code of Avination Virtual Limited 1/*
2// (c) 2012 Melanie Thielker 2 * Copyright (c) Contributors, http://opensimulator.org/
3// 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
4 27
5using System; 28using System;
6using System.Timers; 29using System.Timers;
@@ -32,7 +55,6 @@ namespace OpenSim.Region.Framework.Scenes
32 private object m_lockObject = new object(); 55 private object m_lockObject = new object();
33 private object m_timerLock = new object(); 56 private object m_timerLock = new object();
34 private const double m_tickDuration = 50.0; 57 private const double m_tickDuration = 50.0;
35 private Scene m_scene;
36 58
37 public double TickDuration 59 public double TickDuration
38 { 60 {
@@ -46,8 +68,6 @@ namespace OpenSim.Region.Framework.Scenes
46 m_timer.AutoReset = true; 68 m_timer.AutoReset = true;
47 m_timer.Elapsed += OnTimer; 69 m_timer.Elapsed += OnTimer;
48 70
49 m_scene = scene;
50
51 m_timer.Start(); 71 m_timer.Start();
52 } 72 }
53 73
@@ -71,13 +91,13 @@ namespace OpenSim.Region.Framework.Scenes
71 { 91 {
72 m.OnTimer(TickDuration); 92 m.OnTimer(TickDuration);
73 } 93 }
74 catch (Exception inner) 94 catch (Exception)
75 { 95 {
76 // Don't stop processing 96 // Don't stop processing
77 } 97 }
78 } 98 }
79 } 99 }
80 catch (Exception e) 100 catch (Exception)
81 { 101 {
82 // Keep running no matter what 102 // Keep running no matter what
83 } 103 }
@@ -134,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
134 [Serializable] 154 [Serializable]
135 public class KeyframeMotion 155 public class KeyframeMotion
136 { 156 {
137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 157// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
138 158
139 public enum PlayMode : int 159 public enum PlayMode : int
140 { 160 {
@@ -478,6 +498,7 @@ namespace OpenSim.Region.Framework.Scenes
478 k.Position = pos; 498 k.Position = pos;
479// k.Velocity = Vector3.Zero; 499// k.Velocity = Vector3.Zero;
480 } 500 }
501 k.AngularVelocity = (Vector3)k.Position;
481 502
482 k.StartRotation = rot; 503 k.StartRotation = rot;
483 if (k.Rotation.HasValue) 504 if (k.Rotation.HasValue)
@@ -618,7 +639,7 @@ namespace OpenSim.Region.Framework.Scenes
618 m_group.RootPart.Velocity = Vector3.Zero; 639 m_group.RootPart.Velocity = Vector3.Zero;
619 m_group.RootPart.AngularVelocity = Vector3.Zero; 640 m_group.RootPart.AngularVelocity = Vector3.Zero;
620 641
621 m_nextPosition = (Vector3)m_currentFrame.Position; 642 m_nextPosition = NormalizeVector(m_currentFrame.AngularVelocity);
622 m_group.AbsolutePosition = m_nextPosition; 643 m_group.AbsolutePosition = m_nextPosition;
623 644
624 // we are sending imediate updates, no doing force a extra terseUpdate 645 // we are sending imediate updates, no doing force a extra terseUpdate
@@ -706,7 +727,26 @@ namespace OpenSim.Region.Framework.Scenes
706 m_group.SendGroupRootTerseUpdate(); 727 m_group.SendGroupRootTerseUpdate();
707 } 728 }
708 } 729 }
730 private Vector3 NormalizeVector(Vector3? pPosition)
731 {
732 if (pPosition == null)
733 return Vector3.Zero;
734
735 Vector3 tmp = (Vector3) pPosition;
709 736
737 while (tmp.X > Constants.RegionSize)
738 tmp.X -= Constants.RegionSize;
739 while (tmp.X < 0)
740 tmp.X += Constants.RegionSize;
741 while (tmp.Y > Constants.RegionSize)
742 tmp.Y -= Constants.RegionSize;
743 while (tmp.Y < 0)
744 tmp.Y += Constants.RegionSize;
745
746 return tmp;
747
748
749 }
710 public Byte[] Serialize() 750 public Byte[] Serialize()
711 { 751 {
712 StopTimer(); 752 StopTimer();
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index c11174d..f208afb 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -46,47 +46,33 @@ using OpenSim.Region.Framework.Scenes;
46 46
47namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
48{ 48{
49 public class RegionStatsHandler : IStreamedRequestHandler 49 public class RegionStatsHandler : BaseStreamHandler
50 { 50 {
51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private string osRXStatsURI = String.Empty;
54 private string osXStatsURI = String.Empty; 53 private string osXStatsURI = String.Empty;
55 //private string osSecret = String.Empty; 54 //private string osSecret = String.Empty;
56 private OpenSim.Framework.RegionInfo regionInfo; 55 private OpenSim.Framework.RegionInfo regionInfo;
57 public string localZone = TimeZone.CurrentTimeZone.StandardName; 56 public string localZone = TimeZone.CurrentTimeZone.StandardName;
58 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 57 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
59 58
60 public string Name { get { return "RegionStats"; } } 59 public RegionStatsHandler(RegionInfo region_info)
61 public string Description { get { return "Region Statistics"; } } 60 : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics")
62
63 public RegionStatsHandler(RegionInfo region_info)
64 { 61 {
65 regionInfo = region_info; 62 regionInfo = region_info;
66 osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret);
67 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); 63 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret);
68 } 64 }
69 65
70 public byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 protected override byte[] ProcessRequest(
67 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
71 { 68 {
72 return Util.UTF8.GetBytes(Report()); 69 return Util.UTF8.GetBytes(Report());
73 } 70 }
74 71
75 public string ContentType 72 public override string ContentType
76 { 73 {
77 get { return "text/plain"; } 74 get { return "text/plain"; }
78 } 75 }
79
80 public string HttpMethod
81 {
82 get { return "GET"; }
83 }
84
85 public string Path
86 {
87 // This is for the region and is the regionSecret hashed
88 get { return "/" + osRXStatsURI; }
89 }
90 76
91 private string Report() 77 private string Report()
92 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index d2e41f8..cba75f1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -139,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
139 { 140 {
140 userlevel = 1; 141 userlevel = 1;
141 } 142 }
142 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 143 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
143 144
144 return true; 145 return true;
145 } 146 }
@@ -178,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
178 { 179 {
179 userlevel = 1; 180 userlevel = 1;
180 } 181 }
181 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 182 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
182 183
183 if (originalFolder != UUID.Zero) 184 if (originalFolder != UUID.Zero)
184 { 185 {
@@ -411,19 +412,21 @@ namespace OpenSim.Region.Framework.Scenes
411// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, 412// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
412// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); 413// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
413 414
415 bool sendUpdate = false;
416
414 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid 417 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
415 { 418 {
416 // Create a set of base permissions that will not include export if the user 419 // Create a set of base permissions that will not include export if the user
417 // is not allowed to change the export flag. 420 // is not allowed to change the export flag.
418 bool denyExportChange = false; 421 bool denyExportChange = false;
419 422
420 m_log.InfoFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); 423// m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions);
421 424
422 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export 425 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export
423 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) 426 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner)
424 denyExportChange = true; 427 denyExportChange = true;
425 428
426 m_log.InfoFormat("[XXX]: Deny Export Update {0}", denyExportChange); 429// m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange);
427 430
428 // If it is already set, force it set and also force full perm 431 // If it is already set, force it set and also force full perm
429 // else prevent setting it. It can and should never be set unless 432 // else prevent setting it. It can and should never be set unless
@@ -447,7 +450,7 @@ namespace OpenSim.Region.Framework.Scenes
447 // If the new state is exportable, force full perm 450 // If the new state is exportable, force full perm
448 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) 451 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
449 { 452 {
450 m_log.InfoFormat("[XXX]: Force full perm"); 453// m_log.DebugFormat("[XXX]: Force full perm");
451 itemUpd.NextPermissions = (uint)(PermissionMask.All); 454 itemUpd.NextPermissions = (uint)(PermissionMask.All);
452 } 455 }
453 } 456 }
@@ -484,8 +487,13 @@ namespace OpenSim.Region.Framework.Scenes
484 item.SalePrice = itemUpd.SalePrice; 487 item.SalePrice = itemUpd.SalePrice;
485 item.SaleType = itemUpd.SaleType; 488 item.SaleType = itemUpd.SaleType;
486 489
490 if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0)
491 {
492 item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf);
493 sendUpdate = true;
494 }
495
487 InventoryService.UpdateItem(item); 496 InventoryService.UpdateItem(item);
488 remoteClient.SendBulkUpdateInventory(item);
489 } 497 }
490 498
491 if (UUID.Zero != transactionID) 499 if (UUID.Zero != transactionID)
@@ -495,6 +503,17 @@ namespace OpenSim.Region.Framework.Scenes
495 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); 503 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
496 } 504 }
497 } 505 }
506 else
507 {
508 // This MAY be problematic, if it is, another solution
509 // needs to be found. If inventory item flags are updated
510 // the viewer's notion of the item needs to be refreshed.
511 //
512 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
513 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
514 if (sendUpdate)
515 remoteClient.SendBulkUpdateInventory(item);
516 }
498 } 517 }
499 else 518 else
500 { 519 {
@@ -548,6 +567,9 @@ namespace OpenSim.Region.Framework.Scenes
548 { 567 {
549 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); 568 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
550 569
570 if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
571 return null;
572
551 InventoryItemBase item = new InventoryItemBase(itemId, senderId); 573 InventoryItemBase item = new InventoryItemBase(itemId, senderId);
552 item = InventoryService.GetItem(item); 574 item = InventoryService.GetItem(item);
553 575
@@ -642,17 +664,13 @@ namespace OpenSim.Region.Framework.Scenes
642 // a mask 664 // a mask
643 if (item.InvType == (int)InventoryType.Object) 665 if (item.InvType == (int)InventoryType.Object)
644 { 666 {
645 // Create a safe mask for the current perms
646 uint foldedPerms = (item.CurrentPermissions & 7) << 13;
647 foldedPerms |= permsMask;
648
649 bool isRootMod = (item.CurrentPermissions & 667 bool isRootMod = (item.CurrentPermissions &
650 (uint)PermissionMask.Modify) != 0 ? 668 (uint)PermissionMask.Modify) != 0 ?
651 true : false; 669 true : false;
652 670
653 // Mask the owner perms to the folded perms 671 // Mask the owner perms to the folded perms
654 ownerPerms &= foldedPerms; 672 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms);
655 basePerms &= foldedPerms; 673 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms);
656 674
657 // If the root was mod, let the mask reflect that 675 // If the root was mod, let the mask reflect that
658 // We also need to adjust the base here, because 676 // We also need to adjust the base here, because
@@ -1213,9 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes
1213 { 1231 {
1214 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); 1232 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1215 if (taskItem.InvType == (int)InventoryType.Object) 1233 if (taskItem.InvType == (int)InventoryType.Object)
1216 agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); 1234 {
1235 uint perms = taskItem.CurrentPermissions;
1236 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
1237 agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1238 agentItem.CurrentPermissions = agentItem.BasePermissions;
1239 }
1217 else 1240 else
1241 {
1218 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; 1242 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
1243 }
1219 1244
1220 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 1245 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1221 agentItem.NextPermissions = taskItem.NextPermissions; 1246 agentItem.NextPermissions = taskItem.NextPermissions;
@@ -2124,7 +2149,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2149 {
2125 // If we don't have permission, stop right here 2150 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2151 if (!permissionToTakeCopy)
2152 {
2153 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2154 return;
2155 }
2128 2156
2129 permissionToTake = true; 2157 permissionToTake = true;
2130 // Don't delete 2158 // Don't delete
@@ -2277,6 +2305,85 @@ namespace OpenSim.Region.Framework.Scenes
2277 } 2305 }
2278 2306
2279 /// <summary> 2307 /// <summary>
2308 /// Returns the list of Scene Objects in an asset.
2309 /// </summary>
2310 /// <remarks>
2311 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2312 /// </remarks>
2313 /// <param name="assetData">Asset data</param>
2314 /// <param name="attachment">Whether the item is an attachment</param>
2315 /// <param name="objlist">The objects included in the asset</param>
2316 /// <param name="veclist">Relative positions of the objects</param>
2317 /// <param name="bbox">Bounding box of all the objects</param>
2318 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2319 /// to the centre of the root prim (relevant only when returning a single object)</param>
2320 /// <returns>true = returning a single object; false = multiple objects</returns>
2321 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2322 out Vector3 bbox, out float offsetHeight)
2323 {
2324 objlist = new List<SceneObjectGroup>();
2325 veclist = new List<Vector3>();
2326
2327 XmlDocument doc = new XmlDocument();
2328 string xmlData = Utils.BytesToString(assetData);
2329 doc.LoadXml(xmlData);
2330 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2331
2332 if (e == null || attachment) // Single
2333 {
2334 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2335
2336 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2337 g.RootPart.AttachOffset = g.AbsolutePosition;
2338 g.RootPart.AttachRotation = g.GroupRotation;
2339 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2340 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2341 g.RootPart.Shape.State = 0;
2342
2343 objlist.Add(g);
2344 veclist.Add(new Vector3(0, 0, 0));
2345 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2346 return true;
2347 }
2348 else
2349 {
2350 XmlElement coll = (XmlElement)e;
2351 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2352 float by = Convert.ToSingle(coll.GetAttribute("y"));
2353 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2354 bbox = new Vector3(bx, by, bz);
2355 offsetHeight = 0;
2356
2357 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2358 foreach (XmlNode n in groups)
2359 {
2360 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2361
2362 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2363 g.RootPart.AttachOffset = g.AbsolutePosition;
2364 g.RootPart.AttachRotation = g.GroupRotation;
2365 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2366 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2367 g.RootPart.Shape.State = 0;
2368
2369 objlist.Add(g);
2370
2371 XmlElement el = (XmlElement)n;
2372 string rawX = el.GetAttribute("offsetx");
2373 string rawY = el.GetAttribute("offsety");
2374 string rawZ = el.GetAttribute("offsetz");
2375
2376 float x = Convert.ToSingle(rawX);
2377 float y = Convert.ToSingle(rawY);
2378 float z = Convert.ToSingle(rawZ);
2379 veclist.Add(new Vector3(x, y, z));
2380 }
2381 }
2382
2383 return false;
2384 }
2385
2386 /// <summary>
2280 /// Event Handler Rez an object into a scene 2387 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler 2388 /// Calls the non-void event handler
2282 /// </summary> 2389 /// </summary>
@@ -2351,19 +2458,25 @@ namespace OpenSim.Region.Framework.Scenes
2351 /// will be used if it exists.</param> 2458 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param> 2459 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param> 2460 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2461 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual SceneObjectGroup RezObject( 2462 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2463 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 { 2464 {
2358 if (null == item) 2465 if (null == item)
2359 return null; 2466 return null;
2467
2468 List<SceneObjectGroup> objlist;
2469 List<Vector3> veclist;
2360 2470
2361 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2471 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2362 2472 if (!success)
2363 if (null == group)
2364 return null; 2473 return null;
2365 2474
2366 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2475 int totalPrims = 0;
2476 foreach (SceneObjectGroup group in objlist)
2477 totalPrims += group.PrimCount;
2478
2479 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2367 return null; 2480 return null;
2368 2481
2369 if (!Permissions.BypassPermissions()) 2482 if (!Permissions.BypassPermissions())
@@ -2372,16 +2485,28 @@ namespace OpenSim.Region.Framework.Scenes
2372 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2485 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2373 } 2486 }
2374 2487
2375 group.FromPartID = sourcePart.UUID; 2488 for (int i = 0; i < objlist.Count; i++)
2376 AddNewSceneObject(group, true, pos, rot, vel); 2489 {
2377 2490 SceneObjectGroup group = objlist[i];
2378 // We can only call this after adding the scene object, since the scene object references the scene 2491 Vector3 curpos = pos + veclist[i];
2379 // to find out if scripts should be activated at all. 2492
2380 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2493 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2381 2494 {
2382 group.ScheduleGroupForFullUpdate(); 2495 group.RootPart.AttachedPos = group.AbsolutePosition;
2383 2496 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2384 return group; 2497 }
2498
2499 group.FromPartID = sourcePart.UUID;
2500 AddNewSceneObject(group, true, curpos, rot, vel);
2501
2502 // We can only call this after adding the scene object, since the scene object references the scene
2503 // to find out if scripts should be activated at all.
2504 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2505
2506 group.ScheduleGroupForFullUpdate();
2507 }
2508
2509 return objlist;
2385 } 2510 }
2386 2511
2387 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2512 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index ce6415a..46b2d2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 if (part.ParentGroup.RootPart.LocalId != part.LocalId) 252 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
253 return; 253 return;
254 254
255 bool isAttachment = false;
256
257 // This is wrong, wrong, wrong. Selection should not be 255 // This is wrong, wrong, wrong. Selection should not be
258 // handled by group, but by prim. Legacy cruft. 256 // handled by group, but by prim. Legacy cruft.
259 // TODO: Make selection flagging per prim! 257 // TODO: Make selection flagging per prim!
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes
262 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) 260 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
263 part.ParentGroup.IsSelected = false; 261 part.ParentGroup.IsSelected = false;
264 262
265 if (part.ParentGroup.IsAttachment) 263 part.ParentGroup.ScheduleGroupForFullUpdate();
266 isAttachment = true;
267 else
268 part.ParentGroup.ScheduleGroupForFullUpdate();
269 264
270 // If it's not an attachment, and we are allowed to move it, 265 // If it's not an attachment, and we are allowed to move it,
271 // then we might have done so. If we moved across a parcel 266 // then we might have done so. If we moved across a parcel
272 // boundary, we will need to recount prims on the parcels. 267 // boundary, we will need to recount prims on the parcels.
273 // For attachments, that makes no sense. 268 // For attachments, that makes no sense.
274 // 269 //
275 if (!isAttachment) 270 if (!part.ParentGroup.IsAttachment)
276 { 271 {
277 if (Permissions.CanEditObject( 272 if (Permissions.CanEditObject(
278 part.UUID, remoteClient.AgentId) 273 part.UUID, remoteClient.AgentId)
@@ -416,6 +411,7 @@ namespace OpenSim.Region.Framework.Scenes
416 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) 411 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args)
417 { 412 {
418 // TODO: don't create new blocks if recycling an old packet 413 // TODO: don't create new blocks if recycling an old packet
414 bool discardableEffects = true;
419 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; 415 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count];
420 for (int i = 0; i < args.Count; i++) 416 for (int i = 0; i < args.Count; i++)
421 { 417 {
@@ -427,17 +423,34 @@ namespace OpenSim.Region.Framework.Scenes
427 effect.Type = args[i].Type; 423 effect.Type = args[i].Type;
428 effect.TypeData = args[i].TypeData; 424 effect.TypeData = args[i].TypeData;
429 effectBlockArray[i] = effect; 425 effectBlockArray[i] = effect;
426
427 if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam)
428 discardableEffects = false;
429
430 //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type);
430 } 431 }
431 432
432 ForEachClient( 433 ForEachScenePresence(sp =>
433 delegate(IClientAPI client)
434 { 434 {
435 if (client.AgentId != remoteClient.AgentId) 435 if (sp.ControllingClient.AgentId != remoteClient.AgentId)
436 client.SendViewerEffect(effectBlockArray); 436 {
437 } 437 if (!discardableEffects ||
438 ); 438 (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp)))
439 {
440 //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID);
441 sp.ControllingClient.SendViewerEffect(effectBlockArray);
442 }
443 //else
444 // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID);
445 }
446 });
439 } 447 }
440 448
449 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
450 {
451 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
452 }
453
441 private class DescendentsRequestData 454 private class DescendentsRequestData
442 { 455 {
443 public IClientAPI RemoteClient; 456 public IClientAPI RemoteClient;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b189599..55766cf 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes
151 public SynchronizeSceneHandler SynchronizeScene; 151 public SynchronizeSceneHandler SynchronizeScene;
152 152
153 /// <summary> 153 /// <summary>
154 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. 154 /// Used to prevent simultaneous calls to code that adds and removes agents.
155 /// </summary> 155 /// </summary>
156 private object m_removeClientLock = new object(); 156 private object m_removeClientLock = new object();
157 157
@@ -230,6 +230,8 @@ namespace OpenSim.Region.Framework.Scenes
230 public bool m_seeIntoBannedRegion = false; 230 public bool m_seeIntoBannedRegion = false;
231 public int MaxUndoCount = 5; 231 public int MaxUndoCount = 5;
232 232
233 public bool SeeIntoRegion { get; set; }
234
233 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 235 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
234 public bool LoginLock = false; 236 public bool LoginLock = false;
235 237
@@ -396,10 +398,12 @@ namespace OpenSim.Region.Framework.Scenes
396 if (value) 398 if (value)
397 { 399 {
398 if (!m_active) 400 if (!m_active)
399 Start(); 401 Start(false);
400 } 402 }
401 else 403 else
402 { 404 {
405 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
406 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
403 m_active = false; 407 m_active = false;
404 } 408 }
405 } 409 }
@@ -747,6 +751,7 @@ namespace OpenSim.Region.Framework.Scenes
747 m_config = config; 751 m_config = config;
748 MinFrameTime = 0.089f; 752 MinFrameTime = 0.089f;
749 MinMaintenanceTime = 1; 753 MinMaintenanceTime = 1;
754 SeeIntoRegion = true;
750 755
751 Random random = new Random(); 756 Random random = new Random();
752 757
@@ -859,9 +864,12 @@ namespace OpenSim.Region.Framework.Scenes
859 //Animation states 864 //Animation states
860 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 865 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
861 866
867 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
868
869 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
870
862 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 871 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
863 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 872 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
864
865 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 873 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
866 if (RegionInfo.NonphysPrimMin > 0) 874 if (RegionInfo.NonphysPrimMin > 0)
867 { 875 {
@@ -1332,7 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 Thread.Sleep(500); 1340 Thread.Sleep(500);
1333 1341
1334 // Stop all client threads. 1342 // Stop all client threads.
1335 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1343 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1336 1344
1337 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1345 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1338 EventManager.TriggerSceneShuttingDown(this); 1346 EventManager.TriggerSceneShuttingDown(this);
@@ -1361,10 +1369,18 @@ namespace OpenSim.Region.Framework.Scenes
1361 } 1369 }
1362 } 1370 }
1363 1371
1372 public override void Start()
1373 {
1374 Start(true);
1375 }
1376
1364 /// <summary> 1377 /// <summary>
1365 /// Start the scene 1378 /// Start the scene
1366 /// </summary> 1379 /// </summary>
1367 public void Start() 1380 /// <param name='startScripts'>
1381 /// Start the scripts within the scene.
1382 /// </param>
1383 public void Start(bool startScripts)
1368 { 1384 {
1369 m_active = true; 1385 m_active = true;
1370 1386
@@ -1401,6 +1417,8 @@ namespace OpenSim.Region.Framework.Scenes
1401 m_heartbeatThread 1417 m_heartbeatThread
1402 = Watchdog.StartThread( 1418 = Watchdog.StartThread(
1403 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1419 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1420
1421 StartScripts();
1404 } 1422 }
1405 1423
1406 /// <summary> 1424 /// <summary>
@@ -1557,6 +1575,8 @@ namespace OpenSim.Region.Framework.Scenes
1557 1575
1558 try 1576 try
1559 { 1577 {
1578 EventManager.TriggerRegionHeartbeatStart(this);
1579
1560 // Apply taints in terrain module to terrain in physics scene 1580 // Apply taints in terrain module to terrain in physics scene
1561 if (Frame % m_update_terrain == 0) 1581 if (Frame % m_update_terrain == 0)
1562 { 1582 {
@@ -1996,6 +2016,11 @@ namespace OpenSim.Region.Framework.Scenes
1996 2016
1997 GridRegion region = new GridRegion(RegionInfo); 2017 GridRegion region = new GridRegion(RegionInfo);
1998 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2018 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2019 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
2020 LogHeader, m_regionName,
2021 RegionInfo.RegionID,
2022 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2023 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1999 if (error != String.Empty) 2024 if (error != String.Empty)
2000 throw new Exception(error); 2025 throw new Exception(error);
2001 } 2026 }
@@ -2935,14 +2960,15 @@ namespace OpenSim.Region.Framework.Scenes
2935 2960
2936 #region Add/Remove Avatar Methods 2961 #region Add/Remove Avatar Methods
2937 2962
2938 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2963 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2939 { 2964 {
2940 ScenePresence sp; 2965 ScenePresence sp;
2941 bool vialogin; 2966 bool vialogin;
2967 bool reallyNew = true;
2942 2968
2943 // Validation occurs in LLUDPServer 2969 // Validation occurs in LLUDPServer
2944 // 2970 //
2945 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2971 // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
2946 // each other. In practice, this does not currently occur in the code. 2972 // each other. In practice, this does not currently occur in the code.
2947 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2973 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2948 2974
@@ -2950,9 +2976,9 @@ namespace OpenSim.Region.Framework.Scenes
2950 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2976 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2951 // whilst connecting). 2977 // whilst connecting).
2952 // 2978 //
2953 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 2979 // It would be easier to lock across all NewUserConnection(), AddNewAgent() and
2954 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service 2980 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2955 // response in some module listening to AddNewClient()) from holding up unrelated agent calls. 2981 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2956 // 2982 //
2957 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 2983 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2958 // AddNewClient() operations (though not other ops). 2984 // AddNewClient() operations (though not other ops).
@@ -2969,7 +2995,7 @@ namespace OpenSim.Region.Framework.Scenes
2969 2995
2970 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2996 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2971 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2997 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2972 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2998 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2973 // connected. 2999 // connected.
2974 if (sp == null) 3000 if (sp == null)
2975 { 3001 {
@@ -2997,16 +3023,24 @@ namespace OpenSim.Region.Framework.Scenes
2997 m_log.WarnFormat( 3023 m_log.WarnFormat(
2998 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3024 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2999 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 3025 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3026 reallyNew = false;
3000 } 3027 }
3001 3028
3002 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3029 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3003 // client is for a root or child agent. 3030 // client is for a root or child agent.
3031 // XXX: This may be better set for a new client before that client is added to the client manager.
3032 // But need to know what happens in the case where a ScenePresence is already present (and if this
3033 // actually occurs).
3004 client.SceneAgent = sp; 3034 client.SceneAgent = sp;
3005 3035
3006 // Cache the user's name 3036 // This is currently also being done earlier in NewUserConnection for real users to see if this
3037 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3038 // places. However, we still need to do it here for NPCs.
3007 CacheUserName(sp, aCircuit); 3039 CacheUserName(sp, aCircuit);
3008 3040
3009 EventManager.TriggerOnNewClient(client); 3041 if (reallyNew)
3042 EventManager.TriggerOnNewClient(client);
3043
3010 if (vialogin) 3044 if (vialogin)
3011 EventManager.TriggerOnClientLogin(client); 3045 EventManager.TriggerOnClientLogin(client);
3012 } 3046 }
@@ -3027,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3061 {
3028 string first = aCircuit.firstname, last = aCircuit.lastname; 3062 string first = aCircuit.firstname, last = aCircuit.lastname;
3029 3063
3030 if (sp.PresenceType == PresenceType.Npc) 3064 if (sp != null && sp.PresenceType == PresenceType.Npc)
3031 { 3065 {
3032 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
3033 } 3067 }
@@ -3105,7 +3139,8 @@ namespace OpenSim.Region.Framework.Scenes
3105 if (sp != null) 3139 if (sp != null)
3106 { 3140 {
3107 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3141 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3108 sp.ControllingClient.Close(); 3142
3143 CloseAgent(sp.UUID, false);
3109 } 3144 }
3110 3145
3111 // BANG! SLASH! 3146 // BANG! SLASH!
@@ -3244,8 +3279,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 { 3279 {
3245 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3280 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3246 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3281 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3247 client.OnSetStartLocationRequest += SetHomeRezPoint;
3248 client.OnRegionHandleRequest += RegionHandleRequest;
3249 } 3282 }
3250 3283
3251 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3284 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
@@ -3371,8 +3404,6 @@ namespace OpenSim.Region.Framework.Scenes
3371 { 3404 {
3372 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3405 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3373 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3406 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3374 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3375 client.OnRegionHandleRequest -= RegionHandleRequest;
3376 } 3407 }
3377 3408
3378 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3409 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3498,33 +3529,6 @@ namespace OpenSim.Region.Framework.Scenes
3498 } 3529 }
3499 3530
3500 /// <summary> 3531 /// <summary>
3501 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
3502 /// </summary>
3503 /// <param name="remoteClient"></param>
3504 /// <param name="regionHandle"></param>
3505 /// <param name="position"></param>
3506 /// <param name="lookAt"></param>
3507 /// <param name="flags"></param>
3508 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3509 {
3510 //Add half the avatar's height so that the user doesn't fall through prims
3511 ScenePresence presence;
3512 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3513 {
3514 if (presence.Appearance != null)
3515 {
3516 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3517 }
3518 }
3519
3520 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3521 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3522 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
3523 else
3524 m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed.");
3525 }
3526
3527 /// <summary>
3528 /// Get the avatar apperance for the given client. 3532 /// Get the avatar apperance for the given client.
3529 /// </summary> 3533 /// </summary>
3530 /// <param name="client"></param> 3534 /// <param name="client"></param>
@@ -3548,63 +3552,69 @@ namespace OpenSim.Region.Framework.Scenes
3548 } 3552 }
3549 } 3553 }
3550 3554
3551 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3555 /// <summary>
3556 /// Remove the given client from the scene.
3557 /// </summary>
3558 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3560 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3561 /// from viewers).
3562 /// </remarks>
3563 /// <param name='agentID'>ID of agent to close</param>
3564 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client.
3566 /// </param>
3567 public void RemoveClient(UUID agentID, bool closeChildAgents)
3552 { 3568 {
3553// CheckHeartbeat(); 3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3554 bool isChildAgent = false;
3555 AgentCircuitData acd;
3556 3570
3557 lock (m_removeClientLock) 3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3572 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3573 // However, will keep for now just in case.
3574 if (acd == null)
3558 { 3575 {
3559 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3576 m_log.ErrorFormat(
3577 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3560 3578
3561 if (acd == null) 3579 return;
3562 { 3580 }
3563 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); 3581 else
3564 return; 3582 {
3565 } 3583 m_authenticateHandler.RemoveCircuit(agentID);
3566 else
3567 {
3568 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3569 // simultaneously.
3570 // We also need to remove by agent ID since NPCs will have no circuit code.
3571 m_authenticateHandler.RemoveCircuit(agentID);
3572 }
3573 } 3584 }
3574 3585
3586 // TODO: Can we now remove this lock?
3575 lock (acd) 3587 lock (acd)
3576 { 3588 {
3589 bool isChildAgent = false;
3590
3577 ScenePresence avatar = GetScenePresence(agentID); 3591 ScenePresence avatar = GetScenePresence(agentID);
3578 3592
3593 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3594 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3595 // However, will keep for now just in case.
3579 if (avatar == null) 3596 if (avatar == null)
3580 { 3597 {
3581 m_log.WarnFormat( 3598 m_log.ErrorFormat(
3582 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3599 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3583 3600
3584 return; 3601 return;
3585 } 3602 }
3586 3603
3587 try 3604 try
3588 { 3605 {
3589 isChildAgent = avatar.IsChildAgent; 3606 isChildAgent = avatar.IsChildAgent;
3590 3607
3591 m_log.DebugFormat( 3608 m_log.DebugFormat(
3592 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3609 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3593 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3610 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3594 3611
3595 // Don't do this to root agents, it's not nice for the viewer 3612 // Don't do this to root agents, it's not nice for the viewer
3596 if (closeChildAgents && isChildAgent) 3613 if (closeChildAgents && isChildAgent)
3597 { 3614 {
3598 // Tell a single agent to disconnect from the region. 3615 // Tell a single agent to disconnect from the region.
3599 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3616 // Let's do this via UDP
3600 if (eq != null) 3617 avatar.ControllingClient.SendShutdownConnectionNotice();
3601 {
3602 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3603 }
3604 else
3605 {
3606 avatar.ControllingClient.SendShutdownConnectionNotice();
3607 }
3608 } 3618 }
3609 3619
3610 // Only applies to root agents. 3620 // Only applies to root agents.
@@ -3620,16 +3630,13 @@ namespace OpenSim.Region.Framework.Scenes
3620 if (closeChildAgents && CapsModule != null) 3630 if (closeChildAgents && CapsModule != null)
3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); 3631 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3622 3632
3623// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3624// // this method is doing is HORRIBLE!!!
3625 // Commented pending deletion since this method no longer appears to do anything at all
3626// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3627
3628 if (closeChildAgents && !isChildAgent) 3633 if (closeChildAgents && !isChildAgent)
3629 { 3634 {
3630 List<ulong> regions = avatar.KnownRegionHandles; 3635 List<ulong> regions = avatar.KnownRegionHandles;
3631 regions.Remove(RegionInfo.RegionHandle); 3636 regions.Remove(RegionInfo.RegionHandle);
3632 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3637
3638 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3639 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3633 } 3640 }
3634 3641
3635 m_eventManager.TriggerClientClosed(agentID, this); 3642 m_eventManager.TriggerClientClosed(agentID, this);
@@ -3646,7 +3653,7 @@ namespace OpenSim.Region.Framework.Scenes
3646 delegate(IClientAPI client) 3653 delegate(IClientAPI client)
3647 { 3654 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3655 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3649 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3656 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3657 catch (NullReferenceException) { }
3651 }); 3658 });
3652 } 3659 }
@@ -3727,7 +3734,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3734 }
3728 deleteIDs.Add(localID); 3735 deleteIDs.Add(localID);
3729 } 3736 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3737
3738 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3739 }
3732 3740
3733 #endregion 3741 #endregion
@@ -3763,13 +3771,13 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3771 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3772 /// the LLUDP stack).
3765 /// </remarks> 3773 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3774 /// <param name="acd">CircuitData of the agent who is connecting</param>
3767 /// <param name="reason">Outputs the reason for the false response on this string</param> 3775 /// <param name="reason">Outputs the reason for the false response on this string</param>
3768 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3776 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3769 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3777 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3770 /// <returns>True if the region accepts this agent. False if it does not. False will 3778 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3779 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3780 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3781 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3782 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3783 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,15 +3797,15 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3797 m_log.DebugFormat(
3790 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3798 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})",
3791 RegionInfo.RegionName, 3799 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3800 (acd.child ? "child" : "root"),
3793 agent.firstname, 3801 acd.firstname,
3794 agent.lastname, 3802 acd.lastname,
3795 agent.AgentID, 3803 acd.AgentID,
3796 agent.circuitcode, 3804 acd.circuitcode,
3797 agent.IPAddress, 3805 acd.IPAddress,
3798 agent.Viewer, 3806 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3807 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3808 acd.startpos
3801 ); 3809 );
3802 3810
3803 if (!LoginsEnabled) 3811 if (!LoginsEnabled)
@@ -3815,7 +3823,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3823 {
3816 foreach (string viewer in m_AllowedViewers) 3824 foreach (string viewer in m_AllowedViewers)
3817 { 3825 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3826 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3827 {
3820 ViewerDenied = false; 3828 ViewerDenied = false;
3821 break; 3829 break;
@@ -3832,7 +3840,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3840 {
3833 foreach (string viewer in m_BannedViewers) 3841 foreach (string viewer in m_BannedViewers)
3834 { 3842 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3843 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3844 {
3837 ViewerDenied = true; 3845 ViewerDenied = true;
3838 break; 3846 break;
@@ -3844,54 +3852,129 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3852 {
3845 m_log.DebugFormat( 3853 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3854 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3855 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3856 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3857 return false;
3850 } 3858 }
3851 3859
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3860 ILandObject land;
3861 ScenePresence sp;
3853 3862
3854 // If we have noo presence here or if that presence is a zombie root 3863 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3864 {
3858 if (CapsModule != null) 3865 sp = GetScenePresence(acd.AgentID);
3866
3867 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3868 // closed.
3869 if (sp != null && sp.IsChildAgent
3870 && (sp.LifecycleState == ScenePresenceState.Running
3871 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3872 {
3860 lock (agent) 3873 m_log.DebugFormat(
3874 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3875 sp.Name, sp.LifecycleState, Name);
3876
3877 // In the case where, for example, an A B C D region layout, an avatar may
3878 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3879 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3880 //
3881 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3882 // teleport, since realistically, the close request should always be processed before any other
3883 // region tried to re-establish a child agent. This is much simpler since the logic below is
3884 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3885 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3886 // flag when no teleport had taken place (and hence no close was going to come).
3887// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3888// {
3889// m_log.DebugFormat(
3890// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3891// sp.Name, Name);
3892//
3893// sp.DoNotCloseAfterTeleport = true;
3894// }
3895// else if (EntityTransferModule.IsInTransit(sp.UUID))
3896
3897 sp.LifecycleState = ScenePresenceState.Running;
3898
3899 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3900 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3901 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3902
3903 m_log.DebugFormat(
3904 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3905 sp.Name, Name);
3864 } 3906 }
3865 } 3907 }
3866 } 3908 }
3867 3909
3910 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3911 // allow unpredictable things to happen.
3868 if (sp != null) 3912 if (sp != null)
3869 { 3913 {
3870 if (!sp.IsChildAgent) 3914 const int polls = 10;
3915 const int pollInterval = 1000;
3916 int pollsLeft = polls;
3917
3918 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3919 Thread.Sleep(pollInterval);
3920
3921 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3922 {
3872 // We have a zombie from a crashed session.
3873 // Or the same user is trying to be root twice here, won't work.
3874 // Kill it.
3875 m_log.WarnFormat( 3923 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3924 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3925 sp.Name, Name, polls * pollInterval / 1000);
3878 3926
3879 sp.ControllingClient.Close(true, true); 3927 return false;
3880 sp = null; 3928 }
3929 else if (polls != pollsLeft)
3930 {
3931 m_log.DebugFormat(
3932 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3933 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3934 }
3882 } 3935 }
3883 3936
3884 lock (agent) 3937 // TODO: can we remove this lock?
3938 lock (acd)
3885 { 3939 {
3886 //On login test land permisions 3940 if (sp != null && !sp.IsChildAgent)
3941 {
3942 // We have a root agent. Is it in transit?
3943 if (!EntityTransferModule.IsInTransit(sp.UUID))
3944 {
3945 // We have a zombie from a crashed session.
3946 // Or the same user is trying to be root twice here, won't work.
3947 // Kill it.
3948 m_log.WarnFormat(
3949 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3950 sp.Name, sp.UUID, RegionInfo.RegionName);
3951
3952 if (sp.ControllingClient != null)
3953 CloseAgent(sp.UUID, true);
3954
3955 sp = null;
3956 }
3957 //else
3958 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3959 }
3960
3961 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3962 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3963 // If the checks fail, we remove the circuit.
3964 acd.teleportFlags = teleportFlags;
3965 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3966
3967 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3968
3969 // On login test land permisions
3887 if (vialogin) 3970 if (vialogin)
3888 { 3971 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3972 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 3973 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 3974 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3975 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 3976 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3977 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 3978 return false;
3896 } 3979 }
3897 } 3980 }
@@ -3902,84 +3985,97 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 3985 {
3903 try 3986 try
3904 { 3987 {
3905 if (!VerifyUserPresence(agent, out reason)) 3988 if (!VerifyUserPresence(acd, out reason))
3989 {
3990 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 3991 return false;
3907 } catch (Exception e) 3992 }
3993 }
3994 catch (Exception e)
3908 { 3995 {
3909 m_log.ErrorFormat( 3996 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3997 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3998
3999 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 4000 return false;
3912 } 4001 }
3913 } 4002 }
3914 4003
3915 try 4004 try
3916 { 4005 {
3917 // Always check estate if this is a login. Always 4006 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 4007 {
3921 if (!AuthorizeUser(agent, out reason)) 4008 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 4009 return false;
3923 return false;
3924 }
3925 } 4010 }
3926 } 4011 }
3927 catch (Exception e) 4012 catch (Exception e)
3928 { 4013 {
3929 m_log.ErrorFormat( 4014 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4015 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4016
4017 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4018 return false;
3932 } 4019 }
3933 4020
3934 m_log.InfoFormat( 4021 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4022 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3936 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 4023 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4024 acd.AgentID, acd.circuitcode);
3938 4025
4026 if (CapsModule != null)
4027 {
4028 CapsModule.SetAgentCapsSeeds(acd);
4029 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4030 }
3939 } 4031 }
3940 else 4032 else
3941 { 4033 {
3942 // Let the SP know how we got here. This has a lot of interesting 4034 // Let the SP know how we got here. This has a lot of interesting
3943 // uses down the line. 4035 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4036 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4037
3946 if (sp.IsChildAgent) 4038 if (sp.IsChildAgent)
3947 { 4039 {
3948 m_log.DebugFormat( 4040 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4041 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4042 acd.AgentID, RegionInfo.RegionName);
3951 4043
3952 sp.AdjustKnownSeeds(); 4044 sp.AdjustKnownSeeds();
3953 4045
3954 if (CapsModule != null) 4046 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4047 {
4048 CapsModule.SetAgentCapsSeeds(acd);
4049 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4050 }
3956 } 4051 }
3957 } 4052 }
3958 }
3959 4053
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4054 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4055 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4056 // request for the HG avatar appears to trigger before the user name is cached.
4057 CacheUserName(null, acd);
4058 }
3963 4059
3964 if (CapsModule != null) 4060 if (CapsModule != null)
3965 { 4061 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4062 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4063 }
3968 4064
3969 if (vialogin) 4065 if (vialogin)
3970 { 4066 {
3971// CleanDroppedAttachments(); 4067// CleanDroppedAttachments();
3972 4068
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4069 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4070 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4071 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4072 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4073 }
3978 4074
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4075 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4076 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4077 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4078 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4079 }
3984 4080
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4081 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,68 +4085,88 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4085 {
3990 lock (EastBorders) 4086 lock (EastBorders)
3991 { 4087 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4088 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4089 {
3994 m_log.Warn("FIX AGENT POSITION"); 4090 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4091 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4092 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4093 acd.startpos.Z = 720;
3998 } 4094 }
3999 } 4095 }
4000 lock (NorthBorders) 4096 lock (NorthBorders)
4001 { 4097 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4098 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4099 {
4004 m_log.Warn("FIX Agent POSITION"); 4100 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4101 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4102 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4103 acd.startpos.Z = 720;
4008 } 4104 }
4009 } 4105 }
4010 } else 4106 } else
4011 { 4107 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4108 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4109 {
4014 m_log.Warn("FIX AGENT POSITION"); 4110 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4111 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4112 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4113 acd.startpos.Z = 720;
4018 } 4114 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4115 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4116 {
4021 m_log.Warn("FIX Agent POSITION"); 4117 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4118 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4119 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4120 acd.startpos.Z = 720;
4025 } 4121 }
4026 } 4122 }
4027 4123
4124// m_log.DebugFormat(
4125// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4126// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4127
4028 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4128 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4029 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4129 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4030 RegionInfo.EstateSettings.AllowDirectTeleport == false && 4130 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4031 !viahome && !godlike) 4131 !viahome && !godlike)
4032 { 4132 {
4033 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4133 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4034 // Can have multiple SpawnPoints 4134
4035 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4135 if (telehub != null)
4036 if (spawnpoints.Count > 1)
4037 { 4136 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4137 // Can have multiple SpawnPoints
4039 if (SpawnPointRouting == "random") 4138 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4139 if (spawnpoints.Count > 1)
4041 telehub.AbsolutePosition, 4140 {
4042 telehub.GroupRotation 4141 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4043 ); 4142 if (SpawnPointRouting == "random")
4143 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4144 telehub.AbsolutePosition,
4145 telehub.GroupRotation
4146 );
4147 else
4148 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4149 telehub.AbsolutePosition,
4150 telehub.GroupRotation
4151 );
4152 }
4153 else if (spawnpoints.Count == 1)
4154 {
4155 // We have a single SpawnPoint and will route the agent to it
4156 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4157 }
4044 else 4158 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4159 {
4046 telehub.AbsolutePosition, 4160 m_log.DebugFormat(
4047 telehub.GroupRotation 4161 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4048 ); 4162 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4163 }
4049 } 4164 }
4050 else 4165 else
4051 { 4166 {
4052 // We have a single SpawnPoint and will route the agent to it 4167 m_log.DebugFormat(
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4168 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4169 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4054 } 4170 }
4055 4171
4056 return true; 4172 return true;
@@ -4063,7 +4179,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4179 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4180 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4181 {
4066 agent.startpos = land.LandData.UserLocation; 4182 acd.startpos = land.LandData.UserLocation;
4067 } 4183 }
4068 } 4184 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4185 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4274,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4274 /// <param name="reason">outputs the reason to this string</param>
4159 /// <returns>True if the region accepts this agent. False if it does not. False will 4275 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4276 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4277 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4278 {
4163 reason = String.Empty; 4279 reason = String.Empty;
4164 4280
@@ -4177,67 +4293,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4293 }
4178 } 4294 }
4179 4295
4180 if (RegionInfo.EstateSettings != null) 4296 // We only test the things below when we want to cut off
4297 // child agents from being present in the scene for which their root
4298 // agent isn't allowed. Otherwise, we allow child agents. The test for
4299 // the root is done elsewhere (QueryAccess)
4300 if (!bypassAccessControl)
4181 { 4301 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4302 if (RegionInfo.EstateSettings != null)
4183 { 4303 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4304 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4305 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4306 {
4187 RegionInfo.RegionName); 4307 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4308 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4309 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4310 RegionInfo.RegionName);
4311 return false;
4312 }
4189 } 4313 }
4190 } 4314 else
4191 else
4192 {
4193 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4194 }
4195
4196 List<UUID> agentGroups = new List<UUID>();
4197
4198 if (m_groupsModule != null)
4199 {
4200 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4201
4202 if (GroupMembership != null)
4203 { 4315 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4316 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4317 }
4207 else 4318
4319 List<UUID> agentGroups = new List<UUID>();
4320
4321 if (m_groupsModule != null)
4208 { 4322 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4323 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4324
4325 if (GroupMembership != null)
4326 {
4327 for (int i = 0; i < GroupMembership.Length; i++)
4328 agentGroups.Add(GroupMembership[i].GroupID);
4329 }
4330 else
4331 {
4332 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4333 }
4210 } 4334 }
4211 }
4212 4335
4213 bool groupAccess = false; 4336 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4337 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4338
4216 if (estateGroups != null) 4339 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4340 {
4220 if (agentGroups.Contains(group)) 4341 foreach (UUID group in estateGroups)
4221 { 4342 {
4222 groupAccess = true; 4343 if (agentGroups.Contains(group))
4223 break; 4344 {
4345 groupAccess = true;
4346 break;
4347 }
4224 } 4348 }
4225 } 4349 }
4226 } 4350 else
4227 else 4351 {
4228 { 4352 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4353 }
4230 }
4231 4354
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4355 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4356 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4357 !groupAccess)
4235 { 4358 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4359 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate",
4237 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4360 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4238 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 4361 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4362 RegionInfo.RegionName);
4240 return false; 4363 return false;
4364 }
4241 } 4365 }
4242 4366
4243 // TODO: estate/region settings are not properly hooked up 4367 // TODO: estate/region settings are not properly hooked up
@@ -4362,13 +4486,11 @@ namespace OpenSim.Region.Framework.Scenes
4362 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4486 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4363 /// Appearance, animations, position, etc.</param> 4487 /// Appearance, animations, position, etc.</param>
4364 /// <returns>true if we handled it.</returns> 4488 /// <returns>true if we handled it.</returns>
4365 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4489 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4366 { 4490 {
4367 m_log.DebugFormat( 4491 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4492 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4493
4370 // XPTO: if this agent is not allowed here as root, always return false
4371
4372 // We have to wait until the viewer contacts this region after receiving EAC. 4494 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4495 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4496 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4382,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
4382 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4504 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4383 if (nearestParcel == null) 4505 if (nearestParcel == null)
4384 { 4506 {
4385 m_log.DebugFormat( 4507 m_log.InfoFormat(
4386 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4508 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4387 cAgentData.AgentID, RegionInfo.RegionName); 4509 cAgentData.AgentID, RegionInfo.RegionName);
4388 4510
@@ -4390,13 +4512,44 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4512 }
4391 4513
4392 // We have to wait until the viewer contacts this region 4514 // We have to wait until the viewer contacts this region
4393 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send 4515 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4394 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4516 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4517 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4518 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4519
4397 if (childAgentUpdate != null) 4520 if (sp != null)
4398 { 4521 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4522 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4523 {
4524 m_log.WarnFormat(
4525 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4526 sp.UUID, cAgentData.SessionID);
4527
4528 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4529 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4530 }
4531
4532 sp.UpdateChildAgent(cAgentData);
4533
4534 int ntimes = 20;
4535 if (cAgentData.SenderWantsToWaitForRoot)
4536 {
4537 while (sp.IsChildAgent && ntimes-- > 0)
4538 Thread.Sleep(1000);
4539
4540 if (sp.IsChildAgent)
4541 m_log.WarnFormat(
4542 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4543 sp.Name, sp.UUID, Name);
4544 else
4545 m_log.InfoFormat(
4546 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4547 sp.Name, sp.UUID, Name, 20 - ntimes);
4548
4549 if (sp.IsChildAgent)
4550 return false;
4551 }
4552
4400 return true; 4553 return true;
4401 } 4554 }
4402 4555
@@ -4409,12 +4562,17 @@ namespace OpenSim.Region.Framework.Scenes
4409 /// </summary> 4562 /// </summary>
4410 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4563 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
4411 /// <returns>true if we handled it.</returns> 4564 /// <returns>true if we handled it.</returns>
4412 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4565 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4413 { 4566 {
4414 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4567 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4568 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4569 if (childAgentUpdate != null)
4417 { 4570 {
4571// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4572// // Only warn for now
4573// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4574// childAgentUpdate.UUID, cAgentData.SessionID);
4575
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4576 // I can't imagine *yet* why we would get an update if the agent is a root agent..
4419 // however to avoid a race condition crossing borders.. 4577 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4578 if (childAgentUpdate.IsChildAgent)
@@ -4424,7 +4582,7 @@ namespace OpenSim.Region.Framework.Scenes
4424 uint tRegionX = RegionInfo.RegionLocX; 4582 uint tRegionX = RegionInfo.RegionLocX;
4425 uint tRegionY = RegionInfo.RegionLocY; 4583 uint tRegionY = RegionInfo.RegionLocY;
4426 //Send Data to ScenePresence 4584 //Send Data to ScenePresence
4427 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4585 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4428 // Not Implemented: 4586 // Not Implemented:
4429 //TODO: Do we need to pass the message on to one of our neighbors? 4587 //TODO: Do we need to pass the message on to one of our neighbors?
4430 } 4588 }
@@ -4451,35 +4609,99 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4609 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4610 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4611 agentID, RegionInfo.RegionName);
4454// else
4455// m_log.DebugFormat(
4456// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
4457// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
4458 4612
4459 return sp; 4613 return sp;
4460 } 4614 }
4461 4615
4462 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4616 /// <summary>
4617 /// Authenticated close (via network)
4618 /// </summary>
4619 /// <param name="agentID"></param>
4620 /// <param name="force"></param>
4621 /// <param name="auth_token"></param>
4622 /// <returns></returns>
4623 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4463 { 4624 {
4464 agent = null; 4625 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4465 ScenePresence sp = GetScenePresence(id); 4626
4466 if ((sp != null) && (!sp.IsChildAgent)) 4627 // Check that the auth_token is valid
4628 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4629
4630 if (acd == null)
4467 { 4631 {
4468 sp.IsChildAgent = true; 4632 m_log.DebugFormat(
4469 return sp.CopyAgent(out agent); 4633 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4634 agentID, Name);
4635
4636 return false;
4637 }
4638
4639 if (acd.SessionID.ToString() == auth_token)
4640 {
4641 return CloseAgent(agentID, force);
4642 }
4643 else
4644 {
4645 m_log.WarnFormat(
4646 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4647 agentID, auth_token, Name);
4470 } 4648 }
4471 4649
4472 return false; 4650 return false;
4473 } 4651 }
4474 4652
4475 public bool IncomingCloseAgent(UUID agentID) 4653// public bool IncomingCloseAgent(UUID agentID)
4476 { 4654// {
4477 return IncomingCloseAgent(agentID, false); 4655// return IncomingCloseAgent(agentID, false);
4478 } 4656// }
4479 4657
4480 public bool IncomingCloseChildAgent(UUID agentID) 4658// public bool IncomingCloseChildAgent(UUID agentID)
4659// {
4660// return IncomingCloseAgent(agentID, true);
4661// }
4662
4663 /// <summary>
4664 /// Tell a single client to prepare to close.
4665 /// </summary>
4666 /// <remarks>
4667 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4668 /// internal use - other callers should almost certainly called CloseClient().
4669 /// </remarks>
4670 /// <param name="sp"></param>
4671 /// <returns>true if pre-close state notification was successful. false if the agent
4672 /// was not in a state where it could transition to pre-close.</returns>
4673 public bool IncomingPreCloseClient(ScenePresence sp)
4481 { 4674 {
4482 return IncomingCloseAgent(agentID, true); 4675 lock (m_removeClientLock)
4676 {
4677 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4678 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4679 // want to obey this close since C may have renewed the child agent lease on B.
4680 if (sp.DoNotCloseAfterTeleport)
4681 {
4682 m_log.DebugFormat(
4683 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4684 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4685
4686 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4687 sp.DoNotCloseAfterTeleport = false;
4688
4689 return false;
4690 }
4691
4692 if (sp.LifecycleState != ScenePresenceState.Running)
4693 {
4694 m_log.DebugFormat(
4695 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4696 sp.Name, Name, sp.LifecycleState);
4697
4698 return false;
4699 }
4700
4701 sp.LifecycleState = ScenePresenceState.PreRemove;
4702
4703 return true;
4704 }
4483 } 4705 }
4484 4706
4485 /// <summary> 4707 /// <summary>
@@ -4490,18 +4712,57 @@ namespace OpenSim.Region.Framework.Scenes
4490 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4712 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4491 /// force unless you are absolutely sure that the agent is dead and a normal close is not working. 4713 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4492 /// </param> 4714 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4715 public override bool CloseAgent(UUID agentID, bool force)
4494 { 4716 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4717 ScenePresence sp;
4496 4718
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4719 lock (m_removeClientLock)
4498 if (presence != null) 4720 {
4721 sp = GetScenePresence(agentID);
4722
4723 if (sp == null)
4724 {
4725 m_log.DebugFormat(
4726 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4727 agentID, Name);
4728
4729 return false;
4730 }
4731
4732 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4733 {
4734 m_log.DebugFormat(
4735 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4736 sp.Name, Name, sp.LifecycleState);
4737
4738 return false;
4739 }
4740
4741 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4742 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4743 // want to obey this close since C may have renewed the child agent lease on B.
4744 if (sp.DoNotCloseAfterTeleport)
4745 {
4746 m_log.DebugFormat(
4747 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4748 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4749
4750 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4751 sp.DoNotCloseAfterTeleport = false;
4752
4753 return false;
4754 }
4755
4756 sp.LifecycleState = ScenePresenceState.Removing;
4757 }
4758
4759 if (sp != null)
4499 { 4760 {
4500 presence.ControllingClient.Close(force, force); 4761 sp.ControllingClient.Close(force, force);
4501 return true; 4762 return true;
4502 } 4763 }
4503 4764
4504 // Agent not here 4765 // Agent not here
4505 return false; 4766 return false;
4506 } 4767 }
4507 4768
@@ -5091,21 +5352,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5352
5092 #endregion 5353 #endregion
5093 5354
5094 public void RegionHandleRequest(IClientAPI client, UUID regionID)
5095 {
5096 ulong handle = 0;
5097 if (regionID == RegionInfo.RegionID)
5098 handle = RegionInfo.RegionHandle;
5099 else
5100 {
5101 GridRegion r = GridService.GetRegionByUUID(UUID.Zero, regionID);
5102 if (r != null)
5103 handle = r.RegionHandle;
5104 }
5105
5106 if (handle != 0)
5107 client.SendRegionHandle(regionID, handle);
5108 }
5109 5355
5110// Commented pending deletion since this method no longer appears to do anything at all 5356// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5357// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5903,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5903 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5904 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5905 {
5660 minX = 256; 5906 minX = float.MaxValue;
5661 maxX = -256; 5907 maxX = float.MinValue;
5662 minY = 256; 5908 minY = float.MaxValue;
5663 maxY = -256; 5909 maxY = float.MinValue;
5664 minZ = 8192; 5910 minZ = float.MaxValue;
5665 maxZ = -256; 5911 maxZ = float.MinValue;
5666 5912
5667 List<Vector3> offsets = new List<Vector3>(); 5913 List<Vector3> offsets = new List<Vector3>();
5668 5914
@@ -5802,17 +6048,6 @@ Environment.Exit(1);
5802 { 6048 {
5803 reason = "You are banned from the region"; 6049 reason = "You are banned from the region";
5804 6050
5805 if (EntityTransferModule.IsInTransit(agentID))
5806 {
5807 reason = "Agent is still in transit from this region";
5808
5809 m_log.WarnFormat(
5810 "[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit",
5811 agentID, RegionInfo.RegionName);
5812
5813 return false;
5814 }
5815
5816 if (Permissions.IsGod(agentID)) 6051 if (Permissions.IsGod(agentID))
5817 { 6052 {
5818 reason = String.Empty; 6053 reason = String.Empty;
@@ -5862,9 +6097,9 @@ Environment.Exit(1);
5862 6097
5863 try 6098 try
5864 { 6099 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6100 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6101 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6102 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6103 return false;
5869 } 6104 }
5870 } 6105 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 74c9582..08e26c5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -42,7 +42,8 @@ namespace OpenSim.Region.Framework.Scenes
42{ 42{
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 protected static readonly string LogHeader = "[SCENE]";
46 47
47 #region Events 48 #region Events
48 49
@@ -217,8 +218,9 @@ namespace OpenSim.Region.Framework.Scenes
217 218
218 #region Add/Remove Agent/Avatar 219 #region Add/Remove Agent/Avatar
219 220
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 221 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
221 public abstract void RemoveClient(UUID agentID, bool closeChildAgents); 222
223 public abstract bool CloseAgent(UUID agentID, bool force);
222 224
223 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 225 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
224 { 226 {
@@ -562,6 +564,10 @@ namespace OpenSim.Region.Framework.Scenes
562 get { return false; } 564 get { return false; }
563 } 565 }
564 566
567 public virtual void Start()
568 {
569 }
570
565 public void Restart() 571 public void Restart()
566 { 572 {
567 // This has to be here to fire the event 573 // This has to be here to fire the event
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 775a4c2..52f46f2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// This Closes child agents on neighboring regions 200 /// This Closes child agents on neighboring regions
201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
202 /// </summary> 202 /// </summary>
203 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 203 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
204 { 204 {
205 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 205 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
206 206
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes
209 Utils.LongToUInts(regionHandle, out x, out y); 209 Utils.LongToUInts(regionHandle, out x, out y);
210 210
211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
212 m_scene.SimulationService.CloseChildAgent(destination, agentID);
213 }
214 212
215 private void SendCloseChildAgentCompleted(IAsyncResult iar) 213 m_log.DebugFormat(
216 { 214 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
217 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; 215
218 icon.EndInvoke(iar); 216 m_scene.SimulationService.CloseAgent(destination, agentID, auth_token);
219 } 217 }
220 218
221 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 219 /// <summary>
220 /// Closes a child agents in a collection of regions. Does so asynchronously
221 /// so that the caller doesn't wait.
222 /// </summary>
223 /// <param name="agentID"></param>
224 /// <param name="regionslst"></param>
225 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
222 { 226 {
223 foreach (ulong handle in regionslst) 227 foreach (ulong handle in regionslst)
224 { 228 {
225 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; 229 ulong handleCopy = handle;
226 d.BeginInvoke(agentID, handle, 230 Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
227 SendCloseChildAgentCompleted,
228 d);
229 } 231 }
230 } 232 }
231 233
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..b0f8991 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
631 protected internal ScenePresence CreateAndAddChildScenePresence( 631 protected internal ScenePresence CreateAndAddChildScenePresence(
632 IClientAPI client, AvatarAppearance appearance, PresenceType type) 632 IClientAPI client, AvatarAppearance appearance, PresenceType type)
633 { 633 {
634 ScenePresence newAvatar = null;
635
636 // ScenePresence always defaults to child agent 634 // ScenePresence always defaults to child agent
637 newAvatar = new ScenePresence(client, m_parentScene, appearance, type); 635 ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
638
639 AddScenePresence(newAvatar);
640
641 return newAvatar;
642 }
643
644 /// <summary>
645 /// Add a presence to the scene
646 /// </summary>
647 /// <param name="presence"></param>
648 protected internal void AddScenePresence(ScenePresence presence)
649 {
650 // Always a child when added to the scene
651 bool child = presence.IsChildAgent;
652
653 if (child)
654 {
655 m_numChildAgents++;
656 }
657 else
658 {
659 m_numRootAgents++;
660 presence.AddToPhysicalScene(false);
661 }
662 636
663 Entities[presence.UUID] = presence; 637 Entities[presence.UUID] = presence;
664 638
665 m_scenePresencesLock.EnterWriteLock(); 639 m_scenePresencesLock.EnterWriteLock();
666 try 640 try
667 { 641 {
642 m_numChildAgents++;
643
668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
670 646
@@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
675 } 651 }
676 else 652 else
677 { 653 {
678 // Remember the old presene reference from the dictionary 654 // Remember the old presence reference from the dictionary
679 ScenePresence oldref = newmap[presence.UUID]; 655 ScenePresence oldref = newmap[presence.UUID];
680 // Replace the presence reference in the dictionary with the new value 656 // Replace the presence reference in the dictionary with the new value
681 newmap[presence.UUID] = presence; 657 newmap[presence.UUID] = presence;
@@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes
691 { 667 {
692 m_scenePresencesLock.ExitWriteLock(); 668 m_scenePresencesLock.ExitWriteLock();
693 } 669 }
670
671 return presence;
694 } 672 }
695 673
696 /// <summary> 674 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index c70342f..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes
420 return false; 420 return false;
421 } 421 }
422 422
423 /// <summary>
424 /// Set the debug packet level on each current scene. This level governs which packets are printed out to the
425 /// console.
426 /// </summary>
427 /// <param name="newDebug"></param>
428 /// <param name="name">Name of avatar to debug</param>
429 public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name)
430 {
431 ForEachSelectedScene(scene =>
432 scene.ForEachScenePresence(sp =>
433 {
434 if (name == null || sp.Name == name)
435 {
436 m_log.DebugFormat(
437 "Packet debug for {0} ({1}) set to {2}",
438 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug);
439
440 sp.ControllingClient.DebugPacketLevel = newDebug;
441 }
442 })
443 );
444 }
445
446 public List<ScenePresence> GetCurrentSceneAvatars() 423 public List<ScenePresence> GetCurrentSceneAvatars()
447 { 424 {
448 List<ScenePresence> avatars = new List<ScenePresence>(); 425 List<ScenePresence> avatars = new List<ScenePresence>();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f8624e7..8c50a81 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes
67 { 67 {
68 int scriptsStarted = 0; 68 int scriptsStarted = 0;
69 69
70 if (m_scene == null)
71 {
72 m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances");
73 return 0;
74 }
75
70 // Don't start scripts if they're turned off in the region! 76 // Don't start scripts if they're turned off in the region!
71 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 77 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
72 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 86f60bb..cfa862e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -111,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes
111 STATUS_ROTATE_Z = 0x008, 111 STATUS_ROTATE_Z = 0x008,
112 } 112 }
113 113
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
115 public static readonly uint SLAM = 16;
116
114 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 117 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
115 118
116 /// <summary> 119 /// <summary>
@@ -506,9 +509,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 509 {
507 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 510 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
508 } 511 }
509 512
510
511
512 private struct avtocrossInfo 513 private struct avtocrossInfo
513 { 514 {
514 public ScenePresence av; 515 public ScenePresence av;
@@ -660,12 +661,6 @@ namespace OpenSim.Region.Framework.Scenes
660 } 661 }
661 } 662 }
662 663
663/* don't see the need but worse don't see where is restored to false if things stay in
664 foreach (SceneObjectPart part in m_parts.GetArray())
665 {
666 part.IgnoreUndoUpdate = true;
667 }
668 */
669 if (RootPart.GetStatusSandbox()) 664 if (RootPart.GetStatusSandbox())
670 { 665 {
671 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 666 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -751,7 +746,6 @@ namespace OpenSim.Region.Framework.Scenes
751 } 746 }
752 747
753 agent.ParentUUID = UUID.Zero; 748 agent.ParentUUID = UUID.Zero;
754
755// agent.Reset(); 749// agent.Reset();
756// else // Not successful 750// else // Not successful
757// agent.RestoreInCurrentScene(); 751// agent.RestoreInCurrentScene();
@@ -1667,7 +1661,8 @@ namespace OpenSim.Region.Framework.Scenes
1667 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1661 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1668 if (avatar == null) 1662 if (avatar == null)
1669 return; 1663 return;
1670 1664 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1665 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1671 avatar.RemoveAttachment(this); 1666 avatar.RemoveAttachment(this);
1672 1667
1673 Vector3 detachedpos = new Vector3(127f,127f,127f); 1668 Vector3 detachedpos = new Vector3(127f,127f,127f);
@@ -1868,11 +1863,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1863 /// <summary>
1869 /// Delete this group from its scene. 1864 /// Delete this group from its scene.
1870 /// </summary> 1865 /// </summary>
1871 /// 1866 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1867 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood
1873 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup 1868 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1869 /// must be handled by the caller.
1875 /// 1870 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1871 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1872 public void DeleteGroupFromScene(bool silent)
1878 { 1873 {
@@ -1901,7 +1896,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 if (!IsAttachment 1896 if (!IsAttachment
1902 || AttachedAvatar == avatar.ControllingClient.AgentId 1897 || AttachedAvatar == avatar.ControllingClient.AgentId
1903 || !HasPrivateAttachmentPoint) 1898 || !HasPrivateAttachmentPoint)
1904 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1899 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1905 } 1900 }
1906 } 1901 }
1907 }); 1902 });
@@ -2109,6 +2104,7 @@ namespace OpenSim.Region.Framework.Scenes
2109 2104
2110 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) 2105 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2111 { 2106 {
2107 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2112 RootPart.Shape.State = 0; 2108 RootPart.Shape.State = 0;
2113 ScheduleGroupForFullUpdate(); 2109 ScheduleGroupForFullUpdate();
2114 } 2110 }
@@ -2210,7 +2206,7 @@ namespace OpenSim.Region.Framework.Scenes
2210 if (!userExposed) 2206 if (!userExposed)
2211 dupe.IsAttachment = true; 2207 dupe.IsAttachment = true;
2212 2208
2213 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 2209 dupe.m_sittingAvatars = new List<UUID>();
2214 2210
2215 if (!userExposed) 2211 if (!userExposed)
2216 { 2212 {
@@ -3813,20 +3809,20 @@ namespace OpenSim.Region.Framework.Scenes
3813 /// <summary> 3809 /// <summary>
3814 /// Update just the root prim position in a linkset 3810 /// Update just the root prim position in a linkset
3815 /// </summary> 3811 /// </summary>
3816 /// <param name="pos"></param> 3812 /// <param name="newPos"></param>
3817 public void UpdateRootPosition(Vector3 pos) 3813 public void UpdateRootPosition(Vector3 newPos)
3818 { 3814 {
3819 // needs to be called with phys building true 3815 // needs to be called with phys building true
3820 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3816 Vector3 oldPos;
3821 Vector3 oldPos = 3817
3822 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3818 if (IsAttachment)
3823 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3819 oldPos = m_rootPart.AttachedPos + m_rootPart.OffsetPosition; // OffsetPosition should always be 0 in an attachments's root prim
3824 AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); 3820 else
3821 oldPos = AbsolutePosition + m_rootPart.OffsetPosition;
3822
3825 Vector3 diff = oldPos - newPos; 3823 Vector3 diff = oldPos - newPos;
3826 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3827 Quaternion partRotation = m_rootPart.RotationOffset; 3824 Quaternion partRotation = m_rootPart.RotationOffset;
3828 axDiff *= Quaternion.Inverse(partRotation); 3825 diff *= Quaternion.Inverse(partRotation);
3829 diff = axDiff;
3830 3826
3831 SceneObjectPart[] parts = m_parts.GetArray(); 3827 SceneObjectPart[] parts = m_parts.GetArray();
3832 for (int i = 0; i < parts.Length; i++) 3828 for (int i = 0; i < parts.Length; i++)
@@ -3837,6 +3833,9 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 3833 }
3838 3834
3839 AbsolutePosition = newPos; 3835 AbsolutePosition = newPos;
3836
3837 if (IsAttachment)
3838 m_rootPart.AttachedPos = newPos;
3840 3839
3841 HasGroupChanged = true; 3840 HasGroupChanged = true;
3842 if (m_rootPart.Undoing) 3841 if (m_rootPart.Undoing)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 261e958..ce9baaa 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
231 231
232 public double SoundRadius; 232 public double SoundRadius;
233 233
234 /// <summary>
235 /// Should sounds played from this prim be queued?
236 /// </summary>
237 /// <remarks>
238 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
239 /// </remarks>
240 public bool SoundQueueing { get; set; }
234 241
235 public uint TimeStampFull; 242 public uint TimeStampFull;
236 243
@@ -383,8 +390,6 @@ namespace OpenSim.Region.Framework.Scenes
383 390
384 private SOPVehicle m_vehicleParams = null; 391 private SOPVehicle m_vehicleParams = null;
385 392
386 private KeyframeMotion m_keyframeMotion = null;
387
388 public KeyframeMotion KeyframeMotion 393 public KeyframeMotion KeyframeMotion
389 { 394 {
390 get; set; 395 get; set;
@@ -506,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 511 {
507 get 512 get
508 { 513 {
509 if (CreatorData != null && CreatorData != string.Empty) 514 if (!string.IsNullOrEmpty(CreatorData))
510 return CreatorID.ToString() + ';' + CreatorData; 515 return CreatorID.ToString() + ';' + CreatorData;
511 else 516 else
512 return CreatorID.ToString(); 517 return CreatorID.ToString();
@@ -536,7 +541,11 @@ namespace OpenSim.Region.Framework.Scenes
536 CreatorID = uuid; 541 CreatorID = uuid;
537 } 542 }
538 if (parts.Length >= 2) 543 if (parts.Length >= 2)
544 {
539 CreatorData = parts[1]; 545 CreatorData = parts[1];
546 if (!CreatorData.EndsWith("/"))
547 CreatorData += "/";
548 }
540 if (parts.Length >= 3) 549 if (parts.Length >= 3)
541 name = parts[2]; 550 name = parts[2];
542 551
@@ -815,7 +824,8 @@ namespace OpenSim.Region.Framework.Scenes
815 } 824 }
816 825
817 // Tell the physics engines that this prim changed. 826 // Tell the physics engines that this prim changed.
818 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 827 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
828 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
819 } 829 }
820 catch (Exception e) 830 catch (Exception e)
821 { 831 {
@@ -933,7 +943,7 @@ namespace OpenSim.Region.Framework.Scenes
933 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 943 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
934 } 944 }
935 945
936 if (ParentGroup != null) 946 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
937 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 947 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
938 //} 948 //}
939 } 949 }
@@ -1218,23 +1228,14 @@ namespace OpenSim.Region.Framework.Scenes
1218 // the mappings more consistant. 1228 // the mappings more consistant.
1219 public Vector3 SitTargetPositionLL 1229 public Vector3 SitTargetPositionLL
1220 { 1230 {
1221 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1231 get { return m_sitTargetPosition; }
1222 set { m_sitTargetPosition = value; } 1232 set { m_sitTargetPosition = value; }
1223 } 1233 }
1224 1234
1225 public Quaternion SitTargetOrientationLL 1235 public Quaternion SitTargetOrientationLL
1226 { 1236 {
1227 get 1237 get { return m_sitTargetOrientation; }
1228 { 1238 set { m_sitTargetOrientation = value; }
1229 return new Quaternion(
1230 m_sitTargetOrientation.X,
1231 m_sitTargetOrientation.Y,
1232 m_sitTargetOrientation.Z,
1233 m_sitTargetOrientation.W
1234 );
1235 }
1236
1237 set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); }
1238 } 1239 }
1239 1240
1240 public bool Stopped 1241 public bool Stopped
@@ -2959,6 +2960,26 @@ namespace OpenSim.Region.Framework.Scenes
2959 //ParentGroup.RootPart.m_groupPosition = newpos; 2960 //ParentGroup.RootPart.m_groupPosition = newpos;
2960 } 2961 }
2961 2962
2963 if (pa != null && ParentID != 0 && ParentGroup != null)
2964 {
2965 // Special case where a child object is requesting property updates.
2966 // This happens when linksets are modified to use flexible links rather than
2967 // the default links.
2968 // The simulator code presumes that child parts are only modified by scripts
2969 // so the logic for changing position/rotation/etc does not take into
2970 // account the physical object actually moving.
2971 // This code updates the offset position and rotation of the child and then
2972 // lets the update code push the update to the viewer.
2973 // Since physics engines do not normally generate this event for linkset children,
2974 // this code will not be active unless you have a specially configured
2975 // physics engine.
2976 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
2977 m_offsetPosition = pa.Position - m_groupPosition;
2978 RotationOffset = pa.Orientation * invRootRotation;
2979 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2980 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2981 }
2982
2962 ScheduleTerseUpdate(); 2983 ScheduleTerseUpdate();
2963 } 2984 }
2964 2985
@@ -3137,7 +3158,8 @@ namespace OpenSim.Region.Framework.Scenes
3137 return; 3158 return;
3138 3159
3139 // This was pulled from SceneViewer. Attachments always receive full updates. 3160 // This was pulled from SceneViewer. Attachments always receive full updates.
3140 // I could not verify if this is a requirement but this maintains existing behavior 3161 // This is needed because otherwise if only the root prim changes position, then
3162 // it looks as if the entire object has moved (including the other prims).
3141 if (ParentGroup.IsAttachment) 3163 if (ParentGroup.IsAttachment)
3142 { 3164 {
3143 ScheduleFullUpdate(); 3165 ScheduleFullUpdate();
@@ -4350,30 +4372,31 @@ namespace OpenSim.Region.Framework.Scenes
4350 } 4372 }
4351 } 4373 }
4352 4374
4353 public void UpdateGroupPosition(Vector3 pos) 4375 public void UpdateGroupPosition(Vector3 newPos)
4354 { 4376 {
4355 if ((pos.X != GroupPosition.X) || 4377 Vector3 oldPos = GroupPosition;
4356 (pos.Y != GroupPosition.Y) || 4378
4357 (pos.Z != GroupPosition.Z)) 4379 if ((newPos.X != oldPos.X) ||
4380 (newPos.Y != oldPos.Y) ||
4381 (newPos.Z != oldPos.Z))
4358 { 4382 {
4359 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4360 GroupPosition = newPos; 4383 GroupPosition = newPos;
4361 ScheduleTerseUpdate(); 4384 ScheduleTerseUpdate();
4362 } 4385 }
4363 } 4386 }
4364 4387
4365 /// <summary> 4388 /// <summary>
4366 /// 4389 /// Update this part's offset position.
4367 /// </summary> 4390 /// </summary>
4368 /// <param name="pos"></param> 4391 /// <param name="pos"></param>
4369 public void UpdateOffSet(Vector3 pos) 4392 public void UpdateOffSet(Vector3 newPos)
4370 { 4393 {
4371 if ((pos.X != OffsetPosition.X) || 4394 Vector3 oldPos = OffsetPosition;
4372 (pos.Y != OffsetPosition.Y) ||
4373 (pos.Z != OffsetPosition.Z))
4374 {
4375 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4376 4395
4396 if ((newPos.X != oldPos.X) ||
4397 (newPos.Y != oldPos.Y) ||
4398 (newPos.Z != oldPos.Z))
4399 {
4377 if (ParentGroup.RootPart.GetStatusSandbox()) 4400 if (ParentGroup.RootPart.GetStatusSandbox())
4378 { 4401 {
4379 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4402 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -4520,7 +4543,7 @@ namespace OpenSim.Region.Framework.Scenes
4520 // For now, we use the NINJA naming scheme for identifying joints. 4543 // For now, we use the NINJA naming scheme for identifying joints.
4521 // In the future, we can support other joint specification schemes such as a 4544 // In the future, we can support other joint specification schemes such as a
4522 // custom checkbox in the viewer GUI. 4545 // custom checkbox in the viewer GUI.
4523 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4546 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4524 { 4547 {
4525 return IsHingeJoint() || IsBallJoint(); 4548 return IsHingeJoint() || IsBallJoint();
4526 } 4549 }
@@ -4642,6 +4665,11 @@ namespace OpenSim.Region.Framework.Scenes
4642 } 4665 }
4643 } 4666 }
4644*/ 4667*/
4668 if (pa != null)
4669 {
4670 pa.SetMaterial(Material);
4671 DoPhysicsPropertyUpdate(UsePhysics, true);
4672 }
4645 } 4673 }
4646 else // it already has a physical representation 4674 else // it already has a physical representation
4647 { 4675 {
@@ -5014,6 +5042,14 @@ namespace OpenSim.Region.Framework.Scenes
5014 oldTex.DefaultTexture = fallbackOldFace; 5042 oldTex.DefaultTexture = fallbackOldFace;
5015 } 5043 }
5016 5044
5045 // Materials capable viewers can send a ObjectImage packet
5046 // when nothing in TE has changed. MaterialID should be updated
5047 // by the RenderMaterials CAP handler, so updating it here may cause a
5048 // race condtion. Therefore, if no non-materials TE fields have changed,
5049 // we should ignore any changes and not update Shape.TextureEntry
5050
5051 bool otherFieldsChanged = false;
5052
5017 for (int i = 0 ; i < GetNumberOfSides(); i++) 5053 for (int i = 0 ; i < GetNumberOfSides(); i++)
5018 { 5054 {
5019 5055
@@ -5040,18 +5076,36 @@ namespace OpenSim.Region.Framework.Scenes
5040 // Max change, skip the rest of testing 5076 // Max change, skip the rest of testing
5041 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5077 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
5042 break; 5078 break;
5079
5080 if (!otherFieldsChanged)
5081 {
5082 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
5083 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
5084 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
5085 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
5086 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
5087 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
5088 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
5089 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
5090 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
5091 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
5092 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5093 }
5043 } 5094 }
5044 5095
5045 m_shape.TextureEntry = newTex.GetBytes(); 5096 if (changeFlags != 0 || otherFieldsChanged)
5046 if (changeFlags != 0) 5097 {
5047 TriggerScriptChangedEvent(changeFlags); 5098 m_shape.TextureEntry = newTex.GetBytes();
5048 UpdateFlag = UpdateRequired.FULL; 5099 if (changeFlags != 0)
5049 ParentGroup.HasGroupChanged = true; 5100 TriggerScriptChangedEvent(changeFlags);
5101 UpdateFlag = UpdateRequired.FULL;
5102 ParentGroup.HasGroupChanged = true;
5050 5103
5051 //This is madness.. 5104 //This is madness..
5052 //ParentGroup.ScheduleGroupForFullUpdate(); 5105 //ParentGroup.ScheduleGroupForFullUpdate();
5053 //This is sparta 5106 //This is sparta
5054 ScheduleFullUpdate(); 5107 ScheduleFullUpdate();
5108 }
5055 } 5109 }
5056 5110
5057 5111
@@ -5239,6 +5293,64 @@ namespace OpenSim.Region.Framework.Scenes
5239 { 5293 {
5240 ParentGroup.AddScriptLPS(count); 5294 ParentGroup.AddScriptLPS(count);
5241 } 5295 }
5296
5297 /// <summary>
5298 /// Sets a prim's owner and permissions when it's rezzed.
5299 /// </summary>
5300 /// <param name="item">The inventory item from which the item was rezzed</param>
5301 /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
5302 /// <param name="scene">The scene the prim is being rezzed into</param>
5303 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
5304 {
5305 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
5306 {
5307 if (scene.Permissions.PropagatePermissions())
5308 {
5309 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
5310 {
5311 // Apply the item's permissions to the object
5312 //LogPermissions("Before applying item permissions");
5313 if (userInventory)
5314 {
5315 EveryoneMask = item.EveryOnePermissions;
5316 NextOwnerMask = item.NextPermissions;
5317 }
5318 else
5319 {
5320 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
5321 EveryoneMask = item.EveryOnePermissions;
5322 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
5323 NextOwnerMask = item.NextPermissions;
5324 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
5325 GroupMask = item.GroupPermissions;
5326 }
5327 //LogPermissions("After applying item permissions");
5328 }
5329 }
5330
5331 GroupMask = 0; // DO NOT propagate here
5332 }
5333
5334 if (OwnerID != item.Owner)
5335 {
5336 //LogPermissions("Before ApplyNextOwnerPermissions");
5337 ApplyNextOwnerPermissions();
5338 //LogPermissions("After ApplyNextOwnerPermissions");
5339
5340 LastOwnerID = OwnerID;
5341 OwnerID = item.Owner;
5342 Inventory.ChangeInventoryOwner(item.Owner);
5343 }
5344 }
5345
5346 /// <summary>
5347 /// Logs the prim's permissions. Useful when debugging permission problems.
5348 /// </summary>
5349 /// <param name="message"></param>
5350 private void LogPermissions(String message)
5351 {
5352 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
5353 }
5242 5354
5243 public void ApplyNextOwnerPermissions() 5355 public void ApplyNextOwnerPermissions()
5244 { 5356 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d04d87b..8893cc0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -696,7 +696,8 @@ namespace OpenSim.Region.Framework.Scenes
696 /// </param> 696 /// </param>
697 public void StopScriptInstance(TaskInventoryItem item) 697 public void StopScriptInstance(TaskInventoryItem item)
698 { 698 {
699 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); 699 if (m_part.ParentGroup.Scene != null)
700 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
700 701
701 // At the moment, even stopped scripts are counted as active, which is probably wrong. 702 // At the moment, even stopped scripts are counted as active, which is probably wrong.
702// m_part.ParentGroup.AddActiveScriptCount(-1); 703// m_part.ParentGroup.AddActiveScriptCount(-1);
@@ -880,8 +881,8 @@ namespace OpenSim.Region.Framework.Scenes
880 881
881 return items; 882 return items;
882 } 883 }
883 884
884 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 885 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
885 { 886 {
886 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
887 888
@@ -890,70 +891,58 @@ namespace OpenSim.Region.Framework.Scenes
890 m_log.WarnFormat( 891 m_log.WarnFormat(
891 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
892 item.AssetID, item.Name, m_part.Name); 893 item.AssetID, item.Name, m_part.Name);
893 return null; 894 objlist = null;
895 veclist = null;
896 return false;
894 } 897 }
895 898
896 string xmlData = Utils.BytesToString(rezAsset.Data); 899 Vector3 bbox;
897 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 900 float offsetHeight;
898 901
899 group.RootPart.AttachPoint = group.RootPart.Shape.State; 902 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
900 group.RootPart.AttachOffset = group.AbsolutePosition;
901 group.RootPart.AttachRotation = group.GroupRotation;
902 903
903 group.ResetIDs(); 904 for (int i = 0; i < objlist.Count; i++)
904 905 {
905 SceneObjectPart rootPart = group.GetPart(group.UUID); 906 SceneObjectGroup group = objlist[i];
906 907
907 // Since renaming the item in the inventory does not affect the name stored 908 group.RootPart.AttachPoint = group.RootPart.Shape.State;
908 // in the serialization, transfer the correct name from the inventory to the 909 group.RootPart.AttachOffset = group.AbsolutePosition;
909 // object itself before we rez. 910 group.RootPart.AttachRotation = group.GroupRotation;
910 rootPart.Name = item.Name;
911 rootPart.Description = item.Description;
912 911
913 SceneObjectPart[] partList = group.Parts; 912 group.ResetIDs();
914 913
915 group.SetGroup(m_part.GroupID, null); 914 SceneObjectPart rootPart = group.GetPart(group.UUID);
916 915
917 // TODO: Remove magic number badness 916 // Since renaming the item in the inventory does not affect the name stored
918 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 917 // in the serialization, transfer the correct name from the inventory to the
919 { 918 // object itself before we rez.
920 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) 919 // Only do these for the first object if we are rezzing a coalescence.
920 if (i == 0)
921 { 921 {
922 foreach (SceneObjectPart part in partList) 922 rootPart.Name = item.Name;
923 { 923 rootPart.Description = item.Description;
924 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
925 part.EveryoneMask = item.EveryonePermissions;
926 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
927 part.NextOwnerMask = item.NextPermissions;
928 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
929 part.GroupMask = item.GroupPermissions;
930 }
931
932 group.ApplyNextOwnerPermissions();
933 } 924 }
934 }
935 925
936 foreach (SceneObjectPart part in partList) 926 group.SetGroup(m_part.GroupID, null);
937 { 927
938 // TODO: Remove magic number badness 928 foreach (SceneObjectPart part in group.Parts)
939 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
940 { 929 {
941 part.LastOwnerID = part.OwnerID; 930 // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :)
942 part.OwnerID = item.OwnerID; 931 InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID);
943 part.Inventory.ChangeInventoryOwner(item.OwnerID); 932 dest.BasePermissions = item.BasePermissions;
933 dest.CurrentPermissions = item.CurrentPermissions;
934 dest.EveryOnePermissions = item.EveryonePermissions;
935 dest.GroupPermissions = item.GroupPermissions;
936 dest.NextPermissions = item.NextPermissions;
937 dest.Flags = item.Flags;
938
939 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
944 } 940 }
945 941
946 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 942 rootPart.TrimPermissions();
947 part.EveryoneMask = item.EveryonePermissions;
948 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
949 part.NextOwnerMask = item.NextPermissions;
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
951 part.GroupMask = item.GroupPermissions;
952 } 943 }
953 944
954 rootPart.TrimPermissions(); 945 return true;
955
956 return group;
957 } 946 }
958 947
959 /// <summary> 948 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7004d23..f57d4fe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,7 +29,9 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using Nini.Config;
@@ -73,21 +75,50 @@ namespace OpenSim.Region.Framework.Scenes
73 75
74 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
75 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
76// ~ScenePresence() 80// ~ScenePresence()
77// { 81// {
78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 83// }
80 84
81 private void TriggerScenePresenceUpdated() 85 public void TriggerScenePresenceUpdated()
82 { 86 {
83 if (m_scene != null) 87 if (m_scene != null)
84 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
85 } 89 }
86 90
87 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
88
89 public PresenceType PresenceType { get; private set; } 91 public PresenceType PresenceType { get; private set; }
90 92
93 private ScenePresenceStateMachine m_stateMachine;
94
95 /// <summary>
96 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
97 /// for more details.
98 /// </summary>
99 public ScenePresenceState LifecycleState
100 {
101 get
102 {
103 return m_stateMachine.GetState();
104 }
105
106 set
107 {
108 m_stateMachine.SetState(value);
109 }
110 }
111
112 /// <summary>
113 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
114 /// the viewer fires these in quick succession.
115 /// </summary>
116 /// <remarks>
117 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
118 /// regulation done there.
119 /// </remarks>
120 private object m_completeMovementLock = new object();
121
91// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 122// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
92 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 123 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
93 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 124 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -142,6 +173,8 @@ namespace OpenSim.Region.Framework.Scenes
142 private Vector3 m_lastVelocity; 173 private Vector3 m_lastVelocity;
143 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 174 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
144 175
176 private bool m_followCamAuto = false;
177
145 178
146 private Vector3? m_forceToApply; 179 private Vector3? m_forceToApply;
147 private int m_userFlags; 180 private int m_userFlags;
@@ -200,7 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
200 private float m_sitAvatarHeight = 2.0f; 233 private float m_sitAvatarHeight = 2.0f;
201 234
202 private Vector3 m_lastChildAgentUpdatePosition; 235 private Vector3 m_lastChildAgentUpdatePosition;
203 private Vector3 m_lastChildAgentUpdateCamPosition; 236// private Vector3 m_lastChildAgentUpdateCamPosition;
204 237
205 private const int LAND_VELOCITYMAG_MAX = 12; 238 private const int LAND_VELOCITYMAG_MAX = 12;
206 239
@@ -290,9 +323,37 @@ namespace OpenSim.Region.Framework.Scenes
290 /// </summary> 323 /// </summary>
291 private Vector3 posLastSignificantMove; 324 private Vector3 posLastSignificantMove;
292 325
293 // For teleports and crossings callbacks 326 #region For teleports and crossings callbacks
294 string m_callbackURI; 327
295 UUID m_originRegionID; 328 /// <summary>
329 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
330 /// </summary>
331 private string m_callbackURI;
332
333 /// <summary>
334 /// Records the region from which this presence originated, if not from login.
335 /// </summary>
336 /// <remarks>
337 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
338 /// CompleteMovement and made the previous child agent a root agent.
339 /// </remarks>
340 private UUID m_originRegionID;
341
342 /// <summary>
343 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
344 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
345 /// it is a value type.
346 /// </summary>
347 private object m_originRegionIDAccessLock = new object();
348
349 /// <summary>
350 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
351 /// teleport is reusing the connection.
352 /// </summary>
353 /// <remarks>May be refactored or move somewhere else soon.</remarks>
354 public bool DoNotCloseAfterTeleport { get; set; }
355
356 #endregion
296 357
297 /// <value> 358 /// <value>
298 /// Script engines present in the scene 359 /// Script engines present in the scene
@@ -309,15 +370,12 @@ namespace OpenSim.Region.Framework.Scenes
309 /// <summary> 370 /// <summary>
310 /// Record user movement inputs. 371 /// Record user movement inputs.
311 /// </summary> 372 /// </summary>
312 public byte MovementFlag { get; private set; } 373 public uint MovementFlag { get; private set; }
313 374
314 private bool m_updateflag; 375 /// <summary>
315 376 /// Is the agent stop control flag currently active?
316 public bool Updated 377 /// </summary>
317 { 378 public bool AgentControlStopActive { get; private set; }
318 set { m_updateflag = value; }
319 get { return m_updateflag; }
320 }
321 379
322 private bool m_invulnerable = true; 380 private bool m_invulnerable = true;
323 381
@@ -462,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes
462 } 520 }
463 else 521 else
464 { 522 {
523// m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
465 // Obtain the correct position of a seated avatar. 524 // Obtain the correct position of a seated avatar.
466 // In addition to providing the correct position while 525 // In addition to providing the correct position while
467 // the avatar is seated, this value will also 526 // the avatar is seated, this value will also
@@ -485,7 +544,7 @@ namespace OpenSim.Region.Framework.Scenes
485 } 544 }
486 set 545 set
487 { 546 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 547// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
489// Util.PrintCallStack(); 548// Util.PrintCallStack();
490 549
491 if (PhysicsActor != null) 550 if (PhysicsActor != null)
@@ -502,10 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
502 561
503 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 562 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
504 if (ParentID == 0) 563 if (ParentID == 0)
505 {
506 m_pos = value; 564 m_pos = value;
507// ParentPosition = Vector3.Zero;
508 }
509 565
510 //m_log.DebugFormat( 566 //m_log.DebugFormat(
511 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 567 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -768,6 +824,14 @@ namespace OpenSim.Region.Framework.Scenes
768 set { m_speedModifier = value; } 824 set { m_speedModifier = value; }
769 } 825 }
770 826
827 /// <summary>
828 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
829 /// </summary>
830 /// <remarks>
831 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
832 /// </remarks>
833 private float AgentControlStopSlowWhilstMoving = 0.5f;
834
771 private bool m_forceFly; 835 private bool m_forceFly;
772 836
773 public bool ForceFly 837 public bool ForceFly
@@ -795,7 +859,7 @@ namespace OpenSim.Region.Framework.Scenes
795 859
796 public ScenePresence( 860 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 861 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 862 {
799 AttachmentsSyncLock = new Object(); 863 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 864 AllowMovement = true;
801 IsChildAgent = true; 865 IsChildAgent = true;
@@ -841,6 +905,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 905 SetDirectionVectors();
842 906
843 Appearance = appearance; 907 Appearance = appearance;
908
909 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 910 }
845 911
846 private void RegionHeartbeatEnd(Scene scene) 912 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +940,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 940 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 941 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 942 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
943 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 944 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 945 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 946 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -927,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <summary> 994 /// <summary>
928 /// Turns a child agent into a root agent. 995 /// Turns a child agent into a root agent.
929 /// </summary> 996 /// </summary>
997 /// <remarks>
930 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 998 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
931 /// avatar is actual in the sim. They can perform all actions. 999 /// avatar is actual in the sim. They can perform all actions.
932 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1000 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -934,48 +1002,56 @@ namespace OpenSim.Region.Framework.Scenes
934 /// 1002 ///
935 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1003 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
936 /// delays that crossing. 1004 /// delays that crossing.
937 /// </summary> 1005 /// </remarks>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 1006 private bool MakeRootAgent(Vector3 pos, bool isFlying)
939 { 1007 {
940 m_log.DebugFormat( 1008 lock (m_completeMovementLock)
941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName);
943
944 if (ParentUUID != UUID.Zero)
945 { 1009 {
946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1010 if (!IsChildAgent)
947 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1011 return false;
948 if (part == null) 1012
1013 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1014
1015 // m_log.InfoFormat(
1016 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1017 // Name, m_scene.RegionInfo.RegionName);
1018
1019 if (ParentUUID != UUID.Zero)
949 { 1020 {
950 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1021 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1022 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1023 if (part == null)
1024 {
1025 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1026 }
1027 else
1028 {
1029 part.ParentGroup.AddAvatar(UUID);
1030 if (part.SitTargetPosition != Vector3.Zero)
1031 part.SitTargetAvatar = UUID;
1032 // ParentPosition = part.GetWorldPosition();
1033 ParentID = part.LocalId;
1034 ParentPart = part;
1035 m_pos = PrevSitOffset;
1036 // pos = ParentPosition;
1037 pos = part.GetWorldPosition();
1038 }
1039 ParentUUID = UUID.Zero;
1040
1041 // Animator.TrySetMovementAnimation("SIT");
951 } 1042 }
952 else 1043 else
953 { 1044 {
954 part.ParentGroup.AddAvatar(UUID); 1045 IsLoggingIn = false;
955 if (part.SitTargetPosition != Vector3.Zero)
956 part.SitTargetAvatar = UUID;
957// ParentPosition = part.GetWorldPosition();
958 ParentID = part.LocalId;
959 ParentPart = part;
960 m_pos = PrevSitOffset;
961// pos = ParentPosition;
962 pos = part.GetWorldPosition();
963 } 1046 }
964 ParentUUID = UUID.Zero;
965 1047
966 IsChildAgent = false; 1048 IsChildAgent = false;
967
968// Animator.TrySetMovementAnimation("SIT");
969 } 1049 }
970 else
971 {
972 IsChildAgent = false;
973 IsLoggingIn = false;
974 }
975
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
977 1050
978 IsChildAgent = false; 1051 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1052 // set and prevent the close of the connection on a subsequent re-teleport.
1053 // Should not be needed if we are not trying to tell this region to close
1054// DoNotCloseAfterTeleport = false;
979 1055
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1056 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1057 if (gm != null)
@@ -1116,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes
1116 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently 1192 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1117 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are 1193 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data. 1194 // not transporting the required data.
1119 lock (m_attachments) 1195 //
1196 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1197 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1198 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1199 // not transporting the required data.
1200 //
1201 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1202 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1203 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1204 //
1205 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1206 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1207 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1208 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1209 //
1210 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1211 // be locked, allowing race conditions if other code changes the attachments list.
1212 List<SceneObjectGroup> attachments = GetAttachments();
1213
1214 if (attachments.Count > 0)
1120 { 1215 {
1121 if (HasAttachments()) 1216 m_log.DebugFormat(
1122 { 1217 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1123 m_log.DebugFormat(
1124 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1125 1218
1126 // Resume scripts 1219 // Resume scripts
1127 Util.FireAndForget(delegate(object x) { 1220 foreach (SceneObjectGroup sog in attachments)
1128 foreach (SceneObjectGroup sog in m_attachments) 1221 {
1129 { 1222 sog.ScheduleGroupForFullUpdate();
1130 sog.ScheduleGroupForFullUpdate(); 1223 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1224 sog.ResumeScripts();
1132 sog.ResumeScripts();
1133 }
1134 });
1135 } 1225 }
1136 } 1226 }
1137 } 1227 }
@@ -1153,7 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes
1153 1243
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1244 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1155 1245
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1246 return true;
1157 } 1247 }
1158 1248
1159 public int GetStateSource() 1249 public int GetStateSource()
@@ -1306,7 +1396,26 @@ namespace OpenSim.Region.Framework.Scenes
1306 1396
1307 public void StopFlying() 1397 public void StopFlying()
1308 { 1398 {
1309 ControllingClient.StopFlying(this); 1399 Vector3 pos = AbsolutePosition;
1400 if (Appearance.AvatarHeight != 127.0f)
1401 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1402 else
1403 pos += new Vector3(0f, 0f, (1.56f / 6f));
1404
1405 AbsolutePosition = pos;
1406
1407 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1408 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1409 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1410 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1411
1412 // why are we still testing for this really old height value default???
1413 if (Appearance.AvatarHeight != 127.0f)
1414 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1415 else
1416 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1417
1418 ControllingClient.SendAgentTerseUpdate(this);
1310 } 1419 }
1311 1420
1312 /// <summary> 1421 /// <summary>
@@ -1480,6 +1589,37 @@ namespace OpenSim.Region.Framework.Scenes
1480 1589
1481 } 1590 }
1482 1591
1592 private bool WaitForUpdateAgent(IClientAPI client)
1593 {
1594 // Before the source region executes UpdateAgent
1595 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1596 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1597 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1598 int count = 50;
1599 UUID originID;
1600
1601 lock (m_originRegionIDAccessLock)
1602 originID = m_originRegionID;
1603
1604 while (originID.Equals(UUID.Zero) && count-- > 0)
1605 {
1606 lock (m_originRegionIDAccessLock)
1607 originID = m_originRegionID;
1608
1609 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1610 Thread.Sleep(200);
1611 }
1612
1613 if (originID.Equals(UUID.Zero))
1614 {
1615 // Movement into region will fail
1616 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1617 return false;
1618 }
1619
1620 return true;
1621 }
1622
1483 /// <summary> 1623 /// <summary>
1484 /// Complete Avatar's movement into the region. 1624 /// Complete Avatar's movement into the region.
1485 /// </summary> 1625 /// </summary>
@@ -1493,9 +1633,18 @@ namespace OpenSim.Region.Framework.Scenes
1493 { 1633 {
1494// DateTime startTime = DateTime.Now; 1634// DateTime startTime = DateTime.Now;
1495 1635
1496 m_log.DebugFormat( 1636 m_log.InfoFormat(
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1637 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1638 client.Name, Scene.Name, AbsolutePosition);
1639
1640 // Make sure it's not a login agent. We don't want to wait for updates during login
1641 if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1642 {
1643 // Let's wait until UpdateAgent (called by departing region) is done
1644 if (!WaitForUpdateAgent(client))
1645 // The sending region never sent the UpdateAgent data, we have to refuse
1646 return;
1647 }
1499 1648
1500 Vector3 look = Velocity; 1649 Vector3 look = Velocity;
1501 1650
@@ -1517,12 +1666,25 @@ namespace OpenSim.Region.Framework.Scenes
1517 } 1666 }
1518 1667
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1668 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1520 MakeRootAgent(AbsolutePosition, flying); 1669 if (!MakeRootAgent(AbsolutePosition, flying))
1670 {
1671 m_log.DebugFormat(
1672 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1673 Name, Scene.Name);
1674
1675 return;
1676 }
1677
1678 // Tell the client that we're totally ready
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1679 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1522 1680
1681 // Remember in HandleUseCircuitCode, we delayed this to here
1682 if (m_teleportFlags > 0)
1683 SendInitialDataToMe();
1684
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1685// m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1524 1686
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1687 if (!string.IsNullOrEmpty(m_callbackURI))
1526 { 1688 {
1527 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1689 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1528 // CompleteMovement() is executed synchronously. However, it might be better to delay the release 1690 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
@@ -1535,7 +1697,12 @@ namespace OpenSim.Region.Framework.Scenes
1535 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1697 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1536 client.Name, client.AgentId, m_callbackURI); 1698 client.Name, client.AgentId, m_callbackURI);
1537 1699
1538 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1700 UUID originID;
1701
1702 lock (m_originRegionIDAccessLock)
1703 originID = m_originRegionID;
1704
1705 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1539 m_callbackURI = null; 1706 m_callbackURI = null;
1540 } 1707 }
1541// else 1708// else
@@ -1550,7 +1717,6 @@ namespace OpenSim.Region.Framework.Scenes
1550 // Create child agents in neighbouring regions 1717 // Create child agents in neighbouring regions
1551 if (openChildAgents && !IsChildAgent) 1718 if (openChildAgents && !IsChildAgent)
1552 { 1719 {
1553
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1720 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1555 if (m_agentTransfer != null) 1721 if (m_agentTransfer != null)
1556 m_agentTransfer.EnableChildAgents(this); 1722 m_agentTransfer.EnableChildAgents(this);
@@ -1573,6 +1739,7 @@ namespace OpenSim.Region.Framework.Scenes
1573// m_log.DebugFormat( 1739// m_log.DebugFormat(
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1740// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1741// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1742
1576 } 1743 }
1577 1744
1578 /// <summary> 1745 /// <summary>
@@ -1653,9 +1820,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 1820 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1821 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 1822 {
1656// m_log.DebugFormat( 1823 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 1824 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 1825 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 1826
1660 if (IsChildAgent) 1827 if (IsChildAgent)
1661 { 1828 {
@@ -1663,10 +1830,6 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 1830 return;
1664 } 1831 }
1665 1832
1666 ++m_movementUpdateCount;
1667 if (m_movementUpdateCount < 1)
1668 m_movementUpdateCount = 1;
1669
1670 #region Sanity Checking 1833 #region Sanity Checking
1671 1834
1672 // This is irritating. Really. 1835 // This is irritating. Really.
@@ -1697,21 +1860,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 1860
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 1861 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 1862
1700 // Camera location in world. We'll need to raytrace
1701 // from this location from time to time.
1702 CameraPosition = agentData.CameraCenter;
1703 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
1704 {
1705 ReprioritizeUpdates();
1706 m_lastCameraPosition = CameraPosition;
1707 }
1708
1709 // Use these three vectors to figure out what the agent is looking at
1710 // Convert it to a Matrix and/or Quaternion
1711 CameraAtAxis = agentData.CameraAtAxis;
1712 CameraLeftAxis = agentData.CameraLeftAxis;
1713 CameraUpAxis = agentData.CameraUpAxis;
1714
1715 // The Agent's Draw distance setting 1863 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 1864 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 1865 // changes, then start using the agent's drawdistance rather than the
@@ -1783,9 +1931,16 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 1931 // Here's where you get them.
1784 m_AgentControlFlags = flags; 1932 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 1933 m_headrotation = agentData.HeadRotation;
1934 byte oldState = State;
1786 State = agentData.State; 1935 State = agentData.State;
1787 1936
1937 // We need to send this back to the client in order to stop the edit beams
1938 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
1939 ControllingClient.SendAgentTerseUpdate(this);
1940
1788 PhysicsActor actor = PhysicsActor; 1941 PhysicsActor actor = PhysicsActor;
1942
1943 // This will be the case if the agent is sitting on the groudn or on an object.
1789 if (actor == null) 1944 if (actor == null)
1790 { 1945 {
1791 SendControlsToScripts(flagsForScripts); 1946 SendControlsToScripts(flagsForScripts);
@@ -1794,12 +1949,13 @@ namespace OpenSim.Region.Framework.Scenes
1794 1949
1795 if (AllowMovement && !SitGround) 1950 if (AllowMovement && !SitGround)
1796 { 1951 {
1797 Quaternion bodyRotation = agentData.BodyRotation; 1952// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1953
1798 bool update_rotation = false; 1954 bool update_rotation = false;
1799 1955
1800 if (bodyRotation != Rotation) 1956 if (agentData.BodyRotation != Rotation)
1801 { 1957 {
1802 Rotation = bodyRotation; 1958 Rotation = agentData.BodyRotation;
1803 update_rotation = true; 1959 update_rotation = true;
1804 } 1960 }
1805 1961
@@ -1845,10 +2001,7 @@ namespace OpenSim.Region.Framework.Scenes
1845 else 2001 else
1846 dirVectors = Dir_Vectors; 2002 dirVectors = Dir_Vectors;
1847 2003
1848 // The fact that MovementFlag is a byte needs to be fixed
1849 // it really should be a uint
1850 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2004 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
1851 uint nudgehack = 250;
1852 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2005 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1853 { 2006 {
1854 if (((uint)flags & (uint)DCF) != 0) 2007 if (((uint)flags & (uint)DCF) != 0)
@@ -1865,29 +2018,19 @@ namespace OpenSim.Region.Framework.Scenes
1865 // Why did I get this? 2018 // Why did I get this?
1866 } 2019 }
1867 2020
1868 if ((MovementFlag & (byte)(uint)DCF) == 0) 2021 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive)
1869 { 2022 {
1870 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1871 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1872 {
1873 MovementFlag |= (byte)nudgehack;
1874 }
1875
1876 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2023 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1877 MovementFlag += (byte)(uint)DCF; 2024 MovementFlag += (uint)DCF;
1878 update_movementflag = true; 2025 update_movementflag = true;
1879 } 2026 }
1880 } 2027 }
1881 else 2028 else
1882 { 2029 {
1883 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2030 if ((MovementFlag & (uint)DCF) != 0)
1884 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1885 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1886 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1887 ) // This or is for Nudge forward
1888 { 2031 {
1889 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2032 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1890 MovementFlag -= ((byte)(uint)DCF); 2033 MovementFlag -= (uint)DCF;
1891 update_movementflag = true; 2034 update_movementflag = true;
1892 2035
1893 /* 2036 /*
@@ -1907,6 +2050,13 @@ namespace OpenSim.Region.Framework.Scenes
1907 i++; 2050 i++;
1908 } 2051 }
1909 2052
2053 // Detect AGENT_CONTROL_STOP state changes
2054 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2055 {
2056 AgentControlStopActive = !AgentControlStopActive;
2057 update_movementflag = true;
2058 }
2059
1910 if (MovingToTarget) 2060 if (MovingToTarget)
1911 { 2061 {
1912 // If the user has pressed a key then we want to cancel any move to target. 2062 // If the user has pressed a key then we want to cancel any move to target.
@@ -1932,53 +2082,79 @@ namespace OpenSim.Region.Framework.Scenes
1932 // Only do this if we're flying 2082 // Only do this if we're flying
1933 if (Flying && !ForceFly) 2083 if (Flying && !ForceFly)
1934 { 2084 {
1935 // Landing detection code 2085 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1936 2086 if (AgentControlStopActive)
1937 // Are the landing controls requirements filled?
1938 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1939 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1940
1941 //m_log.Debug("[CONTROL]: " +flags);
1942 // Applies a satisfying roll effect to the avatar when flying.
1943 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
1944 {
1945 ApplyFlyingRoll(
1946 FLY_ROLL_RADIANS_PER_UPDATE,
1947 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1948 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1949 }
1950 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
1951 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1952 { 2087 {
1953 ApplyFlyingRoll( 2088 agent_control_v3 = Vector3.Zero;
1954 -FLY_ROLL_RADIANS_PER_UPDATE,
1955 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1956 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1957 } 2089 }
1958 else 2090 else
1959 { 2091 {
1960 if (m_AngularVelocity.Z != 0) 2092 // Landing detection code
1961 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1962 }
1963 2093
1964 if (Flying && IsColliding && controlland) 2094 // Are the landing controls requirements filled?
1965 { 2095 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1966 // nesting this check because LengthSquared() is expensive and we don't 2096 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1967 // want to do it every step when flying. 2097
1968 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2098 //m_log.Debug("[CONTROL]: " +flags);
1969 StopFlying(); 2099 // Applies a satisfying roll effect to the avatar when flying.
2100 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2101 {
2102 ApplyFlyingRoll(
2103 FLY_ROLL_RADIANS_PER_UPDATE,
2104 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2105 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2106 }
2107 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2108 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2109 {
2110 ApplyFlyingRoll(
2111 -FLY_ROLL_RADIANS_PER_UPDATE,
2112 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2113 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2114 }
2115 else
2116 {
2117 if (m_AngularVelocity.Z != 0)
2118 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2119 }
2120
2121 if (Flying && IsColliding && controlland)
2122 {
2123 // nesting this check because LengthSquared() is expensive and we don't
2124 // want to do it every step when flying.
2125 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2126 StopFlying();
2127 }
1970 } 2128 }
1971 } 2129 }
1972 2130
2131// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2132
1973 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2133 // If the agent update does move the avatar, then calculate the force ready for the velocity update,
1974 // which occurs later in the main scene loop 2134 // which occurs later in the main scene loop
1975 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2135 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2136 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2137 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2138 // avatar location in place).
2139 if (update_movementflag
2140 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1976 { 2141 {
1977// m_log.DebugFormat( 2142// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
1978// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 2143// {
1979// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 2144// m_log.DebugFormat(
2145// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2146// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2147// update_movementflag, MovementFlag, update_rotation);
1980 2148
1981 AddNewMovement(agent_control_v3); 2149 float speedModifier;
2150
2151 if (AgentControlStopActive)
2152 speedModifier = AgentControlStopSlowWhilstMoving;
2153 else
2154 speedModifier = 1;
2155
2156 AddNewMovement(agent_control_v3, speedModifier);
2157// }
1982 } 2158 }
1983// else 2159// else
1984// { 2160// {
@@ -1991,15 +2167,86 @@ namespace OpenSim.Region.Framework.Scenes
1991// } 2167// }
1992 2168
1993 if (update_movementflag && ParentID == 0) 2169 if (update_movementflag && ParentID == 0)
2170 {
2171// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1994 Animator.UpdateMovementAnimations(); 2172 Animator.UpdateMovementAnimations();
2173 }
1995 2174
1996 SendControlsToScripts(flagsForScripts); 2175 SendControlsToScripts(flagsForScripts);
1997 } 2176 }
1998 2177
2178 // We need to send this back to the client in order to see the edit beams
2179 if ((State & (uint)AgentState.Editing) != 0)
2180 ControllingClient.SendAgentTerseUpdate(this);
2181
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2182 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2183 }
2002 2184
2185
2186 /// <summary>
2187 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2188 /// </summary>
2189 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2190 {
2191 //m_log.DebugFormat(
2192 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2193 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2194
2195 if (IsChildAgent)
2196 {
2197 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2198 return;
2199 }
2200
2201 ++m_movementUpdateCount;
2202 if (m_movementUpdateCount < 1)
2203 m_movementUpdateCount = 1;
2204
2205// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2206
2207 // Camera location in world. We'll need to raytrace
2208 // from this location from time to time.
2209 CameraPosition = agentData.CameraCenter;
2210 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2211 {
2212 ReprioritizeUpdates();
2213 m_lastCameraPosition = CameraPosition;
2214 }
2215
2216 // Use these three vectors to figure out what the agent is looking at
2217 // Convert it to a Matrix and/or Quaternion
2218 CameraAtAxis = agentData.CameraAtAxis;
2219 CameraLeftAxis = agentData.CameraLeftAxis;
2220 CameraUpAxis = agentData.CameraUpAxis;
2221
2222 // The Agent's Draw distance setting
2223 // When we get to the point of re-computing neighbors everytime this
2224 // changes, then start using the agent's drawdistance rather than the
2225 // region's draw distance.
2226 // DrawDistance = agentData.Far;
2227 DrawDistance = Scene.DefaultDrawDistance;
2228
2229 // Check if Client has camera in 'follow cam' or 'build' mode.
2230 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2231
2232 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2233 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2234
2235
2236 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2237 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2238 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2239 {
2240 if (m_followCamAuto)
2241 {
2242 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2243 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2244 }
2245 }
2246
2247 TriggerScenePresenceUpdated();
2248 }
2249
2003 /// <summary> 2250 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2251 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2252 /// </summary>
@@ -2252,17 +2499,13 @@ namespace OpenSim.Region.Framework.Scenes
2252 { 2499 {
2253// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2500// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2254 2501
2502 bool satOnObject = IsSatOnObject;
2503 SceneObjectPart part = ParentPart;
2255 SitGround = false; 2504 SitGround = false;
2256 2505
2257/* move this down so avatar gets physical in the new position and not where it is siting 2506 if (satOnObject)
2258 if (PhysicsActor == null)
2259 AddToPhysicalScene(false);
2260 */
2261
2262 if (ParentID != 0)
2263 { 2507 {
2264 PrevSitOffset = m_pos; // Save sit offset 2508 PrevSitOffset = m_pos; // Save sit offset
2265 SceneObjectPart part = ParentPart;
2266 UnRegisterSeatControls(part.ParentGroup.UUID); 2509 UnRegisterSeatControls(part.ParentGroup.UUID);
2267 2510
2268 TaskInventoryDictionary taskIDict = part.TaskInventory; 2511 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2281,34 +2524,71 @@ namespace OpenSim.Region.Framework.Scenes
2281 } 2524 }
2282 2525
2283 part.ParentGroup.DeleteAvatar(UUID); 2526 part.ParentGroup.DeleteAvatar(UUID);
2284// ParentPosition = part.GetWorldPosition(); 2527 Vector3 sitPartWorldPosition = part.GetWorldPosition();
2285 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2528 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2286 2529
2287// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2288// ParentPosition = Vector3.Zero;
2289 m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2290 if (part.SitTargetAvatar == UUID)
2291 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2292
2293 ParentID = 0; 2530 ParentID = 0;
2294 ParentPart = null; 2531 ParentPart = null;
2295 2532
2296 if (PhysicsActor == null) 2533 Quaternion standRotation;
2297 AddToPhysicalScene(false);
2298 2534
2535 if (part.SitTargetAvatar == UUID)
2536 {
2537 standRotation = part.GetWorldRotation();
2538
2539 if (!part.IsRoot)
2540 standRotation = standRotation * part.SitTargetOrientation;
2541// standRotation = part.RotationOffset * part.SitTargetOrientation;
2542// else
2543// standRotation = part.SitTargetOrientation;
2544
2545 }
2546 else
2547 {
2548 standRotation = Rotation;
2549 }
2550
2551 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2552 //Vector3 standPos = ParentPosition;
2553
2554// Vector3 standPositionAdjustment
2555// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2556 Vector3 adjustmentForSitPosition = part.SitTargetPosition * part.GetWorldRotation();
2557
2558 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2559 // hardcoding here.
2560 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2561
2562 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPosition + adjustmentForSitPose;
2563
2564// m_log.DebugFormat(
2565// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2566// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2567
2568 Rotation = standRotation;
2569 AbsolutePosition = standPos;
2570 }
2571
2572 // We need to wait until we have calculated proper stand positions before sitting up the physical
2573 // avatar to avoid race conditions.
2574 if (PhysicsActor == null)
2575 AddToPhysicalScene(false);
2576
2577 if (satOnObject)
2578 {
2299 SendAvatarDataToAllAgents(); 2579 SendAvatarDataToAllAgents();
2300 m_requestedSitTargetID = 0; 2580 m_requestedSitTargetID = 0;
2301 2581
2302 part.RemoveSittingAvatar(UUID); 2582 part.RemoveSittingAvatar(UUID);
2303 2583
2304 if (part != null) 2584 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2306 } 2585 }
2307 2586
2308 else if (PhysicsActor == null) 2587 else if (PhysicsActor == null)
2309 AddToPhysicalScene(false); 2588 AddToPhysicalScene(false);
2310 2589
2311 Animator.TrySetMovementAnimation("STAND"); 2590 Animator.TrySetMovementAnimation("STAND");
2591 TriggerScenePresenceUpdated();
2312 } 2592 }
2313 2593
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2594 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2359,7 +2639,6 @@ namespace OpenSim.Region.Framework.Scenes
2359 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2639 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2360 2640
2361 bool canSit = false; 2641 bool canSit = false;
2362 Vector3 pos = part.AbsolutePosition + offset;
2363 2642
2364 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2643 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2365 { 2644 {
@@ -2369,6 +2648,17 @@ namespace OpenSim.Region.Framework.Scenes
2369 2648
2370 offset = part.SitTargetPosition; 2649 offset = part.SitTargetPosition;
2371 sitOrientation = part.SitTargetOrientation; 2650 sitOrientation = part.SitTargetOrientation;
2651
2652 if (!part.IsRoot)
2653 {
2654 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2655 sitOrientation = part.RotationOffset * sitOrientation;
2656 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2657// m_log.DebugFormat("Old sit offset {0}", offset);
2658 offset = offset * part.RotationOffset;
2659// m_log.DebugFormat("New sit offset {0}", offset);
2660 }
2661
2372 canSit = true; 2662 canSit = true;
2373 } 2663 }
2374 else 2664 else
@@ -2376,9 +2666,10 @@ namespace OpenSim.Region.Framework.Scenes
2376 if (PhysicsSit(part,offset)) // physics engine 2666 if (PhysicsSit(part,offset)) // physics engine
2377 return; 2667 return;
2378 2668
2669 Vector3 pos = part.AbsolutePosition + offset;
2670
2379 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2671 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2380 { 2672 {
2381
2382 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2673 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2383 canSit = true; 2674 canSit = true;
2384 } 2675 }
@@ -2404,10 +2695,14 @@ namespace OpenSim.Region.Framework.Scenes
2404 cameraEyeOffset = part.GetCameraEyeOffset(); 2695 cameraEyeOffset = part.GetCameraEyeOffset();
2405 forceMouselook = part.GetForceMouselook(); 2696 forceMouselook = part.GetForceMouselook();
2406 2697
2698 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2699 // being sat upon.
2700 offset += part.OffsetPosition;
2701
2407 ControllingClient.SendSitResponse( 2702 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2703 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2704
2410 m_requestedSitTargetUUID = targetID; 2705 m_requestedSitTargetUUID = part.UUID;
2411 2706
2412 HandleAgentSit(ControllingClient, UUID); 2707 HandleAgentSit(ControllingClient, UUID);
2413 2708
@@ -2435,7 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2730 if (part != null)
2436 { 2731 {
2437 m_requestedSitTargetID = part.LocalId; 2732 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2733 m_requestedSitTargetUUID = part.UUID;
2439 2734
2440 } 2735 }
2441 else 2736 else
@@ -2554,6 +2849,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 2849
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2850 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 2851 {
2852 if (IsChildAgent)
2853 return;
2854
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2855 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 2856
2559 if (part != null) 2857 if (part != null)
@@ -2603,24 +2901,40 @@ namespace OpenSim.Region.Framework.Scenes
2603 Vector3 up = new Vector3((float)x, (float)y, (float)z); 2901 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2604 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 2902 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2605 2903
2606 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 2904 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2905 Quaternion newRot;
2906
2907 if (part.IsRoot)
2908 {
2909 newRot = sitTargetOrient;
2910 }
2911 else
2912 {
2913 newPos = newPos * part.RotationOffset;
2914 newRot = part.RotationOffset * sitTargetOrient;
2915 }
2916
2917 newPos += part.OffsetPosition;
2918
2919 m_pos = newPos;
2920 Rotation = newRot;
2607 2921
2608// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2609 Rotation = sitTargetOrient;
2610// ParentPosition = part.AbsolutePosition; 2922// ParentPosition = part.AbsolutePosition;
2611 part.ParentGroup.AddAvatar(UUID);
2612 } 2923 }
2613 else 2924 else
2614 { 2925 {
2615 m_pos -= part.AbsolutePosition; 2926 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2927 // being sat upon.
2928 m_pos -= part.GroupPosition;
2929
2616// ParentPosition = part.AbsolutePosition; 2930// ParentPosition = part.AbsolutePosition;
2617 part.ParentGroup.AddAvatar(UUID);
2618 2931
2619// m_log.DebugFormat( 2932// m_log.DebugFormat(
2620// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2933// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2621// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 2934// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2622 } 2935 }
2623 2936
2937 part.ParentGroup.AddAvatar(UUID);
2624 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2938 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2625 ParentID = m_requestedSitTargetID; 2939 ParentID = m_requestedSitTargetID;
2626 m_AngularVelocity = Vector3.Zero; 2940 m_AngularVelocity = Vector3.Zero;
@@ -2634,14 +2948,19 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 2948 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 2949 Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 2950 SendAvatarDataToAllAgents();
2951 TriggerScenePresenceUpdated();
2637 } 2952 }
2638 } 2953 }
2639 2954
2640 public void HandleAgentSitOnGround() 2955 public void HandleAgentSitOnGround()
2641 { 2956 {
2957 if (IsChildAgent)
2958 return;
2959
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 2960// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 2961 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 2962 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
2963 TriggerScenePresenceUpdated();
2645 SitGround = true; 2964 SitGround = true;
2646 RemoveFromPhysicalScene(); 2965 RemoveFromPhysicalScene();
2647 } 2966 }
@@ -2658,11 +2977,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 2977 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 2978 {
2660 Animator.AddAnimation(animID, UUID.Zero); 2979 Animator.AddAnimation(animID, UUID.Zero);
2980 TriggerScenePresenceUpdated();
2661 } 2981 }
2662 2982
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 2983 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 2984 {
2665 Animator.RemoveAnimation(animID, false); 2985 Animator.RemoveAnimation(animID, false);
2986 TriggerScenePresenceUpdated();
2666 } 2987 }
2667 2988
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 2989 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2676,10 +2997,13 @@ namespace OpenSim.Region.Framework.Scenes
2676 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 2997 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2677 /// </summary> 2998 /// </summary>
2678 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2999 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2679 public void AddNewMovement(Vector3 vec) 3000 /// <param name="thisAddSpeedModifier">
3001 /// Optional additional speed modifier for this particular add. Default is 1</param>
3002 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
2680 { 3003 {
2681// m_log.DebugFormat( 3004// m_log.DebugFormat(
2682// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3005// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3006// vec, Rotation, thisAddSpeedModifier, Name);
2683 3007
2684 Vector3 direc = vec * Rotation; 3008 Vector3 direc = vec * Rotation;
2685 direc.Normalize(); 3009 direc.Normalize();
@@ -2697,7 +3021,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 if ((vec.Z == 0f) && !Flying) 3021 if ((vec.Z == 0f) && !Flying)
2698 direc.Z = 0f; // Prevent camera WASD up. 3022 direc.Z = 0f; // Prevent camera WASD up.
2699 3023
2700 direc *= 0.03f * 128f * SpeedModifier; 3024 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2701 3025
2702// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3026// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2703 3027
@@ -2843,6 +3167,7 @@ namespace OpenSim.Region.Framework.Scenes
2843 lastTerseUpdateToAllClientsTick = currentTick; 3167 lastTerseUpdateToAllClientsTick = currentTick;
2844 lastPositionSentToAllClients = OffsetPosition; 3168 lastPositionSentToAllClients = OffsetPosition;
2845 3169
3170// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
2846 m_scene.ForEachClient(SendTerseUpdateToClient); 3171 m_scene.ForEachClient(SendTerseUpdateToClient);
2847 } 3172 }
2848 TriggerScenePresenceUpdated(); 3173 TriggerScenePresenceUpdated();
@@ -2880,11 +3205,12 @@ namespace OpenSim.Region.Framework.Scenes
2880 SendOtherAgentsAppearanceToMe(); 3205 SendOtherAgentsAppearanceToMe();
2881 3206
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3207 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3208 foreach (EntityBase e in entities)
2884 { 3209 {
2885 if (e != null && e is SceneObjectGroup) 3210 if (e != null && e is SceneObjectGroup)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3211 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3212 }
3213
2888 }); 3214 });
2889 } 3215 }
2890 3216
@@ -2919,12 +3245,14 @@ namespace OpenSim.Region.Framework.Scenes
2919 // again here... this comes after the cached appearance check because the avatars 3245 // again here... this comes after the cached appearance check because the avatars
2920 // appearance goes into the avatar update packet 3246 // appearance goes into the avatar update packet
2921 SendAvatarDataToAllAgents(); 3247 SendAvatarDataToAllAgents();
3248
3249 // This invocation always shows up in the viewer logs as an error. Is it needed?
2922 SendAppearanceToAgent(this); 3250 SendAppearanceToAgent(this);
2923 3251
2924 // If we are using the the cached appearance then send it out to everyone 3252 // If we are using the the cached appearance then send it out to everyone
2925 if (cachedappearance) 3253 if (cachedappearance)
2926 { 3254 {
2927 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3255 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
2928 3256
2929 // If the avatars baked textures are all in the cache, then we have a 3257 // If the avatars baked textures are all in the cache, then we have a
2930 // complete appearance... send it out, if not, then we'll send it when 3258 // complete appearance... send it out, if not, then we'll send it when
@@ -3079,11 +3407,10 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3407 }
3080 3408
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3409 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3410 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3411 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3412 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3413// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3414
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3415 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3416 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3110,7 +3437,7 @@ namespace OpenSim.Region.Framework.Scenes
3110 cadu.Velocity = Velocity; 3437 cadu.Velocity = Velocity;
3111 3438
3112 AgentPosition agentpos = new AgentPosition(); 3439 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3440 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3114 3441
3115 // Let's get this out of the update loop 3442 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3443 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3294,11 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes
3294 } 3621 }
3295 } 3622 }
3296 3623
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 }
3301
3302 public void Reset() 3624 public void Reset()
3303 { 3625 {
3304// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3626// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3348,10 +3670,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 3670 if (byebyeRegions.Count > 0)
3349 { 3671 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 3672 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 3673
3352 { 3674 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 3675 string auth = string.Empty;
3354 }); 3676 if (acd != null)
3677 auth = acd.SessionID.ToString();
3678 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 3679 }
3356 3680
3357 foreach (ulong handle in byebyeRegions) 3681 foreach (ulong handle in byebyeRegions)
@@ -3392,7 +3716,7 @@ namespace OpenSim.Region.Framework.Scenes
3392 3716
3393 #region Child Agent Updates 3717 #region Child Agent Updates
3394 3718
3395 public void ChildAgentDataUpdate(AgentData cAgentData) 3719 public void UpdateChildAgent(AgentData cAgentData)
3396 { 3720 {
3397// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3721// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3398 if (!IsChildAgent) 3722 if (!IsChildAgent)
@@ -3402,15 +3726,17 @@ namespace OpenSim.Region.Framework.Scenes
3402 } 3726 }
3403 3727
3404 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3728 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3729
3405 private void RaiseUpdateThrottles() 3730 private void RaiseUpdateThrottles()
3406 { 3731 {
3407 m_scene.EventManager.TriggerThrottleUpdate(this); 3732 m_scene.EventManager.TriggerThrottleUpdate(this);
3408 } 3733 }
3734
3409 /// <summary> 3735 /// <summary>
3410 /// This updates important decision making data about a child agent 3736 /// This updates important decision making data about a child agent
3411 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3737 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3412 /// </summary> 3738 /// </summary>
3413 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 3739 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3414 { 3740 {
3415 if (!IsChildAgent) 3741 if (!IsChildAgent)
3416 return; 3742 return;
@@ -3452,6 +3778,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 3778
3453 cAgent.AgentID = UUID; 3779 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 3780 cAgent.RegionID = Scene.RegionInfo.RegionID;
3781 cAgent.SessionID = ControllingClient.SessionId;
3455 3782
3456 cAgent.Position = AbsolutePosition; 3783 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 3784 cAgent.Velocity = m_velocity;
@@ -3517,7 +3844,8 @@ namespace OpenSim.Region.Framework.Scenes
3517 3844
3518 private void CopyFrom(AgentData cAgent) 3845 private void CopyFrom(AgentData cAgent)
3519 { 3846 {
3520 m_originRegionID = cAgent.RegionID; 3847 lock (m_originRegionIDAccessLock)
3848 m_originRegionID = cAgent.RegionID;
3521 3849
3522 m_callbackURI = cAgent.CallbackURI; 3850 m_callbackURI = cAgent.CallbackURI;
3523// m_log.DebugFormat( 3851// m_log.DebugFormat(
@@ -3611,8 +3939,6 @@ namespace OpenSim.Region.Framework.Scenes
3611 { 3939 {
3612 Vector3 force = m_forceToApply.Value; 3940 Vector3 force = m_forceToApply.Value;
3613 3941
3614 Updated = true;
3615
3616 Velocity = force; 3942 Velocity = force;
3617 3943
3618 m_forceToApply = null; 3944 m_forceToApply = null;
@@ -3694,7 +4020,8 @@ namespace OpenSim.Region.Framework.Scenes
3694 4020
3695// if (m_updateCount > 0) 4021// if (m_updateCount > 0)
3696// { 4022// {
3697 Animator.UpdateMovementAnimations(); 4023 if (Animator.UpdateMovementAnimations())
4024 TriggerScenePresenceUpdated();
3698// m_updateCount--; 4025// m_updateCount--;
3699// } 4026// }
3700 4027
@@ -3858,6 +4185,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4185// Animator.Close();
3859 Animator = null; 4186 Animator = null;
3860 4187
4188 LifecycleState = ScenePresenceState.Removed;
3861 } 4189 }
3862 4190
3863 public void AddAttachment(SceneObjectGroup gobj) 4191 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
new file mode 100644
index 0000000..cae7fe5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Region.Framework.Scenes
31{
32 /// <summary>
33 /// The possible states that a scene presence can be in. This is currently orthagonal to whether a scene presence
34 /// is root or child.
35 /// </summary>
36 /// <remarks>
37 /// This is a state machine.
38 ///
39 /// [Entry] => Running
40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
42 /// Removing => Removed
43 ///
44 /// All other methods should only see the scene presence in running state - this is the normal operational state
45 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
46 /// </remarks>
47 public enum ScenePresenceState
48 {
49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
52 Removed, // The presence has been removed from the scene and is effectively dead.
53 // There is no exit from this state.
54 }
55
56 internal class ScenePresenceStateMachine
57 {
58 private ScenePresence m_sp;
59 private ScenePresenceState m_state;
60
61 internal ScenePresenceStateMachine(ScenePresence sp)
62 {
63 m_sp = sp;
64 m_state = ScenePresenceState.Running;
65 }
66
67 internal ScenePresenceState GetState()
68 {
69 return m_state;
70 }
71
72 /// <summary>
73 /// Updates the state of an agent that is already in transit.
74 /// </summary>
75 /// <param name='id'></param>
76 /// <param name='newState'></param>
77 /// <returns></returns>
78 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
79 internal void SetState(ScenePresenceState newState)
80 {
81 bool transitionOkay = false;
82
83 lock (this)
84 {
85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
97 transitionOkay = true;
98 }
99
100 if (!transitionOkay)
101 {
102 throw new Exception(
103 string.Format(
104 "Scene presence {0} is not allowed to move from state {1} to new state {2} in {3}",
105 m_sp.Name, m_state, newState, m_sp.Scene.Name));
106 }
107 else
108 {
109 m_state = newState;
110 }
111 }
112 }
113} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index ce4fb40..5372360 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); 365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound);
366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); 366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume);
367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); 367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
368 m_SOPXmlProcessors.Add("AttachedPos", ProcessAttachedPos);
368 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); 369 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
369 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); 370 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
370 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); 371 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
@@ -443,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
443 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); 444 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
444 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); 445 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
445 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); 446 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
447 m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
446 m_ShapeXmlProcessors.Add("State", ProcessShpState); 448 m_ShapeXmlProcessors.Add("State", ProcessShpState);
447 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); 449 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
448 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); 450 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@@ -798,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 800 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
799 } 801 }
800 802
803 private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
804 {
805 obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
806 }
807
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) 808 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 { 809 {
803 obj.DynAttrs.ReadXml(reader); 810 obj.DynAttrs.ReadXml(reader);
@@ -1099,6 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1099 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); 1106 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
1100 } 1107 }
1101 1108
1109 private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
1110 {
1111 shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
1112 }
1113
1102 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) 1114 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
1103 { 1115 {
1104 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); 1116 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@@ -1267,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1267 1279
1268 WriteUUID(writer, "CreatorID", sop.CreatorID, options); 1280 WriteUUID(writer, "CreatorID", sop.CreatorID, options);
1269 1281
1270 if (sop.CreatorData != null && sop.CreatorData != string.Empty) 1282 if (!string.IsNullOrEmpty(sop.CreatorData))
1271 writer.WriteElementString("CreatorData", sop.CreatorData); 1283 writer.WriteElementString("CreatorData", sop.CreatorData);
1272 else if (options.ContainsKey("home")) 1284 else if (options.ContainsKey("home"))
1273 { 1285 {
@@ -1345,8 +1357,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1357 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1346 if (sop.MediaUrl != null) 1358 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1359 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1360 WriteVector(writer, "AttachedPos", sop.AttachedPos);
1348 1361
1349 if (sop.DynAttrs.Count > 0) 1362 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1363 {
1351 writer.WriteStartElement("DynAttrs"); 1364 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer); 1365 sop.DynAttrs.WriteXml(writer);
@@ -1451,7 +1464,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1451 1464
1452 WriteUUID(writer, "CreatorID", item.CreatorID, options); 1465 WriteUUID(writer, "CreatorID", item.CreatorID, options);
1453 1466
1454 if (item.CreatorData != null && item.CreatorData != string.Empty) 1467 if (!string.IsNullOrEmpty(item.CreatorData))
1455 writer.WriteElementString("CreatorData", item.CreatorData); 1468 writer.WriteElementString("CreatorData", item.CreatorData);
1456 else if (options.ContainsKey("home")) 1469 else if (options.ContainsKey("home"))
1457 { 1470 {
@@ -1539,6 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1552 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1553 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1554 writer.WriteElementString("State", shp.State.ToString());
1555 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1556
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1557 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1558 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options);
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 5398ab9..bf32251 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -290,6 +290,9 @@ namespace OpenSim.Region.Framework.Scenes
290 290
291 private void statsHeartBeat(object sender, EventArgs e) 291 private void statsHeartBeat(object sender, EventArgs e)
292 { 292 {
293 if (!m_scene.Active)
294 return;
295
293 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; 296 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23];
294 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 297 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
295 298
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 9557cd0..95b30d5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,7 +33,9 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Framework.EntityTransfer;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess; 37using OpenSim.Region.CoreModules.Framework.InventoryAccess;
38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
37using OpenSim.Region.CoreModules.World.Permissions; 39using OpenSim.Region.CoreModules.World.Permissions;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
@@ -52,6 +54,24 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 [TestFixture] 54 [TestFixture]
53 public class SceneObjectDeRezTests : OpenSimTestCase 55 public class SceneObjectDeRezTests : OpenSimTestCase
54 { 56 {
57 [TestFixtureSetUp]
58 public void FixtureInit()
59 {
60 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
61 // This facility was added after the original async delete tests were written, so it may be possible now
62 // to not bother explicitly disabling their async (since everything will be running sync).
63 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
64 }
65
66 [TestFixtureTearDown]
67 public void TearDown()
68 {
69 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
70 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
71 // tests really shouldn't).
72 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
73 }
74
55 /// <summary> 75 /// <summary>
56 /// Test deleting an object from a scene. 76 /// Test deleting an object from a scene.
57 /// </summary> 77 /// </summary>
@@ -59,7 +79,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
59 public void TestDeRezSceneObject() 79 public void TestDeRezSceneObject()
60 { 80 {
61 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
62// log4net.Config.XmlConfigurator.Configure();
63 82
64 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 83 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
65 84
@@ -73,32 +92,77 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 92 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
74 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 93 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
75 sogd.Enabled = false; 94 sogd.Enabled = false;
76 95
77 SceneObjectPart part 96 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId);
78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 97 uint soLocalId = so.LocalId;
79 part.Name = "obj1";
80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81 98
82 List<uint> localIds = new List<uint>(); 99 List<uint> localIds = new List<uint>();
83 localIds.Add(part.LocalId); 100 localIds.Add(so.LocalId);
84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 101 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85 102
86 // Check that object isn't deleted until we crank the sogd handle. 103 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 104 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null); 105 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); 106 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90 107
91 sogd.InventoryDeQueueAndDelete(); 108 sogd.InventoryDeQueueAndDelete();
92 109
93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId); 110 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
94 Assert.That(retrievedPart2, Is.Null); 111 Assert.That(retrievedPart2, Is.Null);
112 }
113
114 /// <summary>
115 /// Test that child and root agents correctly receive KillObject notifications.
116 /// </summary>
117 [Test]
118 public void TestDeRezSceneObjectToAgents()
119 {
120 TestHelpers.InMethod();
121// TestHelpers.EnableLogging();
122
123 SceneHelpers sh = new SceneHelpers();
124 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
125 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
126
127 // We need this so that the creation of the root client for userB in sceneB can trigger the creation of a child client in sceneA
128 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
129 EntityTransferModule etmB = new EntityTransferModule();
130 IConfigSource config = new IniConfigSource();
131 IConfig modulesConfig = config.AddConfig("Modules");
132 modulesConfig.Set("EntityTransferModule", etmB.Name);
133 modulesConfig.Set("SimulationServices", lscm.Name);
134 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
135 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
136
137 // We need this for derez
138 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
139
140 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
141 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
142
143 TestClient clientA = (TestClient)SceneHelpers.AddScenePresence(sceneA, uaA).ControllingClient;
144
145 // This is the more long-winded route we have to take to get a child client created for userB in sceneA
146 // rather than just calling AddScenePresence() as for userA
147 AgentCircuitData acd = SceneHelpers.GenerateAgentData(uaB);
148 TestClient clientB = new TestClient(acd, sceneB);
149 List<TestClient> childClientsB = new List<TestClient>();
150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(clientB, childClientsB);
151
152 SceneHelpers.AddScenePresence(sceneB, clientB, acd);
153
154 SceneObjectGroup so = SceneHelpers.AddSceneObject(sceneA);
155 uint soLocalId = so.LocalId;
156
157 sceneA.DeleteSceneObject(so, false);
95 } 158 }
96 159
97 /// <summary> 160 /// <summary>
98 /// Test deleting an object from a scene where the deleter is not the owner 161 /// Test deleting an object from a scene where the deleter is not the owner
99 /// </summary> 162 /// </summary>
100 /// 163 /// <remarks>
101 /// This test assumes that the deleter is not a god. 164 /// This test assumes that the deleter is not a god.
165 /// </remarks>
102 [Test] 166 [Test]
103 public void TestDeRezSceneObjectNotOwner() 167 public void TestDeRezSceneObjectNotOwner()
104 { 168 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index bbfbbfc..1ff1329 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -111,6 +111,45 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); 111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
112 } 112 }
113 113
114 /// <summary>
115 /// Test that duplicate complete movement calls are ignored.
116 /// </summary>
117 /// <remarks>
118 /// If duplicate calls are not ignored then there is a risk of race conditions or other unexpected effects.
119 /// </remarks>
120 [Test]
121 public void TestDupeCompleteMovementCalls()
122 {
123 TestHelpers.InMethod();
124// TestHelpers.EnableLogging();
125
126 UUID spUuid = TestHelpers.ParseTail(0x1);
127
128 TestScene scene = new SceneHelpers().SetupScene();
129
130 int makeRootAgentEvents = 0;
131 scene.EventManager.OnMakeRootAgent += spi => makeRootAgentEvents++;
132
133 ScenePresence sp = SceneHelpers.AddScenePresence(scene, spUuid);
134
135 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
136
137 // Normally these would be invoked by a CompleteMovement message coming in to the UDP stack. But for
138 // convenience, here we will invoke it manually.
139 sp.CompleteMovement(sp.ControllingClient, true);
140
141 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
142
143 // Check rest of exepcted parameters.
144 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
145 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
146
147 Assert.That(sp.IsChildAgent, Is.False);
148 Assert.That(sp.UUID, Is.EqualTo(spUuid));
149
150 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
151 }
152
114 [Test] 153 [Test]
115 public void TestCreateDuplicateRootScenePresence() 154 public void TestCreateDuplicateRootScenePresence()
116 { 155 {
@@ -119,7 +158,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
119 158
120 UUID spUuid = TestHelpers.ParseTail(0x1); 159 UUID spUuid = TestHelpers.ParseTail(0x1);
121 160
161 // The etm is only invoked by this test to check whether an agent is still in transit if there is a dupe
162 EntityTransferModule etm = new EntityTransferModule();
163
164 IConfigSource config = new IniConfigSource();
165 IConfig modulesConfig = config.AddConfig("Modules");
166 modulesConfig.Set("EntityTransferModule", etm.Name);
167 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
168
169 // In order to run a single threaded regression test we do not want the entity transfer module waiting
170 // for a callback from the destination scene before removing its avatar data.
171 entityTransferConfig.Set("wait_for_callback", false);
172
122 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
174 SceneHelpers.SetupSceneModules(scene, config, etm);
123 SceneHelpers.AddScenePresence(scene, spUuid); 175 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid); 176 SceneHelpers.AddScenePresence(scene, spUuid);
125 177
@@ -133,7 +185,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 } 185 }
134 186
135 [Test] 187 [Test]
136 public void TestCloseAgent() 188 public void TestCloseClient()
137 { 189 {
138 TestHelpers.InMethod(); 190 TestHelpers.InMethod();
139// TestHelpers.EnableLogging(); 191// TestHelpers.EnableLogging();
@@ -141,7 +193,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 193 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 194 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 195
144 scene.IncomingCloseAgent(sp.UUID, false); 196 scene.CloseAgent(sp.UUID, false);
145 197
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 198 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 199 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
@@ -187,7 +239,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
187 // *** This is the second stage, where the client established a child agent/scene presence using the 239 // *** This is the second stage, where the client established a child agent/scene presence using the
188 // circuit code given to the scene in stage 1 *** 240 // circuit code given to the scene in stage 1 ***
189 TestClient client = new TestClient(acd, scene); 241 TestClient client = new TestClient(acd, scene);
190 scene.AddNewClient(client, PresenceType.User); 242 scene.AddNewAgent(client, PresenceType.User);
191 243
192 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 244 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
193 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 245 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -236,58 +288,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
236// Assert.That(childPresence, Is.Not.Null); 288// Assert.That(childPresence, Is.Not.Null);
237// Assert.That(childPresence.IsChildAgent, Is.True); 289// Assert.That(childPresence.IsChildAgent, Is.True);
238 } 290 }
239
240// /// <summary>
241// /// Test adding a root agent to a scene. Doesn't yet actually complete crossing the agent into the scene.
242// /// </summary>
243// [Test]
244// public void T010_TestAddRootAgent()
245// {
246// TestHelpers.InMethod();
247//
248// string firstName = "testfirstname";
249//
250// AgentCircuitData agent = new AgentCircuitData();
251// agent.AgentID = agent1;
252// agent.firstname = firstName;
253// agent.lastname = "testlastname";
254// agent.SessionID = UUID.Random();
255// agent.SecureSessionID = UUID.Random();
256// agent.circuitcode = 123;
257// agent.BaseFolder = UUID.Zero;
258// agent.InventoryFolder = UUID.Zero;
259// agent.startpos = Vector3.Zero;
260// agent.CapsPath = GetRandomCapsObjectPath();
261// agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
262// agent.child = true;
263//
264// scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
265//
266// string reason;
267// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
268// testclient = new TestClient(agent, scene);
269// scene.AddNewClient(testclient);
270//
271// ScenePresence presence = scene.GetScenePresence(agent1);
272//
273// Assert.That(presence, Is.Not.Null, "presence is null");
274// Assert.That(presence.Firstname, Is.EqualTo(firstName), "First name not same");
275// acd1 = agent;
276// }
277//
278// /// <summary>
279// /// Test removing an uncrossed root agent from a scene.
280// /// </summary>
281// [Test]
282// public void T011_TestRemoveRootAgent()
283// {
284// TestHelpers.InMethod();
285//
286// scene.RemoveClient(agent1);
287//
288// ScenePresence presence = scene.GetScenePresence(agent1);
289//
290// Assert.That(presence, Is.Null, "presence is not null");
291// }
292 } 291 }
293} \ No newline at end of file 292} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
new file mode 100644
index 0000000..9fa0a71
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using Nini.Config;
36using NUnit.Framework;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Framework;
44using OpenSim.Region.CoreModules.Framework.EntityTransfer;
45using OpenSim.Region.CoreModules.World.Serialiser;
46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces;
49using OpenSim.Tests.Common;
50using OpenSim.Tests.Common.Mock;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52
53namespace OpenSim.Region.Framework.Scenes.Tests
54{
55 [TestFixture]
56 public class ScenePresenceCapabilityTests : OpenSimTestCase
57 {
58 [Test]
59 public void TestChildAgentSingleRegionCapabilities()
60 {
61 TestHelpers.InMethod();
62// TestHelpers.EnableLogging();
63
64 UUID spUuid = TestHelpers.ParseTail(0x1);
65
66 // XXX: This is not great since the use of statics will mean that this has to be manually cleaned up for
67 // any subsequent test.
68 // XXX: May replace with a mock IHttpServer later.
69 BaseHttpServer httpServer = new BaseHttpServer(99999);
70 MainServer.AddHttpServer(httpServer);
71 MainServer.Instance = httpServer;
72
73 CapabilitiesModule capsMod = new CapabilitiesModule();
74 TestScene scene = new SceneHelpers().SetupScene();
75 SceneHelpers.SetupSceneModules(scene, capsMod);
76
77 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
78 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
79
80 // TODO: Need to add tests for other ICapabiltiesModule methods.
81
82// scene.IncomingCloseAgent(sp.UUID, false);
83// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
84 scene.CloseAgent(sp.UUID, false);
85// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
86
87 // TODO: Need to add tests for other ICapabiltiesModule methods.
88 }
89 }
90}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 8775949..b806a97 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.CoreModules.Framework; 38using OpenSim.Region.CoreModules.Framework;
39using OpenSim.Region.CoreModules.Framework.EntityTransfer; 39using OpenSim.Region.CoreModules.Framework.EntityTransfer;
40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.CoreModules.World.Permissions;
41using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
43 44
@@ -95,11 +96,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
95 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 96 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
96 97
97 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 98 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
98 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 99 TestClient tc = new TestClient(acd, sceneA);
99 List<TestClient> destinationTestClients = new List<TestClient>(); 100 List<TestClient> destinationTestClients = new List<TestClient>();
100 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 101 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
101 102
102 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 103 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
103 originalSp.AbsolutePosition = new Vector3(128, 32, 10); 104 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
104 105
105// originalSp.Flying = true; 106// originalSp.Flying = true;
@@ -112,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
112 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); 113 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
113 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); 114 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
114 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 115 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
116 moveArgs.SessionID = acd.SessionID;
115 117
116 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); 118 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
117 119
@@ -158,5 +160,90 @@ namespace OpenSim.Region.Framework.Scenes.Tests
158 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); 160 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
159 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); 161 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
160 } 162 }
163
164 /// <summary>
165 /// Test a cross attempt where the user can see into the neighbour but does not have permission to become
166 /// root there.
167 /// </summary>
168 [Test]
169 public void TestCrossOnSameSimulatorNoRootDestPerm()
170 {
171 TestHelpers.InMethod();
172// TestHelpers.EnableLogging();
173
174 UUID userId = TestHelpers.ParseTail(0x1);
175
176 EntityTransferModule etmA = new EntityTransferModule();
177 EntityTransferModule etmB = new EntityTransferModule();
178 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
179
180 IConfigSource config = new IniConfigSource();
181 IConfig modulesConfig = config.AddConfig("Modules");
182 modulesConfig.Set("EntityTransferModule", etmA.Name);
183 modulesConfig.Set("SimulationServices", lscm.Name);
184
185 SceneHelpers sh = new SceneHelpers();
186 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
187 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
188
189 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
190 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
191
192 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
193 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
194 // IsAdministrator if no permissions module is present is true.
195// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
196
197 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
198 TestClient tc = new TestClient(acd, sceneA);
199 List<TestClient> destinationTestClients = new List<TestClient>();
200 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
201
202 // Make sure sceneB will not accept this avatar.
203 sceneB.RegionInfo.EstateSettings.PublicAccess = false;
204
205 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
206 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
207
208 AgentUpdateArgs moveArgs = new AgentUpdateArgs();
209 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
210 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
211 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
212 moveArgs.SessionID = acd.SessionID;
213
214 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
215
216 sceneA.Update(1);
217
218// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);
219
220 // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
221 // But really we want to do this in a more robust way.
222 for (int i = 0; i < 100; i++)
223 {
224 sceneA.Update(1);
225// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
226 }
227
228 // sceneA agent should still be root
229 ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
230 Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);
231
232 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
233
234 // sceneB agent should also still be root
235 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
236
237 // sceneB should ignore unauthorized attempt to upgrade agent to root
238 TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);
239
240 int agentMovementCompleteReceived = 0;
241 sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;
242
243 sceneBTc.CompleteMovement();
244
245 Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
246 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
247 }
161 } 248 }
162} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index acaeb90..0911f00 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -111,15 +111,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 111
112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
113 113
114 // We need to preserve this here because phys actor is removed by the sit.
115 Vector3 spPhysActorSize = m_sp.PhysicsActor.Size;
114 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 116 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
115 117
116 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
117 // default avatar.
118 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
119 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
120 Assert.That( 118 Assert.That(
121 m_sp.AbsolutePosition, 119 m_sp.AbsolutePosition,
122 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 120 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2)));
123 121
124 m_sp.StandUp(); 122 m_sp.StandUp();
125 123
@@ -147,9 +145,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
147 145
148 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); 146 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID));
149 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 147 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
150 Assert.That( 148// Assert.That(
151 m_sp.AbsolutePosition, 149// m_sp.AbsolutePosition,
152 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 150// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
153 Assert.That(m_sp.PhysicsActor, Is.Null); 151 Assert.That(m_sp.PhysicsActor, Is.Null);
154 152
155 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 153 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 8d94d29..fff542b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Text; 32using System.Text;
33using System.Threading;
33using Nini.Config; 34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -107,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
107 } 108 }
108 109
109 [Test] 110 [Test]
110 public void TestSameSimulatorIsolatedRegions() 111 public void TestSameSimulatorIsolatedRegionsV1()
111 { 112 {
112 TestHelpers.InMethod(); 113 TestHelpers.InMethod();
113// TestHelpers.EnableLogging(); 114// TestHelpers.EnableLogging();
@@ -136,14 +137,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
136 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 137 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
137 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 138 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
138 139
140 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
141 lscm.ServiceVersion = "SIMULATION/0.1";
142
139 Vector3 teleportPosition = new Vector3(10, 11, 12); 143 Vector3 teleportPosition = new Vector3(10, 11, 12);
140 Vector3 teleportLookAt = new Vector3(20, 21, 22); 144 Vector3 teleportLookAt = new Vector3(20, 21, 22);
141 145
142 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 146 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
143 sp.AbsolutePosition = new Vector3(30, 31, 32); 147 sp.AbsolutePosition = new Vector3(30, 31, 32);
144 148
145 List<TestClient> destinationTestClients = new List<TestClient>(); 149 List<TestClient> destinationTestClients = new List<TestClient>();
146 EntityTransferHelpers.SetUpInformClientOfNeighbour((TestClient)sp.ControllingClient, destinationTestClients); 150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(
151 (TestClient)sp.ControllingClient, destinationTestClients);
147 152
148 sceneA.RequestTeleportLocation( 153 sceneA.RequestTeleportLocation(
149 sp.ControllingClient, 154 sp.ControllingClient,
@@ -176,6 +181,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
176// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); 181// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
177 } 182 }
178 183
184 [Test]
185 public void TestSameSimulatorIsolatedRegionsV2()
186 {
187 TestHelpers.InMethod();
188// TestHelpers.EnableLogging();
189
190 UUID userId = TestHelpers.ParseTail(0x1);
191
192 EntityTransferModule etmA = new EntityTransferModule();
193 EntityTransferModule etmB = new EntityTransferModule();
194 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
195
196 IConfigSource config = new IniConfigSource();
197 IConfig modulesConfig = config.AddConfig("Modules");
198 modulesConfig.Set("EntityTransferModule", etmA.Name);
199 modulesConfig.Set("SimulationServices", lscm.Name);
200
201 SceneHelpers sh = new SceneHelpers();
202 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
203 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
204
205 SceneHelpers.SetupSceneModules(sceneA, config, etmA);
206 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
207 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
208
209 Vector3 teleportPosition = new Vector3(10, 11, 12);
210 Vector3 teleportLookAt = new Vector3(20, 21, 22);
211
212 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
213 sp.AbsolutePosition = new Vector3(30, 31, 32);
214
215 List<TestClient> destinationTestClients = new List<TestClient>();
216 EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement(
217 (TestClient)sp.ControllingClient, destinationTestClients);
218
219 sceneA.RequestTeleportLocation(
220 sp.ControllingClient,
221 sceneB.RegionInfo.RegionHandle,
222 teleportPosition,
223 teleportLookAt,
224 (uint)TeleportFlags.ViaLocation);
225
226 Assert.That(sceneA.GetScenePresence(userId), Is.Null);
227
228 ScenePresence sceneBSp = sceneB.GetScenePresence(userId);
229 Assert.That(sceneBSp, Is.Not.Null);
230 Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
231 Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
232
233 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
234 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
235 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
236 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
237
238 // TODO: Add assertions to check correct circuit details in both scenes.
239
240 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
241 // position instead).
242// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
243 }
244
179 /// <summary> 245 /// <summary>
180 /// Test teleport procedures when the target simulator returns false when queried about access. 246 /// Test teleport procedures when the target simulator returns false when queried about access.
181 /// </summary> 247 /// </summary>
@@ -224,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
224 Vector3 teleportPosition = new Vector3(10, 11, 12); 290 Vector3 teleportPosition = new Vector3(10, 11, 12);
225 Vector3 teleportLookAt = new Vector3(20, 21, 22); 291 Vector3 teleportLookAt = new Vector3(20, 21, 22);
226 292
227 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 293 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
228 sp.AbsolutePosition = preTeleportPosition; 294 sp.AbsolutePosition = preTeleportPosition;
229 295
230 // Make sceneB return false on query access 296 // Make sceneB return false on query access
@@ -300,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
300 Vector3 teleportPosition = new Vector3(10, 11, 12); 366 Vector3 teleportPosition = new Vector3(10, 11, 12);
301 Vector3 teleportLookAt = new Vector3(20, 21, 22); 367 Vector3 teleportLookAt = new Vector3(20, 21, 22);
302 368
303 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 369 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
304 sp.AbsolutePosition = preTeleportPosition; 370 sp.AbsolutePosition = preTeleportPosition;
305 371
306 // Make sceneB refuse CreateAgent 372 // Make sceneB refuse CreateAgent
@@ -389,7 +455,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
389 Vector3 teleportPosition = new Vector3(10, 11, 12); 455 Vector3 teleportPosition = new Vector3(10, 11, 12);
390 Vector3 teleportLookAt = new Vector3(20, 21, 22); 456 Vector3 teleportLookAt = new Vector3(20, 21, 22);
391 457
392 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 458 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
393 sp.AbsolutePosition = preTeleportPosition; 459 sp.AbsolutePosition = preTeleportPosition;
394 460
395 sceneA.RequestTeleportLocation( 461 sceneA.RequestTeleportLocation(
@@ -425,10 +491,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
425 } 491 }
426 492
427 [Test] 493 [Test]
428 public void TestSameSimulatorNeighbouringRegions() 494 public void TestSameSimulatorNeighbouringRegionsV1()
429 { 495 {
430 TestHelpers.InMethod(); 496 TestHelpers.InMethod();
431 TestHelpers.EnableLogging(); 497// TestHelpers.EnableLogging();
432 498
433 UUID userId = TestHelpers.ParseTail(0x1); 499 UUID userId = TestHelpers.ParseTail(0x1);
434 500
@@ -454,15 +520,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
454 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); 520 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
455 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 521 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
456 522
523 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
524 lscm.ServiceVersion = "SIMULATION/0.1";
525
457 Vector3 teleportPosition = new Vector3(10, 11, 12); 526 Vector3 teleportPosition = new Vector3(10, 11, 12);
458 Vector3 teleportLookAt = new Vector3(20, 21, 22); 527 Vector3 teleportLookAt = new Vector3(20, 21, 22);
459 528
460 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 529 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
461 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 530 TestClient tc = new TestClient(acd, sceneA);
462 List<TestClient> destinationTestClients = new List<TestClient>(); 531 List<TestClient> destinationTestClients = new List<TestClient>();
463 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 532 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
464 533
465 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 534 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
466 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); 535 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
467 536
468 Assert.That(beforeSceneASp, Is.Not.Null); 537 Assert.That(beforeSceneASp, Is.Not.Null);
@@ -506,5 +575,89 @@ namespace OpenSim.Region.Framework.Scenes.Tests
506 575
507// TestHelpers.DisableLogging(); 576// TestHelpers.DisableLogging();
508 } 577 }
578
579 [Test]
580 public void TestSameSimulatorNeighbouringRegionsV2()
581 {
582 TestHelpers.InMethod();
583// TestHelpers.EnableLogging();
584
585 UUID userId = TestHelpers.ParseTail(0x1);
586
587 EntityTransferModule etmA = new EntityTransferModule();
588 EntityTransferModule etmB = new EntityTransferModule();
589 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
590
591 IConfigSource config = new IniConfigSource();
592 IConfig modulesConfig = config.AddConfig("Modules");
593 modulesConfig.Set("EntityTransferModule", etmA.Name);
594 modulesConfig.Set("SimulationServices", lscm.Name);
595
596 SceneHelpers sh = new SceneHelpers();
597 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
598 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
599
600 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
601 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
602 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
603
604 Vector3 teleportPosition = new Vector3(10, 11, 12);
605 Vector3 teleportLookAt = new Vector3(20, 21, 22);
606
607 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
608 TestClient tc = new TestClient(acd, sceneA);
609 List<TestClient> destinationTestClients = new List<TestClient>();
610 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
611
612 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
613 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
614
615 Assert.That(beforeSceneASp, Is.Not.Null);
616 Assert.That(beforeSceneASp.IsChildAgent, Is.False);
617
618 ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId);
619 Assert.That(beforeSceneBSp, Is.Not.Null);
620 Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
621
622 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
623 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
624 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
625 // Both these operations will occur on different threads and will wait for each other.
626 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
627 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
628 tc.OnTestClientSendRegionTeleport
629 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
630 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
631
632 sceneA.RequestTeleportLocation(
633 beforeSceneASp.ControllingClient,
634 sceneB.RegionInfo.RegionHandle,
635 teleportPosition,
636 teleportLookAt,
637 (uint)TeleportFlags.ViaLocation);
638
639 ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
640 Assert.That(afterSceneASp, Is.Not.Null);
641 Assert.That(afterSceneASp.IsChildAgent, Is.True);
642
643 ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId);
644 Assert.That(afterSceneBSp, Is.Not.Null);
645 Assert.That(afterSceneBSp.IsChildAgent, Is.False);
646 Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
647 Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
648
649 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
650 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1));
651 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
652 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
653
654 // TODO: Add assertions to check correct circuit details in both scenes.
655
656 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
657 // position instead).
658// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
659
660// TestHelpers.DisableLogging();
661 }
509 } 662 }
510} 663}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
new file mode 100644
index 0000000..1667002
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.Framework.Scenes.Tests
40{
41 [TestFixture]
42 public class SceneStatisticsTests : OpenSimTestCase
43 {
44 private TestScene m_scene;
45
46 [SetUp]
47 public void Init()
48 {
49 m_scene = new SceneHelpers().SetupScene();
50 }
51
52 [Test]
53 public void TestAddRemovePhysicalLinkset()
54 {
55 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
56
57 UUID ownerId = TestHelpers.ParseTail(0x1);
58 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
59 so1.ScriptSetPhysicsStatus(true);
60 m_scene.AddSceneObject(so1);
61
62 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
63 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));
64
65 m_scene.DeleteSceneObject(so1, false);
66
67 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(0));
68 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
69 }
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
new file mode 100644
index 0000000..9a97acc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
@@ -0,0 +1,119 @@
1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are met:
4 * * Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer.
6 * * Redistributions in binary form must reproduce the above copyright
7 * notice, this list of conditions and the following disclaimer in the
8 * documentation and/or other materials provided with the distribution.
9 * * Neither the name of the OpenSimulator Project nor the
10 * names of its contributors may be used to endorse or promote products
11 * derived from this software without specific prior written permission.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25using System;
26using Nini.Config;
27using NUnit.Framework;
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.CoreModules.World.Estate;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Services.Interfaces;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.Framework.Scenes.Tests
38{
39 /// <summary>
40 /// Scene telehub tests
41 /// </summary>
42 /// <remarks>
43 /// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour
44 /// in the case of an error condition
45 /// </remarks>
46 [TestFixture]
47 public class SceneTelehubTests : OpenSimTestCase
48 {
49 /// <summary>
50 /// Test for desired behaviour when a telehub has no spawn points
51 /// </summary>
52 [Test]
53 public void TestNoTelehubSpawnPoints()
54 {
55 TestHelpers.InMethod();
56// TestHelpers.EnableLogging();
57
58 EstateManagementModule emm = new EstateManagementModule();
59
60 SceneHelpers sh = new SceneHelpers();
61 Scene scene = sh.SetupScene();
62 SceneHelpers.SetupSceneModules(scene, emm);
63
64 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
65
66 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
67
68 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
69 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
70
71 // Must still be possible to successfully log in
72 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
73
74 UserAccount ua
75 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
76
77 SceneHelpers.AddScenePresence(scene, ua);
78
79 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
80 }
81
82 /// <summary>
83 /// Test for desired behaviour when the scene object nominated as a telehub object does not exist.
84 /// </summary>
85 [Test]
86 public void TestNoTelehubSceneObject()
87 {
88 TestHelpers.InMethod();
89// TestHelpers.EnableLogging();
90
91 EstateManagementModule emm = new EstateManagementModule();
92
93 SceneHelpers sh = new SceneHelpers();
94 Scene scene = sh.SetupScene();
95 SceneHelpers.SetupSceneModules(scene, emm);
96
97 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
98
99 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
100 SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner);
101
102 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
103 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId);
104 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
105
106 scene.DeleteSceneObject(telehubSo, false);
107
108 // Must still be possible to successfully log in
109 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
110
111 UserAccount ua
112 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
113
114 SceneHelpers.AddScenePresence(scene, ua);
115
116 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
117 }
118 }
119} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index b09ae39..67655d6 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -34,9 +34,11 @@ using System.Threading;
34using log4net; 34using log4net;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.Assets; 36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
39using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
40 42
41namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
42{ 44{
@@ -82,29 +84,33 @@ namespace OpenSim.Region.Framework.Scenes
82 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
83 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
84 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
85 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
86 { 88 {
87 try 89 try
88 { 90 {
89 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;
90 92
91 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 93 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
92 { 94 {
93 GetWearableAssetUuids(assetUuid, assetUuids); 95 GetWearableAssetUuids(assetUuid, assetUuids);
94 } 96 }
95 else if (AssetType.Gesture == assetType) 97 else if ((sbyte)AssetType.Gesture == assetType)
96 { 98 {
97 GetGestureAssetUuids(assetUuid, assetUuids); 99 GetGestureAssetUuids(assetUuid, assetUuids);
98 } 100 }
99 else if (AssetType.Notecard == assetType) 101 else if ((sbyte)AssetType.Notecard == assetType)
100 { 102 {
101 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 103 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
102 } 104 }
103 else if (AssetType.LSLText == assetType) 105 else if ((sbyte)AssetType.LSLText == assetType)
104 { 106 {
105 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
106 } 108 }
107 else if (AssetType.Object == assetType) 109 else if ((sbyte)OpenSimAssetType.Material == assetType)
110 {
111 GetMaterialAssetUuids(assetUuid, assetUuids);
112 }
113 else if ((sbyte)AssetType.Object == assetType)
108 { 114 {
109 GetSceneObjectAssetUuids(assetUuid, assetUuids); 115 GetSceneObjectAssetUuids(assetUuid, assetUuids);
110 } 116 }
@@ -131,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 137 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
132 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. 138 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
133 /// </param> 139 /// </param>
134 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 140 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
135 { 141 {
136// m_log.DebugFormat( 142// m_log.DebugFormat(
137// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 143// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -151,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
151 { 157 {
152 // Get the prim's default texture. This will be used for faces which don't have their own texture 158 // Get the prim's default texture. This will be used for faces which don't have their own texture
153 if (textureEntry.DefaultTexture != null) 159 if (textureEntry.DefaultTexture != null)
154 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 160 assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
155 161
156 if (textureEntry.FaceTextures != null) 162 if (textureEntry.FaceTextures != null)
157 { 163 {
@@ -159,15 +165,37 @@ namespace OpenSim.Region.Framework.Scenes
159 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 165 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
160 { 166 {
161 if (texture != null) 167 if (texture != null)
162 assetUuids[texture.TextureID] = AssetType.Texture; 168 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
163 } 169 }
164 } 170 }
165 } 171 }
166 172
167 // If the prim is a sculpt then preserve this information too 173 // If the prim is a sculpt then preserve this information too
168 if (part.Shape.SculptTexture != UUID.Zero) 174 if (part.Shape.SculptTexture != UUID.Zero)
169 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 175 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
170 176
177 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
178 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
179
180 if (part.CollisionSound != UUID.Zero)
181 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
182
183 if (part.ParticleSystem.Length > 0)
184 {
185 try
186 {
187 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
188 if (ps.Texture != UUID.Zero)
189 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
190 }
191 catch (Exception e)
192 {
193 m_log.WarnFormat(
194 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
195 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
196 }
197 }
198
171 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 199 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
172 200
173 // Now analyze this prim's inventory items to preserve all the uuids that they reference 201 // Now analyze this prim's inventory items to preserve all the uuids that they reference
@@ -178,8 +206,18 @@ namespace OpenSim.Region.Framework.Scenes
178// tii.Name, tii.Type, part.Name, part.UUID); 206// tii.Name, tii.Type, part.Name, part.UUID);
179 207
180 if (!assetUuids.ContainsKey(tii.AssetID)) 208 if (!assetUuids.ContainsKey(tii.AssetID))
181 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 209 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
182 } 210 }
211
212 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
213 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
214 // inventory transfer. There needs to be a way for a module to register a method without assuming a
215 // Scene.EventManager is present.
216// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
217
218
219 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
220 GatherMaterialsUuids(part, assetUuids);
183 } 221 }
184 catch (Exception e) 222 catch (Exception e)
185 { 223 {
@@ -190,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
190 } 228 }
191 } 229 }
192 } 230 }
193 231
194// /// <summary> 232// /// <summary>
195// /// The callback made when we request the asset for an object from the asset service. 233// /// The callback made when we request the asset for an object from the asset service.
196// /// </summary> 234// /// </summary>
@@ -205,6 +243,75 @@ namespace OpenSim.Region.Framework.Scenes
205// } 243// }
206 244
207 /// <summary> 245 /// <summary>
246 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
247 /// stored in legacy format in part.DynAttrs
248 /// </summary>
249 /// <param name="part"></param>
250 /// <param name="assetUuids"></param>
251 //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
252 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
253 {
254 // scan thru the dynAttrs map of this part for any textures used as materials
255 OSD osdMaterials = null;
256
257 lock (part.DynAttrs)
258 {
259 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
260 {
261 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
262
263 if (materialsStore == null)
264 return;
265
266 materialsStore.TryGetValue("Materials", out osdMaterials);
267 }
268
269 if (osdMaterials != null)
270 {
271 //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
272
273 if (osdMaterials is OSDArray)
274 {
275 OSDArray matsArr = osdMaterials as OSDArray;
276 foreach (OSDMap matMap in matsArr)
277 {
278 try
279 {
280 if (matMap.ContainsKey("Material"))
281 {
282 OSDMap mat = matMap["Material"] as OSDMap;
283 if (mat.ContainsKey("NormMap"))
284 {
285 UUID normalMapId = mat["NormMap"].AsUUID();
286 if (normalMapId != UUID.Zero)
287 {
288 assetUuids[normalMapId] = (sbyte)AssetType.Texture;
289 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
290 }
291 }
292 if (mat.ContainsKey("SpecMap"))
293 {
294 UUID specularMapId = mat["SpecMap"].AsUUID();
295 if (specularMapId != UUID.Zero)
296 {
297 assetUuids[specularMapId] = (sbyte)AssetType.Texture;
298 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
299 }
300 }
301 }
302
303 }
304 catch (Exception e)
305 {
306 m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message);
307 }
308 }
309 }
310 }
311 }
312 }
313
314 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 315 /// Get an asset synchronously, potentially using an asynchronous callback. If the
209 /// asynchronous callback is used, we will wait for it to complete. 316 /// asynchronous callback is used, we will wait for it to complete.
210 /// </summary> 317 /// </summary>
@@ -242,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
242 /// </summary> 349 /// </summary>
243 /// <param name="scriptUuid"></param> 350 /// <param name="scriptUuid"></param>
244 /// <param name="assetUuids">Dictionary in which to record the references</param> 351 /// <param name="assetUuids">Dictionary in which to record the references</param>
245 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 352 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
246 { 353 {
247// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 354// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
248 355
@@ -262,7 +369,7 @@ namespace OpenSim.Region.Framework.Scenes
262 369
263 // Embedded asset references (if not false positives) could be for many types of asset, so we will 370 // Embedded asset references (if not false positives) could be for many types of asset, so we will
264 // label these as unknown. 371 // label these as unknown.
265 assetUuids[uuid] = AssetType.Unknown; 372 assetUuids[uuid] = (sbyte)AssetType.Unknown;
266 } 373 }
267 } 374 }
268 } 375 }
@@ -272,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
272 /// </summary> 379 /// </summary>
273 /// <param name="wearableAssetUuid"></param> 380 /// <param name="wearableAssetUuid"></param>
274 /// <param name="assetUuids">Dictionary in which to record the references</param> 381 /// <param name="assetUuids">Dictionary in which to record the references</param>
275 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 382 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
276 { 383 {
277 AssetBase assetBase = GetAsset(wearableAssetUuid); 384 AssetBase assetBase = GetAsset(wearableAssetUuid);
278 385
@@ -287,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes
287 394
288 foreach (UUID uuid in wearableAsset.Textures.Values) 395 foreach (UUID uuid in wearableAsset.Textures.Values)
289 { 396 {
290 assetUuids[uuid] = AssetType.Texture; 397 assetUuids[uuid] = (sbyte)AssetType.Texture;
291 } 398 }
292 } 399 }
293 } 400 }
@@ -299,7 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
299 /// </summary> 406 /// </summary>
300 /// <param name="sceneObject"></param> 407 /// <param name="sceneObject"></param>
301 /// <param name="assetUuids"></param> 408 /// <param name="assetUuids"></param>
302 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 409 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
303 { 410 {
304 AssetBase objectAsset = GetAsset(sceneObjectUuid); 411 AssetBase objectAsset = GetAsset(sceneObjectUuid);
305 412
@@ -328,7 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
328 /// </summary> 435 /// </summary>
329 /// <param name="gestureUuid"></param> 436 /// <param name="gestureUuid"></param>
330 /// <param name="assetUuids"></param> 437 /// <param name="assetUuids"></param>
331 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 438 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
332 { 439 {
333 AssetBase assetBase = GetAsset(gestureUuid); 440 AssetBase assetBase = GetAsset(gestureUuid);
334 if (null == assetBase) 441 if (null == assetBase)
@@ -362,9 +469,29 @@ namespace OpenSim.Region.Framework.Scenes
362 // If it can be parsed as a UUID, it is an asset ID 469 // If it can be parsed as a UUID, it is an asset ID
363 UUID uuid; 470 UUID uuid;
364 if (UUID.TryParse(id, out uuid)) 471 if (UUID.TryParse(id, out uuid))
365 assetUuids[uuid] = AssetType.Animation; 472 assetUuids[uuid] = (sbyte)AssetType.Animation;
366 } 473 }
367 } 474 }
475
476 /// <summary>
477 /// Get the asset uuid's referenced in a material.
478 /// </summary>
479 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
480 {
481 AssetBase assetBase = GetAsset(materialUuid);
482 if (null == assetBase)
483 return;
484
485 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
486
487 UUID normMap = mat["NormMap"].AsUUID();
488 if (normMap != UUID.Zero)
489 assetUuids[normMap] = (sbyte)AssetType.Texture;
490
491 UUID specMap = mat["SpecMap"].AsUUID();
492 if (specMap != UUID.Zero)
493 assetUuids[specMap] = (sbyte)AssetType.Texture;
494 }
368 } 495 }
369 496
370 public class HGUuidGatherer : UuidGatherer 497 public class HGUuidGatherer : UuidGatherer