aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to '')
-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.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs71
-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.cs189
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs834
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs1156
-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.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs203
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs137
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1885
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs62
-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, 4394 insertions, 1714 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..ecd6a09 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)
@@ -145,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
145 if (addRemove) 151 if (addRemove)
146 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero); 152 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
147 else 153 else
148 m_animations.Remove(animID, true); 154 m_animations.Remove(animID, false);
149 } 155 }
150 if(sendPack) 156 if(sendPack)
151 SendAnimPack(); 157 SendAnimPack();
@@ -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..692e0c9 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
@@ -1354,7 +1366,9 @@ namespace OpenSim.Region.Framework.Scenes
1354 { 1366 {
1355 try 1367 try
1356 { 1368 {
1369// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate: {0}",d.Target.ToString());
1357 d(agentId); 1370 d(agentId);
1371// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate done ");
1358 } 1372 }
1359 catch (Exception e) 1373 catch (Exception e)
1360 { 1374 {
@@ -2025,7 +2039,10 @@ namespace OpenSim.Region.Framework.Scenes
2025 { 2039 {
2026 try 2040 try
2027 { 2041 {
2042// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed: {0}", d.Target.ToString());
2028 d(ClientID, scene); 2043 d(ClientID, scene);
2044// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed done ");
2045
2029 } 2046 }
2030 catch (Exception e) 2047 catch (Exception e)
2031 { 2048 {
@@ -2160,7 +2177,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 } 2177 }
2161 } 2178 }
2162 2179
2163 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) 2180 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel)
2164 { 2181 {
2165 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2182 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2166 if (handlerNewInventoryItemUpdateComplete != null) 2183 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2169,7 +2186,7 @@ namespace OpenSim.Region.Framework.Scenes
2169 { 2186 {
2170 try 2187 try
2171 { 2188 {
2172 d(agentID, AssetID, AssetName, userlevel); 2189 d(agentID, type, AssetID, AssetName, userlevel);
2173 } 2190 }
2174 catch (Exception e) 2191 catch (Exception e)
2175 { 2192 {
@@ -3096,6 +3113,27 @@ namespace OpenSim.Region.Framework.Scenes
3096 } 3113 }
3097 } 3114 }
3098 3115
3116 public void TriggerRegionHeartbeatStart(Scene scene)
3117 {
3118 RegionHeartbeatStart handler = OnRegionHeartbeatStart;
3119
3120 if (handler != null)
3121 {
3122 foreach (RegionHeartbeatStart d in handler.GetInvocationList())
3123 {
3124 try
3125 {
3126 d(scene);
3127 }
3128 catch (Exception e)
3129 {
3130 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}",
3131 e.Message, e.StackTrace);
3132 }
3133 }
3134 }
3135 }
3136
3099 public void TriggerRegionHeartbeatEnd(Scene scene) 3137 public void TriggerRegionHeartbeatEnd(Scene scene)
3100 { 3138 {
3101 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; 3139 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd;
@@ -3251,5 +3289,26 @@ namespace OpenSim.Region.Framework.Scenes
3251 handler(scenePresence); 3289 handler(scenePresence);
3252 } 3290 }
3253 } 3291 }
3292
3293// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3294// {
3295// GatherUuids handler = OnGatherUuids;
3296//
3297// if (handler != null)
3298// {
3299// foreach (GatherUuids d in handler.GetInvocationList())
3300// {
3301// try
3302// {
3303// d(sop, assetUuids);
3304// }
3305// catch (Exception e)
3306// {
3307// m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}",
3308// e.Message, e.StackTrace);
3309// }
3310// }
3311// }
3312// }
3254 } 3313 }
3255} 3314}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index f0e639d..49b71e5 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 {
@@ -500,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes
500 k.Position = pos; 520 k.Position = pos;
501// k.Velocity = Vector3.Zero; 521// k.Velocity = Vector3.Zero;
502 } 522 }
523 k.AngularVelocity = (Vector3)k.Position;
503 524
504 k.StartRotation = rot; 525 k.StartRotation = rot;
505 if (k.Rotation.HasValue) 526 if (k.Rotation.HasValue)
@@ -668,7 +689,7 @@ namespace OpenSim.Region.Framework.Scenes
668 m_group.RootPart.Velocity = Vector3.Zero; 689 m_group.RootPart.Velocity = Vector3.Zero;
669 m_group.RootPart.AngularVelocity = Vector3.Zero; 690 m_group.RootPart.AngularVelocity = Vector3.Zero;
670 691
671 m_nextPosition = (Vector3)m_currentFrame.Position; 692 m_nextPosition = NormalizeVector(m_currentFrame.AngularVelocity);
672 m_group.AbsolutePosition = m_nextPosition; 693 m_group.AbsolutePosition = m_nextPosition;
673 694
674 // we are sending imediate updates, no doing force a extra terseUpdate 695 // we are sending imediate updates, no doing force a extra terseUpdate
@@ -755,7 +776,26 @@ namespace OpenSim.Region.Framework.Scenes
755 m_group.SendGroupRootTerseUpdate(); 776 m_group.SendGroupRootTerseUpdate();
756 } 777 }
757 } 778 }
779 private Vector3 NormalizeVector(Vector3? pPosition)
780 {
781 if (pPosition == null)
782 return Vector3.Zero;
783
784 Vector3 tmp = (Vector3) pPosition;
758 785
786 while (tmp.X > Constants.RegionSize)
787 tmp.X -= Constants.RegionSize;
788 while (tmp.X < 0)
789 tmp.X += Constants.RegionSize;
790 while (tmp.Y > Constants.RegionSize)
791 tmp.Y -= Constants.RegionSize;
792 while (tmp.Y < 0)
793 tmp.Y += Constants.RegionSize;
794
795 return tmp;
796
797
798 }
759 public Byte[] Serialize() 799 public Byte[] Serialize()
760 { 800 {
761 StopTimer(); 801 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..8634a3a 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,17 @@ 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 agentItem.CurrentPermissions = perms | (uint)PermissionMask.Move;
1240 }
1217 else 1241 else
1242 {
1218 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; 1243 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
1244 }
1219 1245
1220 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 1246 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1221 agentItem.NextPermissions = taskItem.NextPermissions; 1247 agentItem.NextPermissions = taskItem.NextPermissions;
@@ -2124,7 +2150,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2150 {
2125 // If we don't have permission, stop right here 2151 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2152 if (!permissionToTakeCopy)
2153 {
2154 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2155 return;
2156 }
2128 2157
2129 permissionToTake = true; 2158 permissionToTake = true;
2130 // Don't delete 2159 // Don't delete
@@ -2277,6 +2306,88 @@ namespace OpenSim.Region.Framework.Scenes
2277 } 2306 }
2278 2307
2279 /// <summary> 2308 /// <summary>
2309 /// Returns the list of Scene Objects in an asset.
2310 /// </summary>
2311 /// <remarks>
2312 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2313 /// </remarks>
2314 /// <param name="assetData">Asset data</param>
2315 /// <param name="attachment">Whether the item is an attachment</param>
2316 /// <param name="objlist">The objects included in the asset</param>
2317 /// <param name="veclist">Relative positions of the objects</param>
2318 /// <param name="bbox">Bounding box of all the objects</param>
2319 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2320 /// to the centre of the root prim (relevant only when returning a single object)</param>
2321 /// <returns>true = returning a single object; false = multiple objects</returns>
2322 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2323 out Vector3 bbox, out float offsetHeight)
2324 {
2325 objlist = new List<SceneObjectGroup>();
2326 veclist = new List<Vector3>();
2327
2328 XmlDocument doc = new XmlDocument();
2329 string xmlData = Utils.BytesToString(assetData);
2330 doc.LoadXml(xmlData);
2331 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2332
2333 if (e == null || attachment) // Single
2334 {
2335 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2336/*
2337 if (!attachment)
2338 {
2339 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2340 g.RootPart.AttachedPos = g.AbsolutePosition;
2341 g.RootPart.AttachRotation = g.GroupRotation;
2342 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2343 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2344 g.RootPart.Shape.State = 0;
2345 }
2346*/
2347 objlist.Add(g);
2348 veclist.Add(new Vector3(0, 0, 0));
2349 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2350 return true;
2351 }
2352 else
2353 {
2354 XmlElement coll = (XmlElement)e;
2355 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2356 float by = Convert.ToSingle(coll.GetAttribute("y"));
2357 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2358 bbox = new Vector3(bx, by, bz);
2359 offsetHeight = 0;
2360
2361 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2362 foreach (XmlNode n in groups)
2363 {
2364 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2365/*
2366 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2367 g.RootPart.AttachedPos = g.AbsolutePosition;
2368 g.RootPart.AttachRotation = g.GroupRotation;
2369 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2370 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2371 g.RootPart.Shape.State = 0;
2372*/
2373 objlist.Add(g);
2374
2375 XmlElement el = (XmlElement)n;
2376 string rawX = el.GetAttribute("offsetx");
2377 string rawY = el.GetAttribute("offsety");
2378 string rawZ = el.GetAttribute("offsetz");
2379
2380 float x = Convert.ToSingle(rawX);
2381 float y = Convert.ToSingle(rawY);
2382 float z = Convert.ToSingle(rawZ);
2383 veclist.Add(new Vector3(x, y, z));
2384 }
2385 }
2386
2387 return false;
2388 }
2389
2390 /// <summary>
2280 /// Event Handler Rez an object into a scene 2391 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler 2392 /// Calls the non-void event handler
2282 /// </summary> 2393 /// </summary>
@@ -2351,19 +2462,25 @@ namespace OpenSim.Region.Framework.Scenes
2351 /// will be used if it exists.</param> 2462 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param> 2463 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param> 2464 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2465 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual SceneObjectGroup RezObject( 2466 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2467 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 { 2468 {
2358 if (null == item) 2469 if (null == item)
2359 return null; 2470 return null;
2471
2472 List<SceneObjectGroup> objlist;
2473 List<Vector3> veclist;
2360 2474
2361 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2475 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2362 2476 if (!success)
2363 if (null == group)
2364 return null; 2477 return null;
2365 2478
2366 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2479 int totalPrims = 0;
2480 foreach (SceneObjectGroup group in objlist)
2481 totalPrims += group.PrimCount;
2482
2483 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2367 return null; 2484 return null;
2368 2485
2369 if (!Permissions.BypassPermissions()) 2486 if (!Permissions.BypassPermissions())
@@ -2372,16 +2489,28 @@ namespace OpenSim.Region.Framework.Scenes
2372 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2489 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2373 } 2490 }
2374 2491
2375 group.FromPartID = sourcePart.UUID; 2492 for (int i = 0; i < objlist.Count; i++)
2376 AddNewSceneObject(group, true, pos, rot, vel); 2493 {
2377 2494 SceneObjectGroup group = objlist[i];
2378 // We can only call this after adding the scene object, since the scene object references the scene 2495 Vector3 curpos = pos + veclist[i];
2379 // to find out if scripts should be activated at all. 2496
2380 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2497 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2381 2498 {
2382 group.ScheduleGroupForFullUpdate(); 2499 group.RootPart.AttachedPos = group.AbsolutePosition;
2383 2500 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2384 return group; 2501 }
2502
2503 group.FromPartID = sourcePart.UUID;
2504 AddNewSceneObject(group, true, curpos, rot, vel);
2505
2506 // We can only call this after adding the scene object, since the scene object references the scene
2507 // to find out if scripts should be activated at all.
2508 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2509
2510 group.ScheduleGroupForFullUpdate();
2511 }
2512
2513 return objlist;
2385 } 2514 }
2386 2515
2387 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2516 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..0266faf 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 }
@@ -2444,7 +2469,7 @@ namespace OpenSim.Region.Framework.Scenes
2444 foreach (UUID av in avatars) 2469 foreach (UUID av in avatars)
2445 { 2470 {
2446 ScenePresence p = GetScenePresence(av); 2471 ScenePresence p = GetScenePresence(av);
2447 if (p != null) 2472 if (p != null && p.ParentUUID == UUID.Zero)
2448 p.StandUp(); 2473 p.StandUp();
2449 } 2474 }
2450 2475
@@ -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 }
@@ -3100,12 +3134,13 @@ namespace OpenSim.Region.Framework.Scenes
3100 // and the scene presence and the client, if they exist 3134 // and the scene presence and the client, if they exist
3101 try 3135 try
3102 { 3136 {
3103 ScenePresence sp = GetScenePresence(agentID); 3137 ScenePresence sp = WaitGetScenePresence(agentID);
3104 3138
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,40 +3630,44 @@ 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);
3643// m_log.Debug("[Scene]TriggerClientClosed done");
3636 m_eventManager.TriggerOnRemovePresence(agentID); 3644 m_eventManager.TriggerOnRemovePresence(agentID);
3645// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3637 3646
3638 if (!isChildAgent) 3647 if (!isChildAgent)
3639 { 3648 {
3640 if (AttachmentsModule != null) 3649 if (AttachmentsModule != null)
3641 { 3650 {
3651// m_log.Debug("[Scene]DeRezAttachments");
3642 AttachmentsModule.DeRezAttachments(avatar); 3652 AttachmentsModule.DeRezAttachments(avatar);
3653// m_log.Debug("[Scene]DeRezAttachments done");
3643 } 3654 }
3644 3655
3645 ForEachClient( 3656 ForEachClient(
3646 delegate(IClientAPI client) 3657 delegate(IClientAPI client)
3647 { 3658 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3659 //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 }); } 3660 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3661 catch (NullReferenceException) { }
3651 }); 3662 });
3652 } 3663 }
3653 3664
3654 // It's possible for child agents to have transactions if changes are being made cross-border. 3665 // It's possible for child agents to have transactions if changes are being made cross-border.
3655 if (AgentTransactionsModule != null) 3666 if (AgentTransactionsModule != null)
3667 {
3668// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3656 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3669 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3670 }
3657 m_log.Debug("[Scene] The avatar has left the building"); 3671 m_log.Debug("[Scene] The avatar has left the building");
3658 } 3672 }
3659 catch (Exception e) 3673 catch (Exception e)
@@ -3727,7 +3741,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3741 }
3728 deleteIDs.Add(localID); 3742 deleteIDs.Add(localID);
3729 } 3743 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3744
3745 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3746 }
3732 3747
3733 #endregion 3748 #endregion
@@ -3763,13 +3778,13 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3778 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3779 /// the LLUDP stack).
3765 /// </remarks> 3780 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3781 /// <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> 3782 /// <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 3783 /// <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> 3784 /// 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 3785 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3786 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3787 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3788 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3789 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3790 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,15 +3804,15 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3804 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})", 3805 "[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, 3806 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3807 (acd.child ? "child" : "root"),
3793 agent.firstname, 3808 acd.firstname,
3794 agent.lastname, 3809 acd.lastname,
3795 agent.AgentID, 3810 acd.AgentID,
3796 agent.circuitcode, 3811 acd.circuitcode,
3797 agent.IPAddress, 3812 acd.IPAddress,
3798 agent.Viewer, 3813 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3814 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3815 acd.startpos
3801 ); 3816 );
3802 3817
3803 if (!LoginsEnabled) 3818 if (!LoginsEnabled)
@@ -3815,7 +3830,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3830 {
3816 foreach (string viewer in m_AllowedViewers) 3831 foreach (string viewer in m_AllowedViewers)
3817 { 3832 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3833 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3834 {
3820 ViewerDenied = false; 3835 ViewerDenied = false;
3821 break; 3836 break;
@@ -3832,7 +3847,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3847 {
3833 foreach (string viewer in m_BannedViewers) 3848 foreach (string viewer in m_BannedViewers)
3834 { 3849 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3850 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3851 {
3837 ViewerDenied = true; 3852 ViewerDenied = true;
3838 break; 3853 break;
@@ -3844,54 +3859,129 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3859 {
3845 m_log.DebugFormat( 3860 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3861 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3862 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3863 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3864 return false;
3850 } 3865 }
3851 3866
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3867 ILandObject land;
3868 ScenePresence sp;
3853 3869
3854 // If we have noo presence here or if that presence is a zombie root 3870 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3871 {
3858 if (CapsModule != null) 3872 sp = GetScenePresence(acd.AgentID);
3873
3874 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3875 // closed.
3876 if (sp != null && sp.IsChildAgent
3877 && (sp.LifecycleState == ScenePresenceState.Running
3878 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3879 {
3860 lock (agent) 3880 m_log.DebugFormat(
3881 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3882 sp.Name, sp.LifecycleState, Name);
3883
3884 // In the case where, for example, an A B C D region layout, an avatar may
3885 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3886 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3887 //
3888 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3889 // teleport, since realistically, the close request should always be processed before any other
3890 // region tried to re-establish a child agent. This is much simpler since the logic below is
3891 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3892 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3893 // flag when no teleport had taken place (and hence no close was going to come).
3894// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3895// {
3896// m_log.DebugFormat(
3897// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3898// sp.Name, Name);
3899//
3900// sp.DoNotCloseAfterTeleport = true;
3901// }
3902// else if (EntityTransferModule.IsInTransit(sp.UUID))
3903
3904 sp.LifecycleState = ScenePresenceState.Running;
3905
3906 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3907 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3908 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3909
3910 m_log.DebugFormat(
3911 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3912 sp.Name, Name);
3864 } 3913 }
3865 } 3914 }
3866 } 3915 }
3867 3916
3917 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3918 // allow unpredictable things to happen.
3868 if (sp != null) 3919 if (sp != null)
3869 { 3920 {
3870 if (!sp.IsChildAgent) 3921 const int polls = 10;
3922 const int pollInterval = 1000;
3923 int pollsLeft = polls;
3924
3925 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3926 Thread.Sleep(pollInterval);
3927
3928 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3929 {
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( 3930 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3931 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3932 sp.Name, Name, polls * pollInterval / 1000);
3878 3933
3879 sp.ControllingClient.Close(true, true); 3934 return false;
3880 sp = null; 3935 }
3936 else if (polls != pollsLeft)
3937 {
3938 m_log.DebugFormat(
3939 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3940 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3941 }
3882 } 3942 }
3883 3943
3884 lock (agent) 3944 // TODO: can we remove this lock?
3945 lock (acd)
3885 { 3946 {
3886 //On login test land permisions 3947 if (sp != null && !sp.IsChildAgent)
3948 {
3949 // We have a root agent. Is it in transit?
3950 if (!EntityTransferModule.IsInTransit(sp.UUID))
3951 {
3952 // We have a zombie from a crashed session.
3953 // Or the same user is trying to be root twice here, won't work.
3954 // Kill it.
3955 m_log.WarnFormat(
3956 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3957 sp.Name, sp.UUID, RegionInfo.RegionName);
3958
3959 if (sp.ControllingClient != null)
3960 CloseAgent(sp.UUID, true);
3961
3962 sp = null;
3963 }
3964 //else
3965 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3966 }
3967
3968 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3969 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3970 // If the checks fail, we remove the circuit.
3971 acd.teleportFlags = teleportFlags;
3972 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3973
3974 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3975
3976 // On login test land permisions
3887 if (vialogin) 3977 if (vialogin)
3888 { 3978 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3979 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 3980 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 3981 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3982 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 3983 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3984 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 3985 return false;
3896 } 3986 }
3897 } 3987 }
@@ -3902,84 +3992,97 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 3992 {
3903 try 3993 try
3904 { 3994 {
3905 if (!VerifyUserPresence(agent, out reason)) 3995 if (!VerifyUserPresence(acd, out reason))
3996 {
3997 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 3998 return false;
3907 } catch (Exception e) 3999 }
4000 }
4001 catch (Exception e)
3908 { 4002 {
3909 m_log.ErrorFormat( 4003 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 4004 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
4005
4006 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 4007 return false;
3912 } 4008 }
3913 } 4009 }
3914 4010
3915 try 4011 try
3916 { 4012 {
3917 // Always check estate if this is a login. Always 4013 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 4014 {
3921 if (!AuthorizeUser(agent, out reason)) 4015 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 4016 return false;
3923 return false;
3924 }
3925 } 4017 }
3926 } 4018 }
3927 catch (Exception e) 4019 catch (Exception e)
3928 { 4020 {
3929 m_log.ErrorFormat( 4021 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4022 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4023
4024 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4025 return false;
3932 } 4026 }
3933 4027
3934 m_log.InfoFormat( 4028 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4029 "[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, 4030 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4031 acd.AgentID, acd.circuitcode);
3938 4032
4033 if (CapsModule != null)
4034 {
4035 CapsModule.SetAgentCapsSeeds(acd);
4036 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4037 }
3939 } 4038 }
3940 else 4039 else
3941 { 4040 {
3942 // Let the SP know how we got here. This has a lot of interesting 4041 // Let the SP know how we got here. This has a lot of interesting
3943 // uses down the line. 4042 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4043 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4044
3946 if (sp.IsChildAgent) 4045 if (sp.IsChildAgent)
3947 { 4046 {
3948 m_log.DebugFormat( 4047 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4048 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4049 acd.AgentID, RegionInfo.RegionName);
3951 4050
3952 sp.AdjustKnownSeeds(); 4051 sp.AdjustKnownSeeds();
3953 4052
3954 if (CapsModule != null) 4053 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4054 {
4055 CapsModule.SetAgentCapsSeeds(acd);
4056 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4057 }
3956 } 4058 }
3957 } 4059 }
3958 }
3959 4060
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4061 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4062 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4063 // request for the HG avatar appears to trigger before the user name is cached.
4064 CacheUserName(null, acd);
4065 }
3963 4066
3964 if (CapsModule != null) 4067 if (CapsModule != null)
3965 { 4068 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4069 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4070 }
3968 4071
3969 if (vialogin) 4072 if (vialogin)
3970 { 4073 {
3971// CleanDroppedAttachments(); 4074// CleanDroppedAttachments();
3972 4075
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4076 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4077 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4078 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4079 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4080 }
3978 4081
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4082 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4083 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4084 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4085 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4086 }
3984 4087
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4088 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,68 +4092,88 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4092 {
3990 lock (EastBorders) 4093 lock (EastBorders)
3991 { 4094 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4095 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4096 {
3994 m_log.Warn("FIX AGENT POSITION"); 4097 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4098 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4099 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4100 acd.startpos.Z = 720;
3998 } 4101 }
3999 } 4102 }
4000 lock (NorthBorders) 4103 lock (NorthBorders)
4001 { 4104 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4105 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4106 {
4004 m_log.Warn("FIX Agent POSITION"); 4107 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4108 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4109 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4110 acd.startpos.Z = 720;
4008 } 4111 }
4009 } 4112 }
4010 } else 4113 } else
4011 { 4114 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4115 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4116 {
4014 m_log.Warn("FIX AGENT POSITION"); 4117 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4118 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4119 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4120 acd.startpos.Z = 720;
4018 } 4121 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4122 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4123 {
4021 m_log.Warn("FIX Agent POSITION"); 4124 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4125 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4126 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4127 acd.startpos.Z = 720;
4025 } 4128 }
4026 } 4129 }
4027 4130
4131// m_log.DebugFormat(
4132// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4133// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4134
4028 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4135 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4029 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4136 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4030 RegionInfo.EstateSettings.AllowDirectTeleport == false && 4137 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4031 !viahome && !godlike) 4138 !viahome && !godlike)
4032 { 4139 {
4033 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4140 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4034 // Can have multiple SpawnPoints 4141
4035 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4142 if (telehub != null)
4036 if (spawnpoints.Count > 1)
4037 { 4143 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4144 // Can have multiple SpawnPoints
4039 if (SpawnPointRouting == "random") 4145 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4146 if (spawnpoints.Count > 1)
4041 telehub.AbsolutePosition, 4147 {
4042 telehub.GroupRotation 4148 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4043 ); 4149 if (SpawnPointRouting == "random")
4150 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4151 telehub.AbsolutePosition,
4152 telehub.GroupRotation
4153 );
4154 else
4155 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4156 telehub.AbsolutePosition,
4157 telehub.GroupRotation
4158 );
4159 }
4160 else if (spawnpoints.Count == 1)
4161 {
4162 // We have a single SpawnPoint and will route the agent to it
4163 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4164 }
4044 else 4165 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4166 {
4046 telehub.AbsolutePosition, 4167 m_log.DebugFormat(
4047 telehub.GroupRotation 4168 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4048 ); 4169 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4170 }
4049 } 4171 }
4050 else 4172 else
4051 { 4173 {
4052 // We have a single SpawnPoint and will route the agent to it 4174 m_log.DebugFormat(
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4175 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4176 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4054 } 4177 }
4055 4178
4056 return true; 4179 return true;
@@ -4063,7 +4186,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4186 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4187 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4188 {
4066 agent.startpos = land.LandData.UserLocation; 4189 acd.startpos = land.LandData.UserLocation;
4067 } 4190 }
4068 } 4191 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4192 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4281,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4281 /// <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 4282 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4283 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4284 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4285 {
4163 reason = String.Empty; 4286 reason = String.Empty;
4164 4287
@@ -4177,67 +4300,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4300 }
4178 } 4301 }
4179 4302
4180 if (RegionInfo.EstateSettings != null) 4303 // We only test the things below when we want to cut off
4304 // child agents from being present in the scene for which their root
4305 // agent isn't allowed. Otherwise, we allow child agents. The test for
4306 // the root is done elsewhere (QueryAccess)
4307 if (!bypassAccessControl)
4181 { 4308 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4309 if (RegionInfo.EstateSettings != null)
4183 { 4310 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4311 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4312 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4313 {
4187 RegionInfo.RegionName); 4314 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4315 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4316 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4317 RegionInfo.RegionName);
4318 return false;
4319 }
4189 } 4320 }
4190 } 4321 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 { 4322 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4323 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4324 }
4207 else 4325
4326 List<UUID> agentGroups = new List<UUID>();
4327
4328 if (m_groupsModule != null)
4208 { 4329 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4330 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4331
4332 if (GroupMembership != null)
4333 {
4334 for (int i = 0; i < GroupMembership.Length; i++)
4335 agentGroups.Add(GroupMembership[i].GroupID);
4336 }
4337 else
4338 {
4339 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4340 }
4210 } 4341 }
4211 }
4212 4342
4213 bool groupAccess = false; 4343 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4344 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4345
4216 if (estateGroups != null) 4346 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4347 {
4220 if (agentGroups.Contains(group)) 4348 foreach (UUID group in estateGroups)
4221 { 4349 {
4222 groupAccess = true; 4350 if (agentGroups.Contains(group))
4223 break; 4351 {
4352 groupAccess = true;
4353 break;
4354 }
4224 } 4355 }
4225 } 4356 }
4226 } 4357 else
4227 else 4358 {
4228 { 4359 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4360 }
4230 }
4231 4361
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4362 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4363 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4364 !groupAccess)
4235 { 4365 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4366 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); 4367 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.", 4368 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4369 RegionInfo.RegionName);
4240 return false; 4370 return false;
4371 }
4241 } 4372 }
4242 4373
4243 // TODO: estate/region settings are not properly hooked up 4374 // TODO: estate/region settings are not properly hooked up
@@ -4362,13 +4493,11 @@ namespace OpenSim.Region.Framework.Scenes
4362 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4493 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4363 /// Appearance, animations, position, etc.</param> 4494 /// Appearance, animations, position, etc.</param>
4364 /// <returns>true if we handled it.</returns> 4495 /// <returns>true if we handled it.</returns>
4365 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4496 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4366 { 4497 {
4367 m_log.DebugFormat( 4498 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4499 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4500
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. 4501 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4502 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4503 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4382,7 +4511,7 @@ namespace OpenSim.Region.Framework.Scenes
4382 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4511 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4383 if (nearestParcel == null) 4512 if (nearestParcel == null)
4384 { 4513 {
4385 m_log.DebugFormat( 4514 m_log.InfoFormat(
4386 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4515 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4387 cAgentData.AgentID, RegionInfo.RegionName); 4516 cAgentData.AgentID, RegionInfo.RegionName);
4388 4517
@@ -4390,13 +4519,44 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4519 }
4391 4520
4392 // We have to wait until the viewer contacts this region 4521 // 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 4522 // 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. 4523 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4524 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4525 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4526
4397 if (childAgentUpdate != null) 4527 if (sp != null)
4398 { 4528 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4529 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4530 {
4531 m_log.WarnFormat(
4532 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4533 sp.UUID, cAgentData.SessionID);
4534
4535 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4536 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4537 }
4538
4539 sp.UpdateChildAgent(cAgentData);
4540
4541 int ntimes = 20;
4542 if (cAgentData.SenderWantsToWaitForRoot)
4543 {
4544 while (sp.IsChildAgent && ntimes-- > 0)
4545 Thread.Sleep(1000);
4546
4547 if (sp.IsChildAgent)
4548 m_log.WarnFormat(
4549 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4550 sp.Name, sp.UUID, Name);
4551 else
4552 m_log.InfoFormat(
4553 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4554 sp.Name, sp.UUID, Name, 20 - ntimes);
4555
4556 if (sp.IsChildAgent)
4557 return false;
4558 }
4559
4400 return true; 4560 return true;
4401 } 4561 }
4402 4562
@@ -4409,12 +4569,17 @@ namespace OpenSim.Region.Framework.Scenes
4409 /// </summary> 4569 /// </summary>
4410 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4570 /// <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> 4571 /// <returns>true if we handled it.</returns>
4412 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4572 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4413 { 4573 {
4414 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4574 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4575 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4576 if (childAgentUpdate != null)
4417 { 4577 {
4578// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4579// // Only warn for now
4580// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4581// childAgentUpdate.UUID, cAgentData.SessionID);
4582
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4583 // 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.. 4584 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4585 if (childAgentUpdate.IsChildAgent)
@@ -4424,7 +4589,7 @@ namespace OpenSim.Region.Framework.Scenes
4424 uint tRegionX = RegionInfo.RegionLocX; 4589 uint tRegionX = RegionInfo.RegionLocX;
4425 uint tRegionY = RegionInfo.RegionLocY; 4590 uint tRegionY = RegionInfo.RegionLocY;
4426 //Send Data to ScenePresence 4591 //Send Data to ScenePresence
4427 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4592 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4428 // Not Implemented: 4593 // Not Implemented:
4429 //TODO: Do we need to pass the message on to one of our neighbors? 4594 //TODO: Do we need to pass the message on to one of our neighbors?
4430 } 4595 }
@@ -4451,35 +4616,99 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4616 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4617 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4618 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 4619
4459 return sp; 4620 return sp;
4460 } 4621 }
4461 4622
4462 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4623 /// <summary>
4624 /// Authenticated close (via network)
4625 /// </summary>
4626 /// <param name="agentID"></param>
4627 /// <param name="force"></param>
4628 /// <param name="auth_token"></param>
4629 /// <returns></returns>
4630 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4463 { 4631 {
4464 agent = null; 4632 //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); 4633
4466 if ((sp != null) && (!sp.IsChildAgent)) 4634 // Check that the auth_token is valid
4635 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4636
4637 if (acd == null)
4467 { 4638 {
4468 sp.IsChildAgent = true; 4639 m_log.DebugFormat(
4469 return sp.CopyAgent(out agent); 4640 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4641 agentID, Name);
4642
4643 return false;
4644 }
4645
4646 if (acd.SessionID.ToString() == auth_token)
4647 {
4648 return CloseAgent(agentID, force);
4649 }
4650 else
4651 {
4652 m_log.WarnFormat(
4653 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4654 agentID, auth_token, Name);
4470 } 4655 }
4471 4656
4472 return false; 4657 return false;
4473 } 4658 }
4474 4659
4475 public bool IncomingCloseAgent(UUID agentID) 4660// public bool IncomingCloseAgent(UUID agentID)
4476 { 4661// {
4477 return IncomingCloseAgent(agentID, false); 4662// return IncomingCloseAgent(agentID, false);
4478 } 4663// }
4479 4664
4480 public bool IncomingCloseChildAgent(UUID agentID) 4665// public bool IncomingCloseChildAgent(UUID agentID)
4666// {
4667// return IncomingCloseAgent(agentID, true);
4668// }
4669
4670 /// <summary>
4671 /// Tell a single client to prepare to close.
4672 /// </summary>
4673 /// <remarks>
4674 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4675 /// internal use - other callers should almost certainly called CloseClient().
4676 /// </remarks>
4677 /// <param name="sp"></param>
4678 /// <returns>true if pre-close state notification was successful. false if the agent
4679 /// was not in a state where it could transition to pre-close.</returns>
4680 public bool IncomingPreCloseClient(ScenePresence sp)
4481 { 4681 {
4482 return IncomingCloseAgent(agentID, true); 4682 lock (m_removeClientLock)
4683 {
4684 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4685 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4686 // want to obey this close since C may have renewed the child agent lease on B.
4687 if (sp.DoNotCloseAfterTeleport)
4688 {
4689 m_log.DebugFormat(
4690 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4691 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4692
4693 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4694 sp.DoNotCloseAfterTeleport = false;
4695
4696 return false;
4697 }
4698
4699 if (sp.LifecycleState != ScenePresenceState.Running)
4700 {
4701 m_log.DebugFormat(
4702 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4703 sp.Name, Name, sp.LifecycleState);
4704
4705 return false;
4706 }
4707
4708 sp.LifecycleState = ScenePresenceState.PreRemove;
4709
4710 return true;
4711 }
4483 } 4712 }
4484 4713
4485 /// <summary> 4714 /// <summary>
@@ -4490,18 +4719,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 4719 /// 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. 4720 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4492 /// </param> 4721 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4722 public override bool CloseAgent(UUID agentID, bool force)
4494 { 4723 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4724 ScenePresence sp;
4496 4725
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4726 lock (m_removeClientLock)
4498 if (presence != null)
4499 { 4727 {
4500 presence.ControllingClient.Close(force, force); 4728 sp = GetScenePresence(agentID);
4729
4730 if (sp == null)
4731 {
4732 m_log.DebugFormat(
4733 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4734 agentID, Name);
4735
4736 return false;
4737 }
4738
4739 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4740 {
4741 m_log.DebugFormat(
4742 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4743 sp.Name, Name, sp.LifecycleState);
4744
4745 return false;
4746 }
4747
4748 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4749 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4750 // want to obey this close since C may have renewed the child agent lease on B.
4751 if (sp.DoNotCloseAfterTeleport)
4752 {
4753 m_log.DebugFormat(
4754 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4755 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4756
4757 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4758 sp.DoNotCloseAfterTeleport = false;
4759
4760 return false;
4761 }
4762
4763 sp.LifecycleState = ScenePresenceState.Removing;
4764 }
4765
4766 if (sp != null)
4767 {
4768 sp.ControllingClient.Close(force, force);
4501 return true; 4769 return true;
4502 } 4770 }
4503 4771
4504 // Agent not here 4772 // Agent not here
4505 return false; 4773 return false;
4506 } 4774 }
4507 4775
@@ -5091,21 +5359,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5359
5092 #endregion 5360 #endregion
5093 5361
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 5362
5110// Commented pending deletion since this method no longer appears to do anything at all 5363// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5364// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5910,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5910 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5911 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5912 {
5660 minX = 256; 5913 minX = float.MaxValue;
5661 maxX = -256; 5914 maxX = float.MinValue;
5662 minY = 256; 5915 minY = float.MaxValue;
5663 maxY = -256; 5916 maxY = float.MinValue;
5664 minZ = 8192; 5917 minZ = float.MaxValue;
5665 maxZ = -256; 5918 maxZ = float.MinValue;
5666 5919
5667 List<Vector3> offsets = new List<Vector3>(); 5920 List<Vector3> offsets = new List<Vector3>();
5668 5921
@@ -5802,17 +6055,6 @@ Environment.Exit(1);
5802 { 6055 {
5803 reason = "You are banned from the region"; 6056 reason = "You are banned from the region";
5804 6057
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)) 6058 if (Permissions.IsGod(agentID))
5817 { 6059 {
5818 reason = String.Empty; 6060 reason = String.Empty;
@@ -5862,9 +6104,9 @@ Environment.Exit(1);
5862 6104
5863 try 6105 try
5864 { 6106 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6107 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6108 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6109 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6110 return false;
5869 } 6111 }
5870 } 6112 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 74c9582..dd0c828 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -1,575 +1,581 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading; 31using System.Threading;
32using OpenMetaverse; 32using OpenMetaverse;
33using log4net; 33using log4net;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37 37
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using GridRegion = OpenSim.Services.Interfaces.GridRegion; 39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40 40
41namespace OpenSim.Region.Framework.Scenes 41namespace 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 46 protected static readonly string LogHeader = "[SCENE]";
47 #region Events 47
48 48 #region Events
49 public event restart OnRestart; 49
50 50 public event restart OnRestart;
51 #endregion 51
52 52 #endregion
53 #region Fields 53
54 54 #region Fields
55 public string Name { get { return RegionInfo.RegionName; } } 55
56 56 public string Name { get { return RegionInfo.RegionName; } }
57 public IConfigSource Config 57
58 { 58 public IConfigSource Config
59 get { return GetConfig(); } 59 {
60 } 60 get { return GetConfig(); }
61 61 }
62 protected virtual IConfigSource GetConfig() 62
63 { 63 protected virtual IConfigSource GetConfig()
64 return null; 64 {
65 } 65 return null;
66 66 }
67 /// <value> 67
68 /// All the region modules attached to this scene. 68 /// <value>
69 /// </value> 69 /// All the region modules attached to this scene.
70 public Dictionary<string, IRegionModuleBase> RegionModules 70 /// </value>
71 { 71 public Dictionary<string, IRegionModuleBase> RegionModules
72 get { return m_regionModules; } 72 {
73 } 73 get { return m_regionModules; }
74 private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>(); 74 }
75 75 private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>();
76 /// <value> 76
77 /// The module interfaces available from this scene. 77 /// <value>
78 /// </value> 78 /// The module interfaces available from this scene.
79 protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>(); 79 /// </value>
80 80 protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>();
81 protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>(); 81
82 82 protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>();
83 /// <value> 83
84 /// The module commanders available from this scene 84 /// <value>
85 /// </value> 85 /// The module commanders available from this scene
86 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>(); 86 /// </value>
87 87 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
88 /// <value> 88
89 /// Registered classes that are capable of creating entities. 89 /// <value>
90 /// </value> 90 /// Registered classes that are capable of creating entities.
91 protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>(); 91 /// </value>
92 92 protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>();
93 /// <summary> 93
94 /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is 94 /// <summary>
95 /// dispensed. 95 /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
96 /// </summary> 96 /// dispensed.
97 protected uint m_lastAllocatedLocalId = 720000; 97 /// </summary>
98 98 protected uint m_lastAllocatedLocalId = 720000;
99 private readonly Mutex _primAllocateMutex = new Mutex(false); 99
100 100 private readonly Mutex _primAllocateMutex = new Mutex(false);
101 protected readonly ClientManager m_clientManager = new ClientManager(); 101
102 102 protected readonly ClientManager m_clientManager = new ClientManager();
103 public bool LoginsEnabled 103
104 { 104 public bool LoginsEnabled
105 get 105 {
106 { 106 get
107 return m_loginsEnabled; 107 {
108 } 108 return m_loginsEnabled;
109 109 }
110 set 110
111 { 111 set
112 if (m_loginsEnabled != value) 112 {
113 { 113 if (m_loginsEnabled != value)
114 m_loginsEnabled = value; 114 {
115 EventManager.TriggerRegionLoginsStatusChange(this); 115 m_loginsEnabled = value;
116 } 116 EventManager.TriggerRegionLoginsStatusChange(this);
117 } 117 }
118 } 118 }
119 private bool m_loginsEnabled; 119 }
120 120 private bool m_loginsEnabled;
121 public bool Ready 121
122 { 122 public bool Ready
123 get 123 {
124 { 124 get
125 return m_ready; 125 {
126 } 126 return m_ready;
127 127 }
128 set 128
129 { 129 set
130 if (m_ready != value) 130 {
131 { 131 if (m_ready != value)
132 m_ready = value; 132 {
133 EventManager.TriggerRegionReadyStatusChange(this); 133 m_ready = value;
134 } 134 EventManager.TriggerRegionReadyStatusChange(this);
135 } 135 }
136 } 136 }
137 private bool m_ready; 137 }
138 138 private bool m_ready;
139 public float TimeDilation 139
140 { 140 public float TimeDilation
141 get { return 1.0f; } 141 {
142 } 142 get { return 1.0f; }
143 143 }
144 protected ulong m_regionHandle; 144
145 protected string m_regionName; 145 protected ulong m_regionHandle;
146 146 protected string m_regionName;
147 public ITerrainChannel Heightmap; 147
148 148 public ITerrainChannel Heightmap;
149 /// <value> 149
150 /// Allows retrieval of land information for this scene. 150 /// <value>
151 /// </value> 151 /// Allows retrieval of land information for this scene.
152 public ILandChannel LandChannel; 152 /// </value>
153 153 public ILandChannel LandChannel;
154 /// <value> 154
155 /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules 155 /// <value>
156 /// to subscribe to scene events. 156 /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules
157 /// </value> 157 /// to subscribe to scene events.
158 public EventManager EventManager 158 /// </value>
159 { 159 public EventManager EventManager
160 get { return m_eventManager; } 160 {
161 } 161 get { return m_eventManager; }
162 protected EventManager m_eventManager; 162 }
163 163 protected EventManager m_eventManager;
164 protected ScenePermissions m_permissions; 164
165 public ScenePermissions Permissions 165 protected ScenePermissions m_permissions;
166 { 166 public ScenePermissions Permissions
167 get { return m_permissions; } 167 {
168 } 168 get { return m_permissions; }
169 169 }
170 protected string m_datastore; 170
171 171 protected string m_datastore;
172 /* Used by the loadbalancer plugin on GForge */ 172
173 protected RegionStatus m_regStatus; 173 /* Used by the loadbalancer plugin on GForge */
174 public RegionStatus RegionStatus 174 protected RegionStatus m_regStatus;
175 { 175 public RegionStatus RegionStatus
176 get { return m_regStatus; } 176 {
177 set { m_regStatus = value; } 177 get { return m_regStatus; }
178 } 178 set { m_regStatus = value; }
179 179 }
180 #endregion 180
181 181 #endregion
182 public SceneBase(RegionInfo regInfo) 182
183 { 183 public SceneBase(RegionInfo regInfo)
184 RegionInfo = regInfo; 184 {
185 } 185 RegionInfo = regInfo;
186 186 }
187 #region Update Methods 187
188 188 #region Update Methods
189 /// <summary> 189
190 /// Called to update the scene loop by a number of frames and until shutdown. 190 /// <summary>
191 /// </summary> 191 /// Called to update the scene loop by a number of frames and until shutdown.
192 /// <param name="frames"> 192 /// </summary>
193 /// Number of frames to update. Exits on shutdown even if there are frames remaining. 193 /// <param name="frames">
194 /// If -1 then updates until shutdown. 194 /// Number of frames to update. Exits on shutdown even if there are frames remaining.
195 /// </param> 195 /// If -1 then updates until shutdown.
196 public abstract void Update(int frames); 196 /// </param>
197 197 public abstract void Update(int frames);
198 #endregion 198
199 199 #endregion
200 #region Terrain Methods 200
201 201 #region Terrain Methods
202 /// <summary> 202
203 /// Loads the World heightmap 203 /// <summary>
204 /// </summary> 204 /// Loads the World heightmap
205 public abstract void LoadWorldMap(); 205 /// </summary>
206 206 public abstract void LoadWorldMap();
207 /// <summary> 207
208 /// Send the region heightmap to the client 208 /// <summary>
209 /// </summary> 209 /// Send the region heightmap to the client
210 /// <param name="RemoteClient">Client to send to</param> 210 /// </summary>
211 public virtual void SendLayerData(IClientAPI RemoteClient) 211 /// <param name="RemoteClient">Client to send to</param>
212 { 212 public virtual void SendLayerData(IClientAPI RemoteClient)
213 RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); 213 {
214 } 214 RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
215 215 }
216 #endregion 216
217 217 #endregion
218 #region Add/Remove Agent/Avatar 218
219 219 #region Add/Remove Agent/Avatar
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 220
221 public abstract void RemoveClient(UUID agentID, bool closeChildAgents); 221 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
222 222
223 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 223 public abstract bool CloseAgent(UUID agentID, bool force);
224 { 224
225 scenePresence = null; 225 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
226 ScenePresence sp = null; 226 {
227 if (TryGetScenePresence(agentID, out sp)) 227 scenePresence = null;
228 { 228 ScenePresence sp = null;
229 scenePresence = sp; 229 if (TryGetScenePresence(agentID, out sp))
230 return true; 230 {
231 } 231 scenePresence = sp;
232 232 return true;
233 return false; 233 }
234 } 234
235 235 return false;
236 /// <summary> 236 }
237 /// Try to get a scene presence from the scene 237
238 /// </summary> 238 /// <summary>
239 /// <param name="agentID"></param> 239 /// Try to get a scene presence from the scene
240 /// <param name="scenePresence">null if there is no scene presence with the given agent id</param> 240 /// </summary>
241 /// <returns>true if there was a scene presence with the given id, false otherwise.</returns> 241 /// <param name="agentID"></param>
242 public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); 242 /// <param name="scenePresence">null if there is no scene presence with the given agent id</param>
243 243 /// <returns>true if there was a scene presence with the given id, false otherwise.</returns>
244 #endregion 244 public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence);
245 245
246 /// <summary> 246 #endregion
247 /// 247
248 /// </summary> 248 /// <summary>
249 /// <returns></returns> 249 ///
250 public virtual RegionInfo RegionInfo { get; private set; } 250 /// </summary>
251 251 /// <returns></returns>
252 #region admin stuff 252 public virtual RegionInfo RegionInfo { get; private set; }
253 253
254 public abstract void OtherRegionUp(GridRegion otherRegion); 254 #region admin stuff
255 255
256 public virtual string GetSimulatorVersion() 256 public abstract void OtherRegionUp(GridRegion otherRegion);
257 { 257
258 return "OpenSimulator Server"; 258 public virtual string GetSimulatorVersion()
259 } 259 {
260 260 return "OpenSimulator Server";
261 #endregion 261 }
262 262
263 #region Shutdown 263 #endregion
264 264
265 /// <summary> 265 #region Shutdown
266 /// Tidy before shutdown 266
267 /// </summary> 267 /// <summary>
268 public virtual void Close() 268 /// Tidy before shutdown
269 { 269 /// </summary>
270 try 270 public virtual void Close()
271 { 271 {
272 EventManager.TriggerShutdown(); 272 try
273 } 273 {
274 catch (Exception e) 274 EventManager.TriggerShutdown();
275 { 275 }
276 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); 276 catch (Exception e)
277 } 277 {
278 } 278 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e));
279 279 }
280 #endregion 280 }
281 281
282 /// <summary> 282 #endregion
283 /// Returns a new unallocated local ID 283
284 /// </summary> 284 /// <summary>
285 /// <returns>A brand new local ID</returns> 285 /// Returns a new unallocated local ID
286 public uint AllocateLocalId() 286 /// </summary>
287 { 287 /// <returns>A brand new local ID</returns>
288 uint myID; 288 public uint AllocateLocalId()
289 289 {
290 _primAllocateMutex.WaitOne(); 290 uint myID;
291 myID = ++m_lastAllocatedLocalId; 291
292 _primAllocateMutex.ReleaseMutex(); 292 _primAllocateMutex.WaitOne();
293 293 myID = ++m_lastAllocatedLocalId;
294 return myID; 294 _primAllocateMutex.ReleaseMutex();
295 } 295
296 296 return myID;
297 #region Module Methods 297 }
298 298
299 /// <summary> 299 #region Module Methods
300 /// Add a region-module to this scene. TODO: This will replace AddModule in the future. 300
301 /// </summary> 301 /// <summary>
302 /// <param name="name"></param> 302 /// Add a region-module to this scene. TODO: This will replace AddModule in the future.
303 /// <param name="module"></param> 303 /// </summary>
304 public void AddRegionModule(string name, IRegionModuleBase module) 304 /// <param name="name"></param>
305 { 305 /// <param name="module"></param>
306 if (!RegionModules.ContainsKey(name)) 306 public void AddRegionModule(string name, IRegionModuleBase module)
307 { 307 {
308 RegionModules.Add(name, module); 308 if (!RegionModules.ContainsKey(name))
309 } 309 {
310 } 310 RegionModules.Add(name, module);
311 311 }
312 public void RemoveRegionModule(string name) 312 }
313 { 313
314 RegionModules.Remove(name); 314 public void RemoveRegionModule(string name)
315 } 315 {
316 316 RegionModules.Remove(name);
317 /// <summary> 317 }
318 /// Register a module commander. 318
319 /// </summary> 319 /// <summary>
320 /// <param name="commander"></param> 320 /// Register a module commander.
321 public void RegisterModuleCommander(ICommander commander) 321 /// </summary>
322 { 322 /// <param name="commander"></param>
323 lock (m_moduleCommanders) 323 public void RegisterModuleCommander(ICommander commander)
324 { 324 {
325 m_moduleCommanders.Add(commander.Name, commander); 325 lock (m_moduleCommanders)
326 } 326 {
327 } 327 m_moduleCommanders.Add(commander.Name, commander);
328 328 }
329 /// <summary> 329 }
330 /// Unregister a module commander and all its commands 330
331 /// </summary> 331 /// <summary>
332 /// <param name="name"></param> 332 /// Unregister a module commander and all its commands
333 public void UnregisterModuleCommander(string name) 333 /// </summary>
334 { 334 /// <param name="name"></param>
335 lock (m_moduleCommanders) 335 public void UnregisterModuleCommander(string name)
336 { 336 {
337 ICommander commander; 337 lock (m_moduleCommanders)
338 if (m_moduleCommanders.TryGetValue(name, out commander)) 338 {
339 m_moduleCommanders.Remove(name); 339 ICommander commander;
340 } 340 if (m_moduleCommanders.TryGetValue(name, out commander))
341 } 341 m_moduleCommanders.Remove(name);
342 342 }
343 /// <summary> 343 }
344 /// Get a module commander 344
345 /// </summary> 345 /// <summary>
346 /// <param name="name"></param> 346 /// Get a module commander
347 /// <returns>The module commander, null if no module commander with that name was found</returns> 347 /// </summary>
348 public ICommander GetCommander(string name) 348 /// <param name="name"></param>
349 { 349 /// <returns>The module commander, null if no module commander with that name was found</returns>
350 lock (m_moduleCommanders) 350 public ICommander GetCommander(string name)
351 { 351 {
352 if (m_moduleCommanders.ContainsKey(name)) 352 lock (m_moduleCommanders)
353 return m_moduleCommanders[name]; 353 {
354 } 354 if (m_moduleCommanders.ContainsKey(name))
355 355 return m_moduleCommanders[name];
356 return null; 356 }
357 } 357
358 358 return null;
359 public Dictionary<string, ICommander> GetCommanders() 359 }
360 { 360
361 return m_moduleCommanders; 361 public Dictionary<string, ICommander> GetCommanders()
362 } 362 {
363 363 return m_moduleCommanders;
364 /// <summary> 364 }
365 /// Register an interface to a region module. This allows module methods to be called directly as 365
366 /// well as via events. If there is already a module registered for this interface, it is not replaced 366 /// <summary>
367 /// (is this the best behaviour?) 367 /// Register an interface to a region module. This allows module methods to be called directly as
368 /// </summary> 368 /// well as via events. If there is already a module registered for this interface, it is not replaced
369 /// <param name="mod"></param> 369 /// (is this the best behaviour?)
370 public void RegisterModuleInterface<M>(M mod) 370 /// </summary>
371 { 371 /// <param name="mod"></param>
372// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); 372 public void RegisterModuleInterface<M>(M mod)
373 373 {
374 List<Object> l = null; 374// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M));
375 if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) 375
376 { 376 List<Object> l = null;
377 l = new List<Object>(); 377 if (!ModuleInterfaces.TryGetValue(typeof(M), out l))
378 ModuleInterfaces.Add(typeof(M), l); 378 {
379 } 379 l = new List<Object>();
380 380 ModuleInterfaces.Add(typeof(M), l);
381 if (l.Count > 0) 381 }
382 return; 382
383 383 if (l.Count > 0)
384 l.Add(mod); 384 return;
385 385
386 if (mod is IEntityCreator) 386 l.Add(mod);
387 { 387
388 IEntityCreator entityCreator = (IEntityCreator)mod; 388 if (mod is IEntityCreator)
389 foreach (PCode pcode in entityCreator.CreationCapabilities) 389 {
390 { 390 IEntityCreator entityCreator = (IEntityCreator)mod;
391 m_entityCreators[pcode] = entityCreator; 391 foreach (PCode pcode in entityCreator.CreationCapabilities)
392 } 392 {
393 } 393 m_entityCreators[pcode] = entityCreator;
394 } 394 }
395 395 }
396 public void UnregisterModuleInterface<M>(M mod) 396 }
397 { 397
398 List<Object> l; 398 public void UnregisterModuleInterface<M>(M mod)
399 if (ModuleInterfaces.TryGetValue(typeof(M), out l)) 399 {
400 { 400 List<Object> l;
401 if (l.Remove(mod)) 401 if (ModuleInterfaces.TryGetValue(typeof(M), out l))
402 { 402 {
403 if (mod is IEntityCreator) 403 if (l.Remove(mod))
404 { 404 {
405 IEntityCreator entityCreator = (IEntityCreator)mod; 405 if (mod is IEntityCreator)
406 foreach (PCode pcode in entityCreator.CreationCapabilities) 406 {
407 { 407 IEntityCreator entityCreator = (IEntityCreator)mod;
408 m_entityCreators[pcode] = null; 408 foreach (PCode pcode in entityCreator.CreationCapabilities)
409 } 409 {
410 } 410 m_entityCreators[pcode] = null;
411 } 411 }
412 } 412 }
413 } 413 }
414 414 }
415 public void StackModuleInterface<M>(M mod) 415 }
416 { 416
417 List<Object> l; 417 public void StackModuleInterface<M>(M mod)
418 if (ModuleInterfaces.ContainsKey(typeof(M))) 418 {
419 l = ModuleInterfaces[typeof(M)]; 419 List<Object> l;
420 else 420 if (ModuleInterfaces.ContainsKey(typeof(M)))
421 l = new List<Object>(); 421 l = ModuleInterfaces[typeof(M)];
422 422 else
423 if (l.Contains(mod)) 423 l = new List<Object>();
424 return; 424
425 425 if (l.Contains(mod))
426 l.Add(mod); 426 return;
427 427
428 if (mod is IEntityCreator) 428 l.Add(mod);
429 { 429
430 IEntityCreator entityCreator = (IEntityCreator)mod; 430 if (mod is IEntityCreator)
431 foreach (PCode pcode in entityCreator.CreationCapabilities) 431 {
432 { 432 IEntityCreator entityCreator = (IEntityCreator)mod;
433 m_entityCreators[pcode] = entityCreator; 433 foreach (PCode pcode in entityCreator.CreationCapabilities)
434 } 434 {
435 } 435 m_entityCreators[pcode] = entityCreator;
436 436 }
437 ModuleInterfaces[typeof(M)] = l; 437 }
438 } 438
439 439 ModuleInterfaces[typeof(M)] = l;
440 /// <summary> 440 }
441 /// For the given interface, retrieve the region module which implements it. 441
442 /// </summary> 442 /// <summary>
443 /// <returns>null if there is no registered module implementing that interface</returns> 443 /// For the given interface, retrieve the region module which implements it.
444 public T RequestModuleInterface<T>() 444 /// </summary>
445 { 445 /// <returns>null if there is no registered module implementing that interface</returns>
446 if (ModuleInterfaces.ContainsKey(typeof(T)) && 446 public T RequestModuleInterface<T>()
447 (ModuleInterfaces[typeof(T)].Count > 0)) 447 {
448 return (T)ModuleInterfaces[typeof(T)][0]; 448 if (ModuleInterfaces.ContainsKey(typeof(T)) &&
449 else 449 (ModuleInterfaces[typeof(T)].Count > 0))
450 return default(T); 450 return (T)ModuleInterfaces[typeof(T)][0];
451 } 451 else
452 452 return default(T);
453 /// <summary> 453 }
454 /// For the given interface, retrieve an array of region modules that implement it. 454
455 /// </summary> 455 /// <summary>
456 /// <returns>an empty array if there are no registered modules implementing that interface</returns> 456 /// For the given interface, retrieve an array of region modules that implement it.
457 public T[] RequestModuleInterfaces<T>() 457 /// </summary>
458 { 458 /// <returns>an empty array if there are no registered modules implementing that interface</returns>
459 if (ModuleInterfaces.ContainsKey(typeof(T))) 459 public T[] RequestModuleInterfaces<T>()
460 { 460 {
461 List<T> ret = new List<T>(); 461 if (ModuleInterfaces.ContainsKey(typeof(T)))
462 462 {
463 foreach (Object o in ModuleInterfaces[typeof(T)]) 463 List<T> ret = new List<T>();
464 ret.Add((T)o); 464
465 return ret.ToArray(); 465 foreach (Object o in ModuleInterfaces[typeof(T)])
466 } 466 ret.Add((T)o);
467 else 467 return ret.ToArray();
468 { 468 }
469 return new T[] {}; 469 else
470 } 470 {
471 } 471 return new T[] {};
472 472 }
473 #endregion 473 }
474 474
475 /// <summary> 475 #endregion
476 /// Call this from a region module to add a command to the OpenSim console. 476
477 /// </summary> 477 /// <summary>
478 /// <param name="mod"></param> 478 /// Call this from a region module to add a command to the OpenSim console.
479 /// <param name="command"></param> 479 /// </summary>
480 /// <param name="shorthelp"></param> 480 /// <param name="mod"></param>
481 /// <param name="longhelp"></param> 481 /// <param name="command"></param>
482 /// <param name="callback"></param> 482 /// <param name="shorthelp"></param>
483 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) 483 /// <param name="longhelp"></param>
484 { 484 /// <param name="callback"></param>
485 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); 485 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
486 } 486 {
487 487 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback);
488 /// <summary> 488 }
489 /// Call this from a region module to add a command to the OpenSim console. 489
490 /// </summary> 490 /// <summary>
491 /// <param name="mod"> 491 /// Call this from a region module to add a command to the OpenSim console.
492 /// The use of IRegionModuleBase is a cheap trick to get a different method signature, 492 /// </summary>
493 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. 493 /// <param name="mod">
494 /// </param> 494 /// The use of IRegionModuleBase is a cheap trick to get a different method signature,
495 /// <param name="category"> 495 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway.
496 /// Category of the command. This is the section under which it will appear when the user asks for help 496 /// </param>
497 /// </param> 497 /// <param name="category">
498 /// <param name="command"></param> 498 /// Category of the command. This is the section under which it will appear when the user asks for help
499 /// <param name="shorthelp"></param> 499 /// </param>
500 /// <param name="longhelp"></param> 500 /// <param name="command"></param>
501 /// <param name="callback"></param> 501 /// <param name="shorthelp"></param>
502 public void AddCommand( 502 /// <param name="longhelp"></param>
503 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) 503 /// <param name="callback"></param>
504 { 504 public void AddCommand(
505 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); 505 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
506 } 506 {
507 507 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback);
508 /// <summary> 508 }
509 /// Call this from a region module to add a command to the OpenSim console. 509
510 /// </summary> 510 /// <summary>
511 /// <param name="mod"></param> 511 /// Call this from a region module to add a command to the OpenSim console.
512 /// <param name="command"></param> 512 /// </summary>
513 /// <param name="shorthelp"></param> 513 /// <param name="mod"></param>
514 /// <param name="longhelp"></param> 514 /// <param name="command"></param>
515 /// <param name="descriptivehelp"></param> 515 /// <param name="shorthelp"></param>
516 /// <param name="callback"></param> 516 /// <param name="longhelp"></param>
517 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 517 /// <param name="descriptivehelp"></param>
518 { 518 /// <param name="callback"></param>
519 string moduleName = ""; 519 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
520 520 {
521 if (module != null) 521 string moduleName = "";
522 moduleName = module.Name; 522
523 523 if (module != null)
524 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); 524 moduleName = module.Name;
525 } 525
526 526 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback);
527 /// <summary> 527 }
528 /// Call this from a region module to add a command to the OpenSim console. 528
529 /// </summary> 529 /// <summary>
530 /// <param name="category"> 530 /// Call this from a region module to add a command to the OpenSim console.
531 /// Category of the command. This is the section under which it will appear when the user asks for help 531 /// </summary>
532 /// </param> 532 /// <param name="category">
533 /// <param name="mod"></param> 533 /// Category of the command. This is the section under which it will appear when the user asks for help
534 /// <param name="command"></param> 534 /// </param>
535 /// <param name="shorthelp"></param> 535 /// <param name="mod"></param>
536 /// <param name="longhelp"></param> 536 /// <param name="command"></param>
537 /// <param name="descriptivehelp"></param> 537 /// <param name="shorthelp"></param>
538 /// <param name="callback"></param> 538 /// <param name="longhelp"></param>
539 public void AddCommand( 539 /// <param name="descriptivehelp"></param>
540 string category, IRegionModuleBase module, string command, 540 /// <param name="callback"></param>
541 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 541 public void AddCommand(
542 { 542 string category, IRegionModuleBase module, string command,
543 if (MainConsole.Instance == null) 543 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
544 return; 544 {
545 545 if (MainConsole.Instance == null)
546 bool shared = false; 546 return;
547 547
548 if (module != null) 548 bool shared = false;
549 shared = module is ISharedRegionModule; 549
550 550 if (module != null)
551 MainConsole.Instance.Commands.AddCommand( 551 shared = module is ISharedRegionModule;
552 category, shared, command, shorthelp, longhelp, descriptivehelp, callback); 552
553 } 553 MainConsole.Instance.Commands.AddCommand(
554 554 category, shared, command, shorthelp, longhelp, descriptivehelp, callback);
555 public virtual ISceneObject DeserializeObject(string representation) 555 }
556 { 556
557 return null; 557 public virtual ISceneObject DeserializeObject(string representation)
558 } 558 {
559 559 return null;
560 public virtual bool AllowScriptCrossings 560 }
561 { 561
562 get { return false; } 562 public virtual bool AllowScriptCrossings
563 } 563 {
564 564 get { return false; }
565 public void Restart() 565 }
566 { 566
567 // This has to be here to fire the event 567 public virtual void Start()
568 restart handlerPhysicsCrash = OnRestart; 568 {
569 if (handlerPhysicsCrash != null) 569 }
570 handlerPhysicsCrash(RegionInfo); 570
571 } 571 public void Restart()
572 572 {
573 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); 573 // This has to be here to fire the event
574 } 574 restart handlerPhysicsCrash = OnRestart;
575} 575 if (handlerPhysicsCrash != null)
576 handlerPhysicsCrash(RegionInfo);
577 }
578
579 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
580 }
581}
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..28758a9 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;
@@ -549,10 +550,19 @@ namespace OpenSim.Region.Framework.Scenes
549 Vector3 newpos = Vector3.Zero; 550 Vector3 newpos = Vector3.Zero;
550 OpenSim.Services.Interfaces.GridRegion destination = null; 551 OpenSim.Services.Interfaces.GridRegion destination = null;
551 552
553 if (m_rootPart.DIE_AT_EDGE || m_rootPart.RETURN_AT_EDGE)
554 {
555 // this should delete the grp in this case
556 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
557 // actually assume this sog was removed from simulation
558 return;
559 }
560
552 if (m_rootPart.KeyframeMotion != null) 561 if (m_rootPart.KeyframeMotion != null)
553 m_rootPart.KeyframeMotion.StartCrossingCheck(); 562 m_rootPart.KeyframeMotion.StartCrossingCheck();
554 563
555 bool canCross = true; 564 bool canCross = true;
565
556 foreach (ScenePresence av in m_linkedAvatars) 566 foreach (ScenePresence av in m_linkedAvatars)
557 { 567 {
558 // We need to cross these agents. First, let's find 568 // We need to cross these agents. First, let's find
@@ -637,11 +647,10 @@ namespace OpenSim.Region.Framework.Scenes
637 ScenePresence av = avinfo.av; 647 ScenePresence av = avinfo.av;
638 av.ParentUUID = UUID.Zero; 648 av.ParentUUID = UUID.Zero;
639 av.ParentID = avinfo.ParentID; 649 av.ParentID = avinfo.ParentID;
640// m_linkedAvatars.Add(av); 650 // m_linkedAvatars.Add(av);
641 } 651 }
642 } 652 }
643 avsToCross.Clear(); 653 avsToCross.Clear();
644
645 } 654 }
646 else 655 else
647 { 656 {
@@ -656,16 +665,11 @@ namespace OpenSim.Region.Framework.Scenes
656 Vector3 oldp = AbsolutePosition; 665 Vector3 oldp = AbsolutePosition;
657 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); 666 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
658 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); 667 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
659 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f); 668 // dont crash land StarShips
669 // val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
660 } 670 }
661 } 671 }
662 672
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()) 673 if (RootPart.GetStatusSandbox())
670 { 674 {
671 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 675 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -680,17 +684,35 @@ namespace OpenSim.Region.Framework.Scenes
680 } 684 }
681 } 685 }
682 686
683 // Restuff the new GroupPosition into each SOP of the linkset.
684 // This has the affect of resetting and tainting the physics actors.
685 SceneObjectPart[] parts = m_parts.GetArray();
686 bool triggerScriptEvent = m_rootPart.GroupPosition != val; 687 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
687 if (m_dupeInProgress) 688 if (m_dupeInProgress || IsDeleted)
688 triggerScriptEvent = false; 689 triggerScriptEvent = false;
690
691 m_rootPart.GroupPosition = val;
692
693 // Restuff the new GroupPosition into each child SOP of the linkset.
694 // this is needed because physics may not have linksets but just loose SOPs in world
695
696 SceneObjectPart[] parts = m_parts.GetArray();
697
689 foreach (SceneObjectPart part in parts) 698 foreach (SceneObjectPart part in parts)
690 { 699 {
691 part.GroupPosition = val; 700 if (part != m_rootPart)
692 if (triggerScriptEvent) 701 part.GroupPosition = val;
702 }
703
704 foreach (ScenePresence av in m_linkedAvatars)
705 {
706 av.sitSOGmoved();
707 }
708
709 // now that position is changed tell it to scripts
710 if (triggerScriptEvent)
711 {
712 foreach (SceneObjectPart part in parts)
713 {
693 part.TriggerScriptChangedEvent(Changed.POSITION); 714 part.TriggerScriptChangedEvent(Changed.POSITION);
715 }
694 } 716 }
695 717
696/* 718/*
@@ -744,6 +766,7 @@ namespace OpenSim.Region.Framework.Scenes
744 { 766 {
745 if (agent.ParentUUID != UUID.Zero) 767 if (agent.ParentUUID != UUID.Zero)
746 { 768 {
769 agent.ClearControls();
747 agent.ParentPart = null; 770 agent.ParentPart = null;
748// agent.ParentPosition = Vector3.Zero; 771// agent.ParentPosition = Vector3.Zero;
749// agent.ParentUUID = UUID.Zero; 772// agent.ParentUUID = UUID.Zero;
@@ -751,7 +774,6 @@ namespace OpenSim.Region.Framework.Scenes
751 } 774 }
752 775
753 agent.ParentUUID = UUID.Zero; 776 agent.ParentUUID = UUID.Zero;
754
755// agent.Reset(); 777// agent.Reset();
756// else // Not successful 778// else // Not successful
757// agent.RestoreInCurrentScene(); 779// agent.RestoreInCurrentScene();
@@ -891,14 +913,14 @@ namespace OpenSim.Region.Framework.Scenes
891 } 913 }
892 } 914 }
893 } 915 }
894 916 // PlaySoundMasterPrim no longer in use to remove
895 private SceneObjectPart m_PlaySoundMasterPrim = null; 917 private SceneObjectPart m_PlaySoundMasterPrim = null;
896 public SceneObjectPart PlaySoundMasterPrim 918 public SceneObjectPart PlaySoundMasterPrim
897 { 919 {
898 get { return m_PlaySoundMasterPrim; } 920 get { return m_PlaySoundMasterPrim; }
899 set { m_PlaySoundMasterPrim = value; } 921 set { m_PlaySoundMasterPrim = value; }
900 } 922 }
901 923 // PlaySoundSlavePrims no longer in use to remove
902 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 924 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
903 public List<SceneObjectPart> PlaySoundSlavePrims 925 public List<SceneObjectPart> PlaySoundSlavePrims
904 { 926 {
@@ -906,6 +928,7 @@ namespace OpenSim.Region.Framework.Scenes
906 set { m_PlaySoundSlavePrims = value; } 928 set { m_PlaySoundSlavePrims = value; }
907 } 929 }
908 930
931 // LoopSoundMasterPrim no longer in use to remove
909 private SceneObjectPart m_LoopSoundMasterPrim = null; 932 private SceneObjectPart m_LoopSoundMasterPrim = null;
910 public SceneObjectPart LoopSoundMasterPrim 933 public SceneObjectPart LoopSoundMasterPrim
911 { 934 {
@@ -913,6 +936,7 @@ namespace OpenSim.Region.Framework.Scenes
913 set { m_LoopSoundMasterPrim = value; } 936 set { m_LoopSoundMasterPrim = value; }
914 } 937 }
915 938
939 // m_LoopSoundSlavePrims no longer in use to remove
916 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 940 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
917 public List<SceneObjectPart> LoopSoundSlavePrims 941 public List<SceneObjectPart> LoopSoundSlavePrims
918 { 942 {
@@ -1667,7 +1691,8 @@ namespace OpenSim.Region.Framework.Scenes
1667 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1691 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1668 if (avatar == null) 1692 if (avatar == null)
1669 return; 1693 return;
1670 1694 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1695 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1671 avatar.RemoveAttachment(this); 1696 avatar.RemoveAttachment(this);
1672 1697
1673 Vector3 detachedpos = new Vector3(127f,127f,127f); 1698 Vector3 detachedpos = new Vector3(127f,127f,127f);
@@ -1820,11 +1845,21 @@ namespace OpenSim.Region.Framework.Scenes
1820 // Setting this SOG's absolute position also loops through and sets the positions 1845 // Setting this SOG's absolute position also loops through and sets the positions
1821 // of the SOP's in this SOG's linkset. This has the side affect of making sure 1846 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1822 // the physics world matches the simulated world. 1847 // the physics world matches the simulated world.
1823 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1848 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1824 1849
1825 // teravus: AbsolutePosition is NOT a normal property! 1850 // teravus: AbsolutePosition is NOT a normal property!
1826 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1851 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1827 // jhurliman: Then why is it a property instead of two methods? 1852 // jhurliman: Then why is it a property instead of two methods?
1853
1854 // do only what is supposed to do
1855 Vector3 groupPosition = m_rootPart.GroupPosition;
1856 SceneObjectPart[] parts = m_parts.GetArray();
1857
1858 foreach (SceneObjectPart part in parts)
1859 {
1860 if (part != m_rootPart)
1861 part.GroupPosition = groupPosition;
1862 }
1828 } 1863 }
1829 1864
1830 public UUID GetPartsFullID(uint localID) 1865 public UUID GetPartsFullID(uint localID)
@@ -1868,11 +1903,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1903 /// <summary>
1869 /// Delete this group from its scene. 1904 /// Delete this group from its scene.
1870 /// </summary> 1905 /// </summary>
1871 /// 1906 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1907 /// 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 1908 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1909 /// must be handled by the caller.
1875 /// 1910 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1911 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1912 public void DeleteGroupFromScene(bool silent)
1878 { 1913 {
@@ -1901,7 +1936,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 if (!IsAttachment 1936 if (!IsAttachment
1902 || AttachedAvatar == avatar.ControllingClient.AgentId 1937 || AttachedAvatar == avatar.ControllingClient.AgentId
1903 || !HasPrivateAttachmentPoint) 1938 || !HasPrivateAttachmentPoint)
1904 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1939 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1905 } 1940 }
1906 } 1941 }
1907 }); 1942 });
@@ -2109,6 +2144,7 @@ namespace OpenSim.Region.Framework.Scenes
2109 2144
2110 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) 2145 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2111 { 2146 {
2147 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2112 RootPart.Shape.State = 0; 2148 RootPart.Shape.State = 0;
2113 ScheduleGroupForFullUpdate(); 2149 ScheduleGroupForFullUpdate();
2114 } 2150 }
@@ -2210,7 +2246,7 @@ namespace OpenSim.Region.Framework.Scenes
2210 if (!userExposed) 2246 if (!userExposed)
2211 dupe.IsAttachment = true; 2247 dupe.IsAttachment = true;
2212 2248
2213 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 2249 dupe.m_sittingAvatars = new List<UUID>();
2214 2250
2215 if (!userExposed) 2251 if (!userExposed)
2216 { 2252 {
@@ -3813,20 +3849,20 @@ namespace OpenSim.Region.Framework.Scenes
3813 /// <summary> 3849 /// <summary>
3814 /// Update just the root prim position in a linkset 3850 /// Update just the root prim position in a linkset
3815 /// </summary> 3851 /// </summary>
3816 /// <param name="pos"></param> 3852 /// <param name="newPos"></param>
3817 public void UpdateRootPosition(Vector3 pos) 3853 public void UpdateRootPosition(Vector3 newPos)
3818 { 3854 {
3819 // needs to be called with phys building true 3855 // needs to be called with phys building true
3820 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3856 Vector3 oldPos;
3821 Vector3 oldPos = 3857
3822 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3858 if (IsAttachment)
3823 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3859 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); 3860 else
3861 oldPos = AbsolutePosition + m_rootPart.OffsetPosition;
3862
3825 Vector3 diff = oldPos - newPos; 3863 Vector3 diff = oldPos - newPos;
3826 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3827 Quaternion partRotation = m_rootPart.RotationOffset; 3864 Quaternion partRotation = m_rootPart.RotationOffset;
3828 axDiff *= Quaternion.Inverse(partRotation); 3865 diff *= Quaternion.Inverse(partRotation);
3829 diff = axDiff;
3830 3866
3831 SceneObjectPart[] parts = m_parts.GetArray(); 3867 SceneObjectPart[] parts = m_parts.GetArray();
3832 for (int i = 0; i < parts.Length; i++) 3868 for (int i = 0; i < parts.Length; i++)
@@ -3837,6 +3873,9 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 3873 }
3838 3874
3839 AbsolutePosition = newPos; 3875 AbsolutePosition = newPos;
3876
3877 if (IsAttachment)
3878 m_rootPart.AttachedPos = newPos;
3840 3879
3841 HasGroupChanged = true; 3880 HasGroupChanged = true;
3842 if (m_rootPart.Undoing) 3881 if (m_rootPart.Undoing)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 566605a..98ea880 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
@@ -244,9 +251,6 @@ namespace OpenSim.Region.Framework.Scenes
244 public byte AttachPoint = 0; 251 public byte AttachPoint = 0;
245 252
246 [XmlIgnore] 253 [XmlIgnore]
247 public Vector3 AttachOffset = Vector3.Zero;
248
249 [XmlIgnore]
250 public Quaternion AttachRotation = Quaternion.Identity; 254 public Quaternion AttachRotation = Quaternion.Identity;
251 255
252 [XmlIgnore] 256 [XmlIgnore]
@@ -383,8 +387,6 @@ namespace OpenSim.Region.Framework.Scenes
383 387
384 private SOPVehicle m_vehicleParams = null; 388 private SOPVehicle m_vehicleParams = null;
385 389
386 private KeyframeMotion m_keyframeMotion = null;
387
388 public KeyframeMotion KeyframeMotion 390 public KeyframeMotion KeyframeMotion
389 { 391 {
390 get; set; 392 get; set;
@@ -506,7 +508,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 508 {
507 get 509 get
508 { 510 {
509 if (CreatorData != null && CreatorData != string.Empty) 511 if (!string.IsNullOrEmpty(CreatorData))
510 return CreatorID.ToString() + ';' + CreatorData; 512 return CreatorID.ToString() + ';' + CreatorData;
511 else 513 else
512 return CreatorID.ToString(); 514 return CreatorID.ToString();
@@ -536,7 +538,11 @@ namespace OpenSim.Region.Framework.Scenes
536 CreatorID = uuid; 538 CreatorID = uuid;
537 } 539 }
538 if (parts.Length >= 2) 540 if (parts.Length >= 2)
541 {
539 CreatorData = parts[1]; 542 CreatorData = parts[1];
543 if (!CreatorData.EndsWith("/"))
544 CreatorData += "/";
545 }
540 if (parts.Length >= 3) 546 if (parts.Length >= 3)
541 name = parts[2]; 547 name = parts[2];
542 548
@@ -815,7 +821,8 @@ namespace OpenSim.Region.Framework.Scenes
815 } 821 }
816 822
817 // Tell the physics engines that this prim changed. 823 // Tell the physics engines that this prim changed.
818 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 824 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
825 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
819 } 826 }
820 catch (Exception e) 827 catch (Exception e)
821 { 828 {
@@ -933,7 +940,7 @@ namespace OpenSim.Region.Framework.Scenes
933 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 940 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
934 } 941 }
935 942
936 if (ParentGroup != null) 943 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
937 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 944 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
938 //} 945 //}
939 } 946 }
@@ -1218,23 +1225,14 @@ namespace OpenSim.Region.Framework.Scenes
1218 // the mappings more consistant. 1225 // the mappings more consistant.
1219 public Vector3 SitTargetPositionLL 1226 public Vector3 SitTargetPositionLL
1220 { 1227 {
1221 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1228 get { return m_sitTargetPosition; }
1222 set { m_sitTargetPosition = value; } 1229 set { m_sitTargetPosition = value; }
1223 } 1230 }
1224 1231
1225 public Quaternion SitTargetOrientationLL 1232 public Quaternion SitTargetOrientationLL
1226 { 1233 {
1227 get 1234 get { return m_sitTargetOrientation; }
1228 { 1235 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 } 1236 }
1239 1237
1240 public bool Stopped 1238 public bool Stopped
@@ -2965,7 +2963,27 @@ namespace OpenSim.Region.Framework.Scenes
2965 } 2963 }
2966 //ParentGroup.RootPart.m_groupPosition = newpos; 2964 //ParentGroup.RootPart.m_groupPosition = newpos;
2967 } 2965 }
2968 2966/* ubit: there are no flexible links
2967 if (pa != null && ParentID != 0 && ParentGroup != null)
2968 {
2969 // Special case where a child object is requesting property updates.
2970 // This happens when linksets are modified to use flexible links rather than
2971 // the default links.
2972 // The simulator code presumes that child parts are only modified by scripts
2973 // so the logic for changing position/rotation/etc does not take into
2974 // account the physical object actually moving.
2975 // This code updates the offset position and rotation of the child and then
2976 // lets the update code push the update to the viewer.
2977 // Since physics engines do not normally generate this event for linkset children,
2978 // this code will not be active unless you have a specially configured
2979 // physics engine.
2980 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
2981 m_offsetPosition = pa.Position - m_groupPosition;
2982 RotationOffset = pa.Orientation * invRootRotation;
2983 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2984 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2985 }
2986*/
2969 ScheduleTerseUpdate(); 2987 ScheduleTerseUpdate();
2970 } 2988 }
2971 2989
@@ -3144,7 +3162,8 @@ namespace OpenSim.Region.Framework.Scenes
3144 return; 3162 return;
3145 3163
3146 // This was pulled from SceneViewer. Attachments always receive full updates. 3164 // This was pulled from SceneViewer. Attachments always receive full updates.
3147 // I could not verify if this is a requirement but this maintains existing behavior 3165 // This is needed because otherwise if only the root prim changes position, then
3166 // it looks as if the entire object has moved (including the other prims).
3148 if (ParentGroup.IsAttachment) 3167 if (ParentGroup.IsAttachment)
3149 { 3168 {
3150 ScheduleFullUpdate(); 3169 ScheduleFullUpdate();
@@ -3277,9 +3296,9 @@ namespace OpenSim.Region.Framework.Scenes
3277 return; 3296 return;
3278 3297
3279 // Suppress full updates during attachment editing 3298 // Suppress full updates during attachment editing
3280 // 3299 // sl Does send them
3281 if (ParentGroup.IsSelected && ParentGroup.IsAttachment) 3300 // if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
3282 return; 3301 // return;
3283 3302
3284 if (ParentGroup.IsDeleted) 3303 if (ParentGroup.IsDeleted)
3285 return; 3304 return;
@@ -4357,30 +4376,31 @@ namespace OpenSim.Region.Framework.Scenes
4357 } 4376 }
4358 } 4377 }
4359 4378
4360 public void UpdateGroupPosition(Vector3 pos) 4379 public void UpdateGroupPosition(Vector3 newPos)
4361 { 4380 {
4362 if ((pos.X != GroupPosition.X) || 4381 Vector3 oldPos = GroupPosition;
4363 (pos.Y != GroupPosition.Y) || 4382
4364 (pos.Z != GroupPosition.Z)) 4383 if ((newPos.X != oldPos.X) ||
4384 (newPos.Y != oldPos.Y) ||
4385 (newPos.Z != oldPos.Z))
4365 { 4386 {
4366 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4367 GroupPosition = newPos; 4387 GroupPosition = newPos;
4368 ScheduleTerseUpdate(); 4388 ScheduleTerseUpdate();
4369 } 4389 }
4370 } 4390 }
4371 4391
4372 /// <summary> 4392 /// <summary>
4373 /// 4393 /// Update this part's offset position.
4374 /// </summary> 4394 /// </summary>
4375 /// <param name="pos"></param> 4395 /// <param name="pos"></param>
4376 public void UpdateOffSet(Vector3 pos) 4396 public void UpdateOffSet(Vector3 newPos)
4377 { 4397 {
4378 if ((pos.X != OffsetPosition.X) || 4398 Vector3 oldPos = OffsetPosition;
4379 (pos.Y != OffsetPosition.Y) ||
4380 (pos.Z != OffsetPosition.Z))
4381 {
4382 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4383 4399
4400 if ((newPos.X != oldPos.X) ||
4401 (newPos.Y != oldPos.Y) ||
4402 (newPos.Z != oldPos.Z))
4403 {
4384 if (ParentGroup.RootPart.GetStatusSandbox()) 4404 if (ParentGroup.RootPart.GetStatusSandbox())
4385 { 4405 {
4386 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4406 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -4527,7 +4547,7 @@ namespace OpenSim.Region.Framework.Scenes
4527 // For now, we use the NINJA naming scheme for identifying joints. 4547 // For now, we use the NINJA naming scheme for identifying joints.
4528 // In the future, we can support other joint specification schemes such as a 4548 // In the future, we can support other joint specification schemes such as a
4529 // custom checkbox in the viewer GUI. 4549 // custom checkbox in the viewer GUI.
4530 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4550 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4531 { 4551 {
4532 return IsHingeJoint() || IsBallJoint(); 4552 return IsHingeJoint() || IsBallJoint();
4533 } 4553 }
@@ -4649,6 +4669,11 @@ namespace OpenSim.Region.Framework.Scenes
4649 } 4669 }
4650 } 4670 }
4651*/ 4671*/
4672 if (pa != null)
4673 {
4674 pa.SetMaterial(Material);
4675 DoPhysicsPropertyUpdate(UsePhysics, true);
4676 }
4652 } 4677 }
4653 else // it already has a physical representation 4678 else // it already has a physical representation
4654 { 4679 {
@@ -5021,6 +5046,14 @@ namespace OpenSim.Region.Framework.Scenes
5021 oldTex.DefaultTexture = fallbackOldFace; 5046 oldTex.DefaultTexture = fallbackOldFace;
5022 } 5047 }
5023 5048
5049 // Materials capable viewers can send a ObjectImage packet
5050 // when nothing in TE has changed. MaterialID should be updated
5051 // by the RenderMaterials CAP handler, so updating it here may cause a
5052 // race condtion. Therefore, if no non-materials TE fields have changed,
5053 // we should ignore any changes and not update Shape.TextureEntry
5054
5055 bool otherFieldsChanged = false;
5056
5024 for (int i = 0 ; i < GetNumberOfSides(); i++) 5057 for (int i = 0 ; i < GetNumberOfSides(); i++)
5025 { 5058 {
5026 5059
@@ -5047,18 +5080,36 @@ namespace OpenSim.Region.Framework.Scenes
5047 // Max change, skip the rest of testing 5080 // Max change, skip the rest of testing
5048 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5081 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
5049 break; 5082 break;
5083
5084 if (!otherFieldsChanged)
5085 {
5086 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
5087 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
5088 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
5089 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
5090 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
5091 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
5092 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
5093 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
5094 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
5095 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
5096 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5097 }
5050 } 5098 }
5051 5099
5052 m_shape.TextureEntry = newTex.GetBytes(); 5100 if (changeFlags != 0 || otherFieldsChanged)
5053 if (changeFlags != 0) 5101 {
5054 TriggerScriptChangedEvent(changeFlags); 5102 m_shape.TextureEntry = newTex.GetBytes();
5055 UpdateFlag = UpdateRequired.FULL; 5103 if (changeFlags != 0)
5056 ParentGroup.HasGroupChanged = true; 5104 TriggerScriptChangedEvent(changeFlags);
5105 UpdateFlag = UpdateRequired.FULL;
5106 ParentGroup.HasGroupChanged = true;
5057 5107
5058 //This is madness.. 5108 //This is madness..
5059 //ParentGroup.ScheduleGroupForFullUpdate(); 5109 //ParentGroup.ScheduleGroupForFullUpdate();
5060 //This is sparta 5110 //This is sparta
5061 ScheduleFullUpdate(); 5111 ScheduleFullUpdate();
5112 }
5062 } 5113 }
5063 5114
5064 5115
@@ -5246,6 +5297,64 @@ namespace OpenSim.Region.Framework.Scenes
5246 { 5297 {
5247 ParentGroup.AddScriptLPS(count); 5298 ParentGroup.AddScriptLPS(count);
5248 } 5299 }
5300
5301 /// <summary>
5302 /// Sets a prim's owner and permissions when it's rezzed.
5303 /// </summary>
5304 /// <param name="item">The inventory item from which the item was rezzed</param>
5305 /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
5306 /// <param name="scene">The scene the prim is being rezzed into</param>
5307 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
5308 {
5309 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
5310 {
5311 if (scene.Permissions.PropagatePermissions())
5312 {
5313 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
5314 {
5315 // Apply the item's permissions to the object
5316 //LogPermissions("Before applying item permissions");
5317 if (userInventory)
5318 {
5319 EveryoneMask = item.EveryOnePermissions;
5320 NextOwnerMask = item.NextPermissions;
5321 }
5322 else
5323 {
5324 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
5325 EveryoneMask = item.EveryOnePermissions;
5326 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
5327 NextOwnerMask = item.NextPermissions;
5328 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
5329 GroupMask = item.GroupPermissions;
5330 }
5331 //LogPermissions("After applying item permissions");
5332 }
5333 }
5334
5335 GroupMask = 0; // DO NOT propagate here
5336 }
5337
5338 if (OwnerID != item.Owner)
5339 {
5340 //LogPermissions("Before ApplyNextOwnerPermissions");
5341 ApplyNextOwnerPermissions();
5342 //LogPermissions("After ApplyNextOwnerPermissions");
5343
5344 LastOwnerID = OwnerID;
5345 OwnerID = item.Owner;
5346 Inventory.ChangeInventoryOwner(item.Owner);
5347 }
5348 }
5349
5350 /// <summary>
5351 /// Logs the prim's permissions. Useful when debugging permission problems.
5352 /// </summary>
5353 /// <param name="message"></param>
5354 private void LogPermissions(String message)
5355 {
5356 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
5357 }
5249 5358
5250 public void ApplyNextOwnerPermissions() 5359 public void ApplyNextOwnerPermissions()
5251 { 5360 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d04d87b..a6a963b 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,102 @@ 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
899 group.RootPart.AttachPoint = group.RootPart.Shape.State;
900 group.RootPart.AttachOffset = group.AbsolutePosition;
901 group.RootPart.AttachRotation = group.GroupRotation;
902 901
903 group.ResetIDs(); 902 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
904 903
905 SceneObjectPart rootPart = group.GetPart(group.UUID); 904 for (int i = 0; i < objlist.Count; i++)
906 905 {
907 // Since renaming the item in the inventory does not affect the name stored 906 SceneObjectGroup group = objlist[i];
908 // in the serialization, transfer the correct name from the inventory to the 907/*
909 // object itself before we rez. 908 group.RootPart.AttachPoint = group.RootPart.Shape.State;
910 rootPart.Name = item.Name; 909 group.RootPart.AttachedPos = group.AbsolutePosition;
911 rootPart.Description = item.Description; 910 group.RootPart.AttachRotation = group.GroupRotation;
911*/
912 group.ResetIDs();
913
914 SceneObjectPart rootPart = group.GetPart(group.UUID);
915
916 // Since renaming the item in the inventory does not affect the name stored
917 // in the serialization, transfer the correct name from the inventory to the
918 // object itself before we rez.
919 // Only do these for the first object if we are rezzing a coalescence.
920 // nahh dont mess with coalescence objects,
921 // the name in inventory can be change for inventory purpuses only
922 if (objlist.Count == 1)
923 {
924 rootPart.Name = item.Name;
925 rootPart.Description = item.Description;
926 }
927/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed
928 group.SetGroup(m_part.GroupID, null);
912 929
913 SceneObjectPart[] partList = group.Parts; 930 foreach (SceneObjectPart part in group.Parts)
931 {
932 // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :)
933 InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID);
934 dest.BasePermissions = item.BasePermissions;
935 dest.CurrentPermissions = item.CurrentPermissions;
936 dest.EveryOnePermissions = item.EveryonePermissions;
937 dest.GroupPermissions = item.GroupPermissions;
938 dest.NextPermissions = item.NextPermissions;
939 dest.Flags = item.Flags;
940
941 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
942 }
943*/
944// old code start
945 SceneObjectPart[] partList = group.Parts;
914 946
915 group.SetGroup(m_part.GroupID, null); 947 group.SetGroup(m_part.GroupID, null);
916 948
917 // TODO: Remove magic number badness 949 // TODO: Remove magic number badness
918 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 950 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
919 {
920 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
921 { 951 {
922 foreach (SceneObjectPart part in partList) 952 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
923 { 953 {
924 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 954 foreach (SceneObjectPart part in partList)
925 part.EveryoneMask = item.EveryonePermissions; 955 {
926 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) 956 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
927 part.NextOwnerMask = item.NextPermissions; 957 part.EveryoneMask = item.EveryonePermissions;
928 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 958 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
929 part.GroupMask = item.GroupPermissions; 959 part.NextOwnerMask = item.NextPermissions;
960 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
961 part.GroupMask = item.GroupPermissions;
962 }
963
964 group.ApplyNextOwnerPermissions();
930 } 965 }
931
932 group.ApplyNextOwnerPermissions();
933 } 966 }
934 }
935 967
936 foreach (SceneObjectPart part in partList) 968 foreach (SceneObjectPart part in partList)
937 {
938 // TODO: Remove magic number badness
939 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
940 { 969 {
941 part.LastOwnerID = part.OwnerID; 970 // TODO: Remove magic number badness
942 part.OwnerID = item.OwnerID; 971 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
943 part.Inventory.ChangeInventoryOwner(item.OwnerID); 972 {
973 part.LastOwnerID = part.OwnerID;
974 part.OwnerID = item.OwnerID;
975 part.Inventory.ChangeInventoryOwner(item.OwnerID);
976 }
977
978 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
979 part.EveryoneMask = item.EveryonePermissions;
980 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
981 part.NextOwnerMask = item.NextPermissions;
982 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
983 part.GroupMask = item.GroupPermissions;
944 } 984 }
945 985// old code end
946 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 986 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 } 987 }
953 988
954 rootPart.TrimPermissions(); 989 return true;
955
956 return group;
957 } 990 }
958 991
959 /// <summary> 992 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7004d23..8fae032 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,20 +75,59 @@ 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); 91 public bool isNPC { get; private set; }
92
93 private PresenceType m_presenceType;
94 public PresenceType PresenceType {
95 get {return m_presenceType;}
96 private set
97 {
98 m_presenceType = value;
99 isNPC = (m_presenceType == PresenceType.Npc);
100 }
101 }
102
103 private ScenePresenceStateMachine m_stateMachine;
104
105 /// <summary>
106 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
107 /// for more details.
108 /// </summary>
109 public ScenePresenceState LifecycleState
110 {
111 get
112 {
113 return m_stateMachine.GetState();
114 }
115
116 set
117 {
118 m_stateMachine.SetState(value);
119 }
120 }
88 121
89 public PresenceType PresenceType { get; private set; } 122 /// <summary>
123 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
124 /// the viewer fires these in quick succession.
125 /// </summary>
126 /// <remarks>
127 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
128 /// regulation done there.
129 /// </remarks>
130 private object m_completeMovementLock = new object();
90 131
91// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 132// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
92 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 133 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
@@ -109,8 +150,90 @@ namespace OpenSim.Region.Framework.Scenes
109 /// </summary> 150 /// </summary>
110 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 151 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f;
111 152
112 public UUID currentParcelUUID = UUID.Zero; 153 private UUID m_previusParcelUUID = UUID.Zero;
154 private UUID m_currentParcelUUID = UUID.Zero;
155 private bool m_previusParcelHide = false;
156 private bool m_currentParcelHide = false;
157 private object parcelLock = new Object();
158
159 public UUID currentParcelUUID
160 {
161 get { return m_currentParcelUUID; }
162 set
163 {
164 lock (parcelLock)
165 {
166 bool oldhide = m_currentParcelHide;
167 bool checksame = true;
168 if (value != m_currentParcelUUID)
169 {
170 m_previusParcelHide = m_currentParcelHide;
171 m_previusParcelUUID = m_currentParcelUUID;
172 checksame = false;
173 }
174 m_currentParcelUUID = value;
175 m_currentParcelHide = false;
176
177 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
178 if (land != null && !land.LandData.SeeAVs)
179 m_currentParcelHide = true;
180
181 if (m_previusParcelUUID != UUID.Zero || checksame)
182 ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
183 }
184 }
185 }
186
187 public void sitSOGmoved()
188 {
189 if (IsDeleted || !IsSatOnObject)
190 //what me? nahh
191 return;
192 if (IsInTransit)
193 return;
194
195 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
196 if (land == null)
197 return; //??
198 UUID parcelID = land.LandData.GlobalID;
199 if (m_currentParcelUUID != parcelID)
200 currentParcelUUID = parcelID;
201 }
202
203
204 public bool ParcelAllowThisAvatarSounds
205 {
206 get
207 {
208 try
209 {
210 lock (parcelLock)
211 {
212 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
213 if (land == null)
214 return true;
215 if (land.LandData.AnyAVSounds)
216 return true;
217 if (!land.LandData.GroupAVSounds)
218 return false;
219 return land.LandData.GroupID == ControllingClient.ActiveGroupId;
220 }
221 }
222 catch
223 {
224 return true;
225 }
226 }
227 }
113 228
229 public bool ParcelHideThisAvatar
230 {
231 get
232 {
233 return m_currentParcelHide;
234 }
235 }
236
114 /// <value> 237 /// <value>
115 /// The animator for this avatar 238 /// The animator for this avatar
116 /// </value> 239 /// </value>
@@ -142,6 +265,8 @@ namespace OpenSim.Region.Framework.Scenes
142 private Vector3 m_lastVelocity; 265 private Vector3 m_lastVelocity;
143 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 266 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
144 267
268 private bool m_followCamAuto = false;
269
145 270
146 private Vector3? m_forceToApply; 271 private Vector3? m_forceToApply;
147 private int m_userFlags; 272 private int m_userFlags;
@@ -200,7 +325,7 @@ namespace OpenSim.Region.Framework.Scenes
200 private float m_sitAvatarHeight = 2.0f; 325 private float m_sitAvatarHeight = 2.0f;
201 326
202 private Vector3 m_lastChildAgentUpdatePosition; 327 private Vector3 m_lastChildAgentUpdatePosition;
203 private Vector3 m_lastChildAgentUpdateCamPosition; 328// private Vector3 m_lastChildAgentUpdateCamPosition;
204 329
205 private const int LAND_VELOCITYMAG_MAX = 12; 330 private const int LAND_VELOCITYMAG_MAX = 12;
206 331
@@ -290,9 +415,37 @@ namespace OpenSim.Region.Framework.Scenes
290 /// </summary> 415 /// </summary>
291 private Vector3 posLastSignificantMove; 416 private Vector3 posLastSignificantMove;
292 417
293 // For teleports and crossings callbacks 418 #region For teleports and crossings callbacks
294 string m_callbackURI; 419
295 UUID m_originRegionID; 420 /// <summary>
421 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
422 /// </summary>
423 private string m_callbackURI;
424
425 /// <summary>
426 /// Records the region from which this presence originated, if not from login.
427 /// </summary>
428 /// <remarks>
429 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
430 /// CompleteMovement and made the previous child agent a root agent.
431 /// </remarks>
432 private UUID m_originRegionID;
433
434 /// <summary>
435 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
436 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
437 /// it is a value type.
438 /// </summary>
439 private object m_originRegionIDAccessLock = new object();
440
441 /// <summary>
442 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
443 /// teleport is reusing the connection.
444 /// </summary>
445 /// <remarks>May be refactored or move somewhere else soon.</remarks>
446 public bool DoNotCloseAfterTeleport { get; set; }
447
448 #endregion
296 449
297 /// <value> 450 /// <value>
298 /// Script engines present in the scene 451 /// Script engines present in the scene
@@ -309,15 +462,12 @@ namespace OpenSim.Region.Framework.Scenes
309 /// <summary> 462 /// <summary>
310 /// Record user movement inputs. 463 /// Record user movement inputs.
311 /// </summary> 464 /// </summary>
312 public byte MovementFlag { get; private set; } 465 public uint MovementFlag { get; private set; }
313
314 private bool m_updateflag;
315 466
316 public bool Updated 467 /// <summary>
317 { 468 /// Is the agent stop control flag currently active?
318 set { m_updateflag = value; } 469 /// </summary>
319 get { return m_updateflag; } 470 public bool AgentControlStopActive { get; private set; }
320 }
321 471
322 private bool m_invulnerable = true; 472 private bool m_invulnerable = true;
323 473
@@ -424,6 +574,7 @@ namespace OpenSim.Region.Framework.Scenes
424 } 574 }
425 } 575 }
426 576
577
427 public byte State { get; set; } 578 public byte State { get; set; }
428 579
429 private AgentManager.ControlFlags m_AgentControlFlags; 580 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -462,6 +613,7 @@ namespace OpenSim.Region.Framework.Scenes
462 } 613 }
463 else 614 else
464 { 615 {
616// 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. 617 // Obtain the correct position of a seated avatar.
466 // In addition to providing the correct position while 618 // In addition to providing the correct position while
467 // the avatar is seated, this value will also 619 // the avatar is seated, this value will also
@@ -475,17 +627,21 @@ namespace OpenSim.Region.Framework.Scenes
475 // in the sim unless the avatar is on a sit target. While 627 // in the sim unless the avatar is on a sit target. While
476 // on a sit target, m_pos will contain the desired offset 628 // on a sit target, m_pos will contain the desired offset
477 // without the parent rotation applied. 629 // without the parent rotation applied.
478 SceneObjectPart sitPart = ParentPart; 630 if (ParentPart != null)
479 631 {
480 if (sitPart != null) 632 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
481 return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 633 // if (sitPart != null)
634 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
635 if (rootPart != null)
636 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
637 }
482 } 638 }
483 639
484 return m_pos; 640 return m_pos;
485 } 641 }
486 set 642 set
487 { 643 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 644// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
489// Util.PrintCallStack(); 645// Util.PrintCallStack();
490 646
491 if (PhysicsActor != null) 647 if (PhysicsActor != null)
@@ -502,10 +658,7 @@ namespace OpenSim.Region.Framework.Scenes
502 658
503 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 659 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
504 if (ParentID == 0) 660 if (ParentID == 0)
505 {
506 m_pos = value; 661 m_pos = value;
507// ParentPosition = Vector3.Zero;
508 }
509 662
510 //m_log.DebugFormat( 663 //m_log.DebugFormat(
511 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 664 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -768,6 +921,14 @@ namespace OpenSim.Region.Framework.Scenes
768 set { m_speedModifier = value; } 921 set { m_speedModifier = value; }
769 } 922 }
770 923
924 /// <summary>
925 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
926 /// </summary>
927 /// <remarks>
928 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
929 /// </remarks>
930 private float AgentControlStopSlowWhilstMoving = 0.5f;
931
771 private bool m_forceFly; 932 private bool m_forceFly;
772 933
773 public bool ForceFly 934 public bool ForceFly
@@ -795,7 +956,7 @@ namespace OpenSim.Region.Framework.Scenes
795 956
796 public ScenePresence( 957 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 958 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 959 {
799 AttachmentsSyncLock = new Object(); 960 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 961 AllowMovement = true;
801 IsChildAgent = true; 962 IsChildAgent = true;
@@ -824,7 +985,7 @@ namespace OpenSim.Region.Framework.Scenes
824 985
825 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 986 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
826 if (gm != null) 987 if (gm != null)
827 Grouptitle = gm.GetGroupTitle(m_uuid); 988 Grouptitle = gm.GetGroupTitle(m_uuid);
828 989
829 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 990 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
830 991
@@ -841,6 +1002,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 1002 SetDirectionVectors();
842 1003
843 Appearance = appearance; 1004 Appearance = appearance;
1005
1006 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 1007 }
845 1008
846 private void RegionHeartbeatEnd(Scene scene) 1009 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +1037,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 1037 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 1038 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 1039 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
1040 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 1041 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 1042 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1043 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -927,6 +1091,7 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <summary> 1091 /// <summary>
928 /// Turns a child agent into a root agent. 1092 /// Turns a child agent into a root agent.
929 /// </summary> 1093 /// </summary>
1094 /// <remarks>
930 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 1095 /// 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. 1096 /// 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, 1097 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -934,53 +1099,61 @@ namespace OpenSim.Region.Framework.Scenes
934 /// 1099 ///
935 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1100 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
936 /// delays that crossing. 1101 /// delays that crossing.
937 /// </summary> 1102 /// </remarks>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 1103
939 {
940 m_log.DebugFormat(
941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName);
943 1104
944 if (ParentUUID != UUID.Zero) 1105 // only in use as part of completemovement
1106 // other uses need fix
1107 private bool MakeRootAgent(Vector3 pos, bool isFlying)
1108 {
1109 lock (m_completeMovementLock)
945 { 1110 {
946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1111 if (!IsChildAgent)
947 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1112 return false;
948 if (part == null) 1113
1114 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1115
1116 // m_log.InfoFormat(
1117 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1118 // Name, m_scene.RegionInfo.RegionName);
1119
1120 if (ParentUUID != UUID.Zero)
949 { 1121 {
950 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1122 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1123 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1124 if (part == null)
1125 {
1126 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1127 }
1128 else
1129 {
1130 part.ParentGroup.AddAvatar(UUID);
1131 if (part.SitTargetPosition != Vector3.Zero)
1132 part.SitTargetAvatar = UUID;
1133 ParentID = part.LocalId;
1134 ParentPart = part;
1135 m_pos = PrevSitOffset;
1136 pos = part.GetWorldPosition();
1137 }
1138 ParentUUID = UUID.Zero;
951 } 1139 }
952 else 1140 else
953 { 1141 {
954 part.ParentGroup.AddAvatar(UUID); 1142 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 } 1143 }
964 ParentUUID = UUID.Zero;
965
966 IsChildAgent = false;
967 1144
968// Animator.TrySetMovementAnimation("SIT");
969 }
970 else
971 {
972 IsChildAgent = false; 1145 IsChildAgent = false;
973 IsLoggingIn = false;
974 } 1146 }
975 1147
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1148 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
977 1149 // set and prevent the close of the connection on a subsequent re-teleport.
978 IsChildAgent = false; 1150 // Should not be needed if we are not trying to tell this region to close
1151// DoNotCloseAfterTeleport = false;
979 1152
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1153 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1154 if (gm != null)
982 Grouptitle = gm.GetGroupTitle(m_uuid); 1155 Grouptitle = gm.GetGroupTitle(m_uuid);
983 1156
984 RegionHandle = m_scene.RegionInfo.RegionHandle; 1157 RegionHandle = m_scene.RegionInfo.RegionHandle;
985 1158
986 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1159 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
@@ -993,6 +1166,7 @@ namespace OpenSim.Region.Framework.Scenes
993 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status 1166 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
994 try 1167 try
995 { 1168 {
1169
996 if (gm != null) 1170 if (gm != null)
997 { 1171 {
998 groupUUID = ControllingClient.ActiveGroupId; 1172 groupUUID = ControllingClient.ActiveGroupId;
@@ -1017,7 +1191,7 @@ namespace OpenSim.Region.Framework.Scenes
1017 // Moved this from SendInitialData to ensure that Appearance is initialized 1191 // Moved this from SendInitialData to ensure that Appearance is initialized
1018 // before the inventory is processed in MakeRootAgent. This fixes a race condition 1192 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1019 // related to the handling of attachments 1193 // related to the handling of attachments
1020 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); 1194
1021 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1195 if (m_scene.TestBorderCross(pos, Cardinals.E))
1022 { 1196 {
1023 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1197 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
@@ -1096,6 +1270,7 @@ namespace OpenSim.Region.Framework.Scenes
1096 // and it has already rezzed the attachments and started their scripts. 1270 // and it has already rezzed the attachments and started their scripts.
1097 // We do the following only for non-login agents, because their scripts 1271 // We do the following only for non-login agents, because their scripts
1098 // haven't started yet. 1272 // haven't started yet.
1273/* moved down
1099 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0) 1274 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1100 { 1275 {
1101 // Viewers which have a current outfit folder will actually rez their own attachments. However, 1276 // Viewers which have a current outfit folder will actually rez their own attachments. However,
@@ -1111,31 +1286,50 @@ namespace OpenSim.Region.Framework.Scenes
1111 }); 1286 });
1112 } 1287 }
1113 else 1288 else
1289
1114 { 1290 {
1115 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT 1291 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1116 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently 1292 // 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 1293 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data. 1294 // not transporting the required data.
1119 lock (m_attachments) 1295 //
1296 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1297 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1298 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1299 // not transporting the required data.
1300 //
1301 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1302 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1303 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1304 //
1305 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1306 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1307 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1308 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1309 //
1310 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1311 // be locked, allowing race conditions if other code changes the attachments list.
1312
1313 List<SceneObjectGroup> attachments = GetAttachments();
1314
1315 if (attachments.Count > 0)
1120 { 1316 {
1121 if (HasAttachments()) 1317 m_log.DebugFormat(
1122 { 1318 "[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 1319
1126 // Resume scripts 1320 // Resume scripts this possible should also be moved down after sending the avatar to viewer ?
1127 Util.FireAndForget(delegate(object x) { 1321 foreach (SceneObjectGroup sog in attachments)
1128 foreach (SceneObjectGroup sog in m_attachments) 1322 {
1129 { 1323// sending attachments before the avatar ?
1130 sog.ScheduleGroupForFullUpdate(); 1324// moved to completemovement where it already was
1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1325// sog.ScheduleGroupForFullUpdate();
1132 sog.ResumeScripts(); 1326 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1133 } 1327 sog.ResumeScripts();
1134 });
1135 } 1328 }
1136 } 1329 }
1137 } 1330 }
1138 1331*/
1332/*
1139 SendAvatarDataToAllAgents(); 1333 SendAvatarDataToAllAgents();
1140 1334
1141 // send the animations of the other presences to me 1335 // send the animations of the other presences to me
@@ -1144,6 +1338,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 if (presence != this) 1338 if (presence != this)
1145 presence.Animator.SendAnimPackToClient(ControllingClient); 1339 presence.Animator.SendAnimPackToClient(ControllingClient);
1146 }); 1340 });
1341*/
1147 1342
1148 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1343 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1149 // stall on the border crossing since the existing child agent will still have the last movement 1344 // stall on the border crossing since the existing child agent will still have the last movement
@@ -1153,7 +1348,7 @@ namespace OpenSim.Region.Framework.Scenes
1153 1348
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1349 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1155 1350
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1351 return true;
1157 } 1352 }
1158 1353
1159 public int GetStateSource() 1354 public int GetStateSource()
@@ -1185,6 +1380,11 @@ namespace OpenSim.Region.Framework.Scenes
1185 1380
1186 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1381 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
1187 1382
1383 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1384 // from the source simulator has completed on a V2 teleport.
1385 lock (m_originRegionIDAccessLock)
1386 m_originRegionID = UUID.Zero;
1387
1188 // Reset these so that teleporting in and walking out isn't seen 1388 // Reset these so that teleporting in and walking out isn't seen
1189 // as teleporting back 1389 // as teleporting back
1190 TeleportFlags = TeleportFlags.Default; 1390 TeleportFlags = TeleportFlags.Default;
@@ -1306,7 +1506,29 @@ namespace OpenSim.Region.Framework.Scenes
1306 1506
1307 public void StopFlying() 1507 public void StopFlying()
1308 { 1508 {
1309 ControllingClient.StopFlying(this); 1509 if (IsInTransit)
1510 return;
1511
1512 Vector3 pos = AbsolutePosition;
1513 if (Appearance.AvatarHeight != 127.0f)
1514 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1515 else
1516 pos += new Vector3(0f, 0f, (1.56f / 6f));
1517
1518 AbsolutePosition = pos;
1519
1520 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1521 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1522 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1523 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1524
1525 // why are we still testing for this really old height value default???
1526 if (Appearance.AvatarHeight != 127.0f)
1527 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1528 else
1529 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1530
1531 SendAgentTerseUpdate(this);
1310 } 1532 }
1311 1533
1312 /// <summary> 1534 /// <summary>
@@ -1480,6 +1702,37 @@ namespace OpenSim.Region.Framework.Scenes
1480 1702
1481 } 1703 }
1482 1704
1705 private bool WaitForUpdateAgent(IClientAPI client)
1706 {
1707 // Before the source region executes UpdateAgent
1708 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1709 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1710 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1711 int count = 50;
1712 UUID originID;
1713
1714 lock (m_originRegionIDAccessLock)
1715 originID = m_originRegionID;
1716
1717 while (originID.Equals(UUID.Zero) && count-- > 0)
1718 {
1719 lock (m_originRegionIDAccessLock)
1720 originID = m_originRegionID;
1721
1722 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1723 Thread.Sleep(200);
1724 }
1725
1726 if (originID.Equals(UUID.Zero))
1727 {
1728 // Movement into region will fail
1729 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1730 return false;
1731 }
1732
1733 return true;
1734 }
1735
1483 /// <summary> 1736 /// <summary>
1484 /// Complete Avatar's movement into the region. 1737 /// Complete Avatar's movement into the region.
1485 /// </summary> 1738 /// </summary>
@@ -1493,86 +1746,186 @@ namespace OpenSim.Region.Framework.Scenes
1493 { 1746 {
1494// DateTime startTime = DateTime.Now; 1747// DateTime startTime = DateTime.Now;
1495 1748
1496 m_log.DebugFormat( 1749 m_log.InfoFormat(
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1750 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1751 client.Name, Scene.Name, AbsolutePosition);
1752
1753 m_inTransit = true;
1754 bool newhide = false;
1755 try
1756 {
1757 // Make sure it's not a login agent. We don't want to wait for updates during login
1758 if (!isNPC && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1759 {
1760 // Let's wait until UpdateAgent (called by departing region) is done
1761 if (!WaitForUpdateAgent(client))
1762 // The sending region never sent the UpdateAgent data, we have to refuse
1763 return;
1764 }
1499 1765
1500 Vector3 look = Velocity; 1766 Vector3 look = Velocity;
1501 1767
1502 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1768 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
1503 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) 1769 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1504 { 1770 {
1505 look = new Vector3(0.99f, 0.042f, 0); 1771 look = new Vector3(0.99f, 0.042f, 0);
1506 } 1772 }
1507 1773
1508 // Prevent teleporting to an underground location 1774 // Prevent teleporting to an underground location
1509 // (may crash client otherwise) 1775 // (may crash client otherwise)
1510 // 1776 //
1511 Vector3 pos = AbsolutePosition; 1777 Vector3 pos = AbsolutePosition;
1512 float ground = m_scene.GetGroundHeight(pos.X, pos.Y); 1778 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1513 if (pos.Z < ground + 1.5f) 1779 if (pos.Z < ground + 1.5f)
1514 { 1780 {
1515 pos.Z = ground + 1.5f; 1781 pos.Z = ground + 1.5f;
1516 AbsolutePosition = pos; 1782 AbsolutePosition = pos;
1517 } 1783 }
1518 1784
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1785 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1520 MakeRootAgent(AbsolutePosition, flying); 1786 if (!MakeRootAgent(AbsolutePosition, flying))
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1787 {
1788 m_log.DebugFormat(
1789 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1790 Name, Scene.Name);
1522 1791
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1792 return;
1793 }
1524 1794
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1795 // Tell the client that we're totally ready
1526 { 1796 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1527 // 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
1529 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1530 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1531 // region as the current region, meaning that a close sent before then will fail the teleport.
1532// System.Threading.Thread.Sleep(2000);
1533 1797
1534 m_log.DebugFormat( 1798 // Remember in HandleUseCircuitCode, we delayed this to here
1535 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1799// this prims etc, moved down
1536 client.Name, client.AgentId, m_callbackURI); 1800// if (m_teleportFlags > 0)
1801// SendInitialDataToMe();
1537 1802
1538 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1803 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1539 m_callbackURI = null;
1540 }
1541// else
1542// {
1543// m_log.DebugFormat(
1544// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1545// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1546// }
1547 1804
1548 ValidateAndSendAppearanceAndAgentData(); 1805 if (!string.IsNullOrEmpty(m_callbackURI))
1806 {
1807 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1808 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1809 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1810 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1811 // region as the current region, meaning that a close sent before then will fail the teleport.
1812 // System.Threading.Thread.Sleep(2000);
1549 1813
1550 // Create child agents in neighbouring regions 1814 m_log.DebugFormat(
1551 if (openChildAgents && !IsChildAgent) 1815 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1552 { 1816 client.Name, client.AgentId, m_callbackURI);
1553 1817
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1818 UUID originID;
1555 if (m_agentTransfer != null)
1556 m_agentTransfer.EnableChildAgents(this);
1557 1819
1558 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1820 lock (m_originRegionIDAccessLock)
1559 if (friendsModule != null) 1821 originID = m_originRegionID;
1560 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1561 1822
1562 } 1823 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1824 m_callbackURI = null;
1825 }
1826 // else
1827 // {
1828 // m_log.DebugFormat(
1829 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1830 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1831 // }
1832
1833 m_previusParcelHide = false;
1834 m_previusParcelUUID = UUID.Zero;
1835 m_currentParcelHide = false;
1836 m_currentParcelUUID = UUID.Zero;
1837
1838 // send initial land overlay and parcel
1839 ILandChannel landch = m_scene.LandChannel;
1840 if (landch != null)
1841 {
1842 landch.sendClientInitialLandInfo(client);
1843 if (!IsChildAgent)
1844 {
1845 newhide = m_currentParcelHide;
1846 m_currentParcelHide = false;
1847 }
1848 }
1563 1849
1564 // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region 1850 // send agentData to all clients including us (?)
1565 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. 1851 // get appearance
1566 // This may be due to viewer code or it may be something we're not doing properly simulator side. 1852 // if in cache sent it to all clients
1567 lock (m_attachments) 1853 // send what we have to us, even if not in cache ( bad? )
1854 ValidateAndSendAppearanceAndAgentData();
1855
1856 // attachments
1857 if (isNPC || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1858 {
1859 if (Scene.AttachmentsModule != null)
1860// Util.FireAndForget(
1861// o =>
1862// {
1863 Scene.AttachmentsModule.RezAttachments(this);
1864// });
1865 }
1866 else
1867 {
1868 List<SceneObjectGroup> attachments = GetAttachments();
1869
1870 if (attachments.Count > 0)
1871 {
1872 m_log.DebugFormat(
1873 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1874
1875 // Resume scripts this possible should also be moved down after sending the avatar to viewer ?
1876 foreach (SceneObjectGroup sog in attachments)
1877 {
1878 sog.ScheduleGroupForFullUpdate();
1879 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1880 sog.ResumeScripts();
1881 }
1882 }
1883 }
1884 // m_log.DebugFormat(
1885 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1886 // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1887
1888 // Create child agents in neighbouring regions
1889 if (openChildAgents && !IsChildAgent)
1890 {
1891 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1892 if (m_agentTransfer != null)
1893 m_agentTransfer.EnableChildAgents(this);
1894 }
1895
1896 // send the rest of the world
1897 if (m_teleportFlags > 0 && !isNPC)
1898 SendInitialDataToMe();
1899
1900 if (!IsChildAgent)
1901 {
1902// moved from makeroot missing in sendInitialDataToMe
1903// its already there
1904/*
1905 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1906 {
1907 if (presence != this)
1908 presence.Animator.SendAnimPackToClient(ControllingClient);
1909 });
1910*/
1911 if (openChildAgents)
1912 {
1913 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1914 if (friendsModule != null)
1915 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1916 }
1917 }
1918 }
1919 finally
1568 { 1920 {
1569 foreach (SceneObjectGroup sog in m_attachments) 1921 m_inTransit = false;
1570 sog.ScheduleGroupForFullUpdate(); 1922 }
1923 // if hide force a check
1924 if (!IsChildAgent && newhide)
1925 {
1926 ParcelLoginCheck(m_currentParcelUUID);
1927 m_currentParcelHide = newhide;
1571 } 1928 }
1572
1573// m_log.DebugFormat(
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1576 } 1929 }
1577 1930
1578 /// <summary> 1931 /// <summary>
@@ -1653,9 +2006,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 2006 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 2007 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 2008 {
1656// m_log.DebugFormat( 2009 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 2010 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 2011 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 2012
1660 if (IsChildAgent) 2013 if (IsChildAgent)
1661 { 2014 {
@@ -1663,9 +2016,8 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 2016 return;
1664 } 2017 }
1665 2018
1666 ++m_movementUpdateCount; 2019 if (IsInTransit)
1667 if (m_movementUpdateCount < 1) 2020 return;
1668 m_movementUpdateCount = 1;
1669 2021
1670 #region Sanity Checking 2022 #region Sanity Checking
1671 2023
@@ -1697,21 +2049,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 2049
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 2050 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 2051
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 2052 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 2053 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 2054 // changes, then start using the agent's drawdistance rather than the
@@ -1733,6 +2070,7 @@ namespace OpenSim.Region.Framework.Scenes
1733// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2070// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1734// m_updateCount = UPDATE_COUNT; 2071// m_updateCount = UPDATE_COUNT;
1735 2072
2073
1736 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2074 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1737 { 2075 {
1738 StandUp(); 2076 StandUp();
@@ -1783,9 +2121,16 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 2121 // Here's where you get them.
1784 m_AgentControlFlags = flags; 2122 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 2123 m_headrotation = agentData.HeadRotation;
2124 byte oldState = State;
1786 State = agentData.State; 2125 State = agentData.State;
1787 2126
2127 // We need to send this back to the client in order to stop the edit beams
2128 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2129 SendAgentTerseUpdate(this);
2130
1788 PhysicsActor actor = PhysicsActor; 2131 PhysicsActor actor = PhysicsActor;
2132
2133 // This will be the case if the agent is sitting on the groudn or on an object.
1789 if (actor == null) 2134 if (actor == null)
1790 { 2135 {
1791 SendControlsToScripts(flagsForScripts); 2136 SendControlsToScripts(flagsForScripts);
@@ -1794,12 +2139,11 @@ namespace OpenSim.Region.Framework.Scenes
1794 2139
1795 if (AllowMovement && !SitGround) 2140 if (AllowMovement && !SitGround)
1796 { 2141 {
1797 Quaternion bodyRotation = agentData.BodyRotation; 2142// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1798 bool update_rotation = false; 2143 bool update_rotation = false;
1799 2144 if (agentData.BodyRotation != Rotation)
1800 if (bodyRotation != Rotation)
1801 { 2145 {
1802 Rotation = bodyRotation; 2146 Rotation = agentData.BodyRotation;
1803 update_rotation = true; 2147 update_rotation = true;
1804 } 2148 }
1805 2149
@@ -1845,10 +2189,7 @@ namespace OpenSim.Region.Framework.Scenes
1845 else 2189 else
1846 dirVectors = Dir_Vectors; 2190 dirVectors = Dir_Vectors;
1847 2191
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. 2192 // 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) 2193 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1853 { 2194 {
1854 if (((uint)flags & (uint)DCF) != 0) 2195 if (((uint)flags & (uint)DCF) != 0)
@@ -1865,29 +2206,19 @@ namespace OpenSim.Region.Framework.Scenes
1865 // Why did I get this? 2206 // Why did I get this?
1866 } 2207 }
1867 2208
1868 if ((MovementFlag & (byte)(uint)DCF) == 0) 2209 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive)
1869 { 2210 {
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); 2211 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1877 MovementFlag += (byte)(uint)DCF; 2212 MovementFlag += (uint)DCF;
1878 update_movementflag = true; 2213 update_movementflag = true;
1879 } 2214 }
1880 } 2215 }
1881 else 2216 else
1882 { 2217 {
1883 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2218 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 { 2219 {
1889 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2220 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1890 MovementFlag -= ((byte)(uint)DCF); 2221 MovementFlag -= (uint)DCF;
1891 update_movementflag = true; 2222 update_movementflag = true;
1892 2223
1893 /* 2224 /*
@@ -1907,6 +2238,13 @@ namespace OpenSim.Region.Framework.Scenes
1907 i++; 2238 i++;
1908 } 2239 }
1909 2240
2241 // Detect AGENT_CONTROL_STOP state changes
2242 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2243 {
2244 AgentControlStopActive = !AgentControlStopActive;
2245 update_movementflag = true;
2246 }
2247
1910 if (MovingToTarget) 2248 if (MovingToTarget)
1911 { 2249 {
1912 // If the user has pressed a key then we want to cancel any move to target. 2250 // If the user has pressed a key then we want to cancel any move to target.
@@ -1932,53 +2270,79 @@ namespace OpenSim.Region.Framework.Scenes
1932 // Only do this if we're flying 2270 // Only do this if we're flying
1933 if (Flying && !ForceFly) 2271 if (Flying && !ForceFly)
1934 { 2272 {
1935 // Landing detection code 2273 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1936 2274 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 { 2275 {
1953 ApplyFlyingRoll( 2276 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 } 2277 }
1958 else 2278 else
1959 { 2279 {
1960 if (m_AngularVelocity.Z != 0) 2280 // Landing detection code
1961 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1962 }
1963 2281
1964 if (Flying && IsColliding && controlland) 2282 // Are the landing controls requirements filled?
1965 { 2283 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1966 // nesting this check because LengthSquared() is expensive and we don't 2284 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1967 // want to do it every step when flying. 2285
1968 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2286 //m_log.Debug("[CONTROL]: " +flags);
1969 StopFlying(); 2287 // Applies a satisfying roll effect to the avatar when flying.
2288 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2289 {
2290 ApplyFlyingRoll(
2291 FLY_ROLL_RADIANS_PER_UPDATE,
2292 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2293 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2294 }
2295 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2296 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2297 {
2298 ApplyFlyingRoll(
2299 -FLY_ROLL_RADIANS_PER_UPDATE,
2300 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2301 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2302 }
2303 else
2304 {
2305 if (m_AngularVelocity.Z != 0)
2306 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2307 }
2308
2309 if (Flying && IsColliding && controlland)
2310 {
2311 // nesting this check because LengthSquared() is expensive and we don't
2312 // want to do it every step when flying.
2313 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2314 StopFlying();
2315 }
1970 } 2316 }
1971 } 2317 }
1972 2318
2319// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2320
1973 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2321 // 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 2322 // which occurs later in the main scene loop
1975 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2323 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2324 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2325 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2326 // avatar location in place).
2327 if (update_movementflag
2328 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1976 { 2329 {
1977// m_log.DebugFormat( 2330// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
1978// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 2331// {
1979// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 2332// m_log.DebugFormat(
2333// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2334// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2335// update_movementflag, MovementFlag, update_rotation);
2336
2337 float speedModifier;
1980 2338
1981 AddNewMovement(agent_control_v3); 2339 if (AgentControlStopActive)
2340 speedModifier = AgentControlStopSlowWhilstMoving;
2341 else
2342 speedModifier = 1;
2343
2344 AddNewMovement(agent_control_v3, speedModifier);
2345// }
1982 } 2346 }
1983// else 2347// else
1984// { 2348// {
@@ -1991,15 +2355,86 @@ namespace OpenSim.Region.Framework.Scenes
1991// } 2355// }
1992 2356
1993 if (update_movementflag && ParentID == 0) 2357 if (update_movementflag && ParentID == 0)
2358 {
2359// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1994 Animator.UpdateMovementAnimations(); 2360 Animator.UpdateMovementAnimations();
2361 }
1995 2362
1996 SendControlsToScripts(flagsForScripts); 2363 SendControlsToScripts(flagsForScripts);
1997 } 2364 }
1998 2365
2366 // We need to send this back to the client in order to see the edit beams
2367 if ((State & (uint)AgentState.Editing) != 0)
2368 SendAgentTerseUpdate(this);
2369
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2370 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2371 }
2002 2372
2373
2374 /// <summary>
2375 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2376 /// </summary>
2377 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2378 {
2379 //m_log.DebugFormat(
2380 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2381 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2382
2383 if (IsChildAgent)
2384 {
2385 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2386 return;
2387 }
2388
2389 ++m_movementUpdateCount;
2390 if (m_movementUpdateCount < 1)
2391 m_movementUpdateCount = 1;
2392
2393// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2394
2395 // Camera location in world. We'll need to raytrace
2396 // from this location from time to time.
2397 CameraPosition = agentData.CameraCenter;
2398 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2399 {
2400 ReprioritizeUpdates();
2401 m_lastCameraPosition = CameraPosition;
2402 }
2403
2404 // Use these three vectors to figure out what the agent is looking at
2405 // Convert it to a Matrix and/or Quaternion
2406 CameraAtAxis = agentData.CameraAtAxis;
2407 CameraLeftAxis = agentData.CameraLeftAxis;
2408 CameraUpAxis = agentData.CameraUpAxis;
2409
2410 // The Agent's Draw distance setting
2411 // When we get to the point of re-computing neighbors everytime this
2412 // changes, then start using the agent's drawdistance rather than the
2413 // region's draw distance.
2414 // DrawDistance = agentData.Far;
2415 DrawDistance = Scene.DefaultDrawDistance;
2416
2417 // Check if Client has camera in 'follow cam' or 'build' mode.
2418 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2419
2420 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2421 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2422
2423
2424 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2425 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2426 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2427 {
2428 if (m_followCamAuto)
2429 {
2430 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2431 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2432 }
2433 }
2434
2435 TriggerScenePresenceUpdated();
2436 }
2437
2003 /// <summary> 2438 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2439 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2440 /// </summary>
@@ -2185,6 +2620,8 @@ namespace OpenSim.Region.Framework.Scenes
2185 targetScene = m_scene; 2620 targetScene = m_scene;
2186 2621
2187 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2622 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
2623 // dont try to land underground
2624 terrainHeight += Appearance.AvatarHeight / 2;
2188 pos.Z = Math.Max(terrainHeight, pos.Z); 2625 pos.Z = Math.Max(terrainHeight, pos.Z);
2189 2626
2190 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2627 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2196,10 +2633,11 @@ namespace OpenSim.Region.Framework.Scenes
2196// m_log.DebugFormat( 2633// m_log.DebugFormat(
2197// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2634// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2198// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2635// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2636
2199 2637
2200 if (noFly) 2638 if (noFly)
2201 Flying = false; 2639 Flying = false;
2202 else if (pos.Z > terrainHeight) 2640 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2203 Flying = true; 2641 Flying = true;
2204 2642
2205 LandAtTarget = landAtTarget; 2643 LandAtTarget = landAtTarget;
@@ -2252,17 +2690,13 @@ namespace OpenSim.Region.Framework.Scenes
2252 { 2690 {
2253// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2691// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2254 2692
2693 bool satOnObject = IsSatOnObject;
2694 SceneObjectPart part = ParentPart;
2255 SitGround = false; 2695 SitGround = false;
2256 2696
2257/* move this down so avatar gets physical in the new position and not where it is siting 2697 if (satOnObject)
2258 if (PhysicsActor == null)
2259 AddToPhysicalScene(false);
2260 */
2261
2262 if (ParentID != 0)
2263 { 2698 {
2264 PrevSitOffset = m_pos; // Save sit offset 2699 PrevSitOffset = m_pos; // Save sit offset
2265 SceneObjectPart part = ParentPart;
2266 UnRegisterSeatControls(part.ParentGroup.UUID); 2700 UnRegisterSeatControls(part.ParentGroup.UUID);
2267 2701
2268 TaskInventoryDictionary taskIDict = part.TaskInventory; 2702 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2281,34 +2715,86 @@ namespace OpenSim.Region.Framework.Scenes
2281 } 2715 }
2282 2716
2283 part.ParentGroup.DeleteAvatar(UUID); 2717 part.ParentGroup.DeleteAvatar(UUID);
2284// ParentPosition = part.GetWorldPosition();
2285 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2286 2718
2287// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2719 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2288// ParentPosition = Vector3.Zero; 2720 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2289 m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2721 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2290 if (part.SitTargetAvatar == UUID)
2291 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2292 2722
2293 ParentID = 0; 2723 ParentID = 0;
2294 ParentPart = null; 2724 ParentPart = null;
2295 2725
2296 if (PhysicsActor == null)
2297 AddToPhysicalScene(false);
2298 2726
2299 SendAvatarDataToAllAgents(); 2727 if (part.SitTargetAvatar == UUID)
2728 standRotation = standRotation * part.SitTargetOrientation;
2729 else
2730 standRotation = standRotation * m_bodyRot;
2731
2732 m_bodyRot = standRotation;
2733
2734 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2735
2736 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2737 if (t > 0)
2738 {
2739 t = 1.0f / (float)Math.Sqrt(t);
2740 standRotationZ.W *= t;
2741 standRotationZ.Z *= t;
2742 }
2743 else
2744 {
2745 standRotationZ.W = 1.0f;
2746 standRotationZ.Z = 0f;
2747 }
2748
2749 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2750
2751 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2752
2753// m_log.DebugFormat(
2754// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2755// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2756
2757 standPos.X = Util.Clamp<float>(standPos.X, 0.5f, (float)Constants.RegionSize - 0.5f);
2758 standPos.Y = Util.Clamp<float>(standPos.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
2759 m_pos = standPos;
2760 }
2761
2762 // We need to wait until we have calculated proper stand positions before sitting up the physical
2763 // avatar to avoid race conditions.
2764 if (PhysicsActor == null)
2765 AddToPhysicalScene(false);
2766
2767 if (satOnObject)
2768 {
2769// SendAvatarDataToAllAgents();
2300 m_requestedSitTargetID = 0; 2770 m_requestedSitTargetID = 0;
2301 2771
2302 part.RemoveSittingAvatar(UUID); 2772 part.RemoveSittingAvatar(UUID);
2303 2773
2304 if (part != null) 2774 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2306 } 2775 }
2307 2776
2308 else if (PhysicsActor == null) 2777 else if (PhysicsActor == null)
2309 AddToPhysicalScene(false); 2778 AddToPhysicalScene(false);
2310 2779
2311 Animator.TrySetMovementAnimation("STAND"); 2780 Animator.TrySetMovementAnimation("STAND");
2781
2782 if (satOnObject)
2783 {
2784 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X,AbsolutePosition.Y);
2785 if (land != null)
2786 {
2787 UUID parcelID = land.LandData.GlobalID;
2788 if (m_currentParcelUUID != parcelID)
2789 currentParcelUUID = parcelID;
2790 else
2791 SendAvatarDataToAllAgents();
2792 }
2793 else
2794 SendAvatarDataToAllAgents();
2795 }
2796
2797 TriggerScenePresenceUpdated();
2312 } 2798 }
2313 2799
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2800 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2355,20 +2841,17 @@ namespace OpenSim.Region.Framework.Scenes
2355 if (part == null) 2841 if (part == null)
2356 return; 2842 return;
2357 2843
2844
2358 if (PhysicsActor != null) 2845 if (PhysicsActor != null)
2359 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2846 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2360 2847
2361 bool canSit = false; 2848 bool canSit = false;
2362 Vector3 pos = part.AbsolutePosition + offset;
2363 2849
2364 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2850 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2365 { 2851 {
2366// m_log.DebugFormat(
2367// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2368// Name, part.Name, part.LocalId);
2369
2370 offset = part.SitTargetPosition; 2852 offset = part.SitTargetPosition;
2371 sitOrientation = part.SitTargetOrientation; 2853 sitOrientation = part.SitTargetOrientation;
2854
2372 canSit = true; 2855 canSit = true;
2373 } 2856 }
2374 else 2857 else
@@ -2376,9 +2859,10 @@ namespace OpenSim.Region.Framework.Scenes
2376 if (PhysicsSit(part,offset)) // physics engine 2859 if (PhysicsSit(part,offset)) // physics engine
2377 return; 2860 return;
2378 2861
2862 Vector3 pos = part.AbsolutePosition + offset;
2863
2379 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2864 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2380 { 2865 {
2381
2382 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2866 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2383 canSit = true; 2867 canSit = true;
2384 } 2868 }
@@ -2404,10 +2888,31 @@ namespace OpenSim.Region.Framework.Scenes
2404 cameraEyeOffset = part.GetCameraEyeOffset(); 2888 cameraEyeOffset = part.GetCameraEyeOffset();
2405 forceMouselook = part.GetForceMouselook(); 2889 forceMouselook = part.GetForceMouselook();
2406 2890
2891 if (!part.IsRoot)
2892 {
2893 sitOrientation = part.RotationOffset * sitOrientation;
2894 offset = offset * part.RotationOffset;
2895 offset += part.OffsetPosition;
2896
2897 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2898 {
2899 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
2900 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2901 }
2902 else
2903 {
2904 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2905 cameraAtOffset += part.OffsetPosition;
2906 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
2907 cameraEyeOffset += part.OffsetPosition;
2908 }
2909 }
2910
2911
2407 ControllingClient.SendSitResponse( 2912 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2913 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2914
2410 m_requestedSitTargetUUID = targetID; 2915 m_requestedSitTargetUUID = part.UUID;
2411 2916
2412 HandleAgentSit(ControllingClient, UUID); 2917 HandleAgentSit(ControllingClient, UUID);
2413 2918
@@ -2435,7 +2940,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2940 if (part != null)
2436 { 2941 {
2437 m_requestedSitTargetID = part.LocalId; 2942 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2943 m_requestedSitTargetUUID = part.UUID;
2439 2944
2440 } 2945 }
2441 else 2946 else
@@ -2529,14 +3034,35 @@ namespace OpenSim.Region.Framework.Scenes
2529 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3034 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2530 bool forceMouselook = part.GetForceMouselook(); 3035 bool forceMouselook = part.GetForceMouselook();
2531 3036
2532 ControllingClient.SendSitResponse( 3037 m_bodyRot = Orientation;
2533 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3038
3039 if (!part.IsRoot)
3040 {
3041 Orientation = part.RotationOffset * Orientation;
3042 offset = offset * part.RotationOffset;
3043 offset += part.OffsetPosition;
3044
3045 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3046 {
3047 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3048 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3049 }
3050 else
3051 {
3052 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3053 cameraAtOffset += part.OffsetPosition;
3054 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3055 cameraEyeOffset += part.OffsetPosition;
3056 }
2534 3057
2535 // not using autopilot 3058 }
2536 3059
2537 Rotation = Orientation;
2538 m_pos = offset; 3060 m_pos = offset;
2539 3061
3062 ControllingClient.SendSitResponse(
3063 part.ParentGroup.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
3064
3065
2540 m_requestedSitTargetID = 0; 3066 m_requestedSitTargetID = 0;
2541 part.ParentGroup.AddAvatar(UUID); 3067 part.ParentGroup.AddAvatar(UUID);
2542 3068
@@ -2554,6 +3080,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 3080
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 3081 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 3082 {
3083 if (IsChildAgent)
3084 return;
3085
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3086 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 3087
2559 if (part != null) 3088 if (part != null)
@@ -2603,24 +3132,40 @@ namespace OpenSim.Region.Framework.Scenes
2603 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3132 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2604 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 3133 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2605 3134
2606 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 3135 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3136 Quaternion newRot;
3137
3138 if (part.IsRoot)
3139 {
3140 newRot = sitTargetOrient;
3141 }
3142 else
3143 {
3144 newPos = newPos * part.RotationOffset;
3145 newRot = part.RotationOffset * sitTargetOrient;
3146 }
3147
3148 newPos += part.OffsetPosition;
3149
3150 m_pos = newPos;
3151 Rotation = newRot;
2607 3152
2608// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2609 Rotation = sitTargetOrient;
2610// ParentPosition = part.AbsolutePosition; 3153// ParentPosition = part.AbsolutePosition;
2611 part.ParentGroup.AddAvatar(UUID);
2612 } 3154 }
2613 else 3155 else
2614 { 3156 {
2615 m_pos -= part.AbsolutePosition; 3157 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
3158 // being sat upon.
3159 m_pos -= part.GroupPosition;
3160
2616// ParentPosition = part.AbsolutePosition; 3161// ParentPosition = part.AbsolutePosition;
2617 part.ParentGroup.AddAvatar(UUID);
2618 3162
2619// m_log.DebugFormat( 3163// m_log.DebugFormat(
2620// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 3164// "[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); 3165// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2622 } 3166 }
2623 3167
3168 part.ParentGroup.AddAvatar(UUID);
2624 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3169 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2625 ParentID = m_requestedSitTargetID; 3170 ParentID = m_requestedSitTargetID;
2626 m_AngularVelocity = Vector3.Zero; 3171 m_AngularVelocity = Vector3.Zero;
@@ -2634,14 +3179,19 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 3179 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 3180 Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 3181 SendAvatarDataToAllAgents();
3182 TriggerScenePresenceUpdated();
2637 } 3183 }
2638 } 3184 }
2639 3185
2640 public void HandleAgentSitOnGround() 3186 public void HandleAgentSitOnGround()
2641 { 3187 {
3188 if (IsChildAgent)
3189 return;
3190
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3191// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 3192 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3193 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3194 TriggerScenePresenceUpdated();
2645 SitGround = true; 3195 SitGround = true;
2646 RemoveFromPhysicalScene(); 3196 RemoveFromPhysicalScene();
2647 } 3197 }
@@ -2658,11 +3208,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 3208 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 3209 {
2660 Animator.AddAnimation(animID, UUID.Zero); 3210 Animator.AddAnimation(animID, UUID.Zero);
3211 TriggerScenePresenceUpdated();
2661 } 3212 }
2662 3213
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 3214 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 3215 {
2665 Animator.RemoveAnimation(animID, false); 3216 Animator.RemoveAnimation(animID, false);
3217 TriggerScenePresenceUpdated();
2666 } 3218 }
2667 3219
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 3220 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2676,10 +3228,13 @@ namespace OpenSim.Region.Framework.Scenes
2676 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3228 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2677 /// </summary> 3229 /// </summary>
2678 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3230 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2679 public void AddNewMovement(Vector3 vec) 3231 /// <param name="thisAddSpeedModifier">
3232 /// Optional additional speed modifier for this particular add. Default is 1</param>
3233 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
2680 { 3234 {
2681// m_log.DebugFormat( 3235// m_log.DebugFormat(
2682// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3236// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3237// vec, Rotation, thisAddSpeedModifier, Name);
2683 3238
2684 Vector3 direc = vec * Rotation; 3239 Vector3 direc = vec * Rotation;
2685 direc.Normalize(); 3240 direc.Normalize();
@@ -2697,7 +3252,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 if ((vec.Z == 0f) && !Flying) 3252 if ((vec.Z == 0f) && !Flying)
2698 direc.Z = 0f; // Prevent camera WASD up. 3253 direc.Z = 0f; // Prevent camera WASD up.
2699 3254
2700 direc *= 0.03f * 128f * SpeedModifier; 3255 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2701 3256
2702// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3257// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2703 3258
@@ -2753,6 +3308,9 @@ namespace OpenSim.Region.Framework.Scenes
2753 3308
2754 if (IsChildAgent == false) 3309 if (IsChildAgent == false)
2755 { 3310 {
3311 if (IsInTransit)
3312 return;
3313
2756 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3314 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
2757 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3315 // grab the latest PhysicsActor velocity, whereas m_velocity is often
2758 // storing a requested force instead of an actual traveling velocity 3316 // storing a requested force instead of an actual traveling velocity
@@ -2781,9 +3339,16 @@ namespace OpenSim.Region.Framework.Scenes
2781 3339
2782 #region Update Client(s) 3340 #region Update Client(s)
2783 3341
3342 // this is diferente from SendTerseUpdateToClient
3343 // this sends bypassing ententies updates
3344 public void SendAgentTerseUpdate(ISceneEntity p)
3345 {
3346 ControllingClient.SendAgentTerseUpdate(p);
3347 }
2784 3348
2785 /// <summary> 3349 /// <summary>
2786 /// Sends a location update to the client connected to this scenePresence 3350 /// Sends a location update to the client connected to this scenePresence
3351 /// via entity updates
2787 /// </summary> 3352 /// </summary>
2788 /// <param name="remoteClient"></param> 3353 /// <param name="remoteClient"></param>
2789 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3354 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -2793,7 +3358,6 @@ namespace OpenSim.Region.Framework.Scenes
2793 if (remoteClient.IsActive) 3358 if (remoteClient.IsActive)
2794 { 3359 {
2795 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3360 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
2796
2797 remoteClient.SendEntityUpdate( 3361 remoteClient.SendEntityUpdate(
2798 this, 3362 this,
2799 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3363 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -2803,6 +3367,24 @@ namespace OpenSim.Region.Framework.Scenes
2803 } 3367 }
2804 } 3368 }
2805 3369
3370 public void SendTerseUpdateToAgentClient(ScenePresence p)
3371 {
3372 IClientAPI remoteClient = p.ControllingClient;
3373
3374 if (!remoteClient.IsActive)
3375 return;
3376
3377 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3378 return;
3379
3380 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3381 remoteClient.SendEntityUpdate(
3382 this,
3383 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3384 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3385
3386 m_scene.StatsReporter.AddAgentUpdates(1);
3387 }
2806 3388
2807 // vars to support reduced update frequency when velocity is unchanged 3389 // vars to support reduced update frequency when velocity is unchanged
2808 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3390 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -2843,7 +3425,9 @@ namespace OpenSim.Region.Framework.Scenes
2843 lastTerseUpdateToAllClientsTick = currentTick; 3425 lastTerseUpdateToAllClientsTick = currentTick;
2844 lastPositionSentToAllClients = OffsetPosition; 3426 lastPositionSentToAllClients = OffsetPosition;
2845 3427
2846 m_scene.ForEachClient(SendTerseUpdateToClient); 3428// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3429// m_scene.ForEachClient(SendTerseUpdateToClient);
3430 m_scene.ForEachScenePresence(SendTerseUpdateToAgentClient);
2847 } 3431 }
2848 TriggerScenePresenceUpdated(); 3432 TriggerScenePresenceUpdated();
2849 } 3433 }
@@ -2876,15 +3460,24 @@ namespace OpenSim.Region.Framework.Scenes
2876 // we created a new ScenePresence (a new child agent) in a fresh region. 3460 // we created a new ScenePresence (a new child agent) in a fresh region.
2877 // Request info about all the (root) agents in this region 3461 // Request info about all the (root) agents in this region
2878 // Note: This won't send data *to* other clients in that region (children don't send) 3462 // Note: This won't send data *to* other clients in that region (children don't send)
3463 if (m_teleportFlags <= 0)
3464 {
3465 ILandChannel landch = m_scene.LandChannel;
3466 if (landch != null)
3467 {
3468 landch.sendClientInitialLandInfo(ControllingClient);
3469 }
3470 }
2879 SendOtherAgentsAvatarDataToMe(); 3471 SendOtherAgentsAvatarDataToMe();
2880 SendOtherAgentsAppearanceToMe(); 3472 SendOtherAgentsAppearanceToMe();
2881 3473
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3474 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3475 foreach (EntityBase e in entities)
2884 { 3476 {
2885 if (e != null && e is SceneObjectGroup) 3477 if (e != null && e is SceneObjectGroup)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3478 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3479 }
3480
2888 }); 3481 });
2889 } 3482 }
2890 3483
@@ -2909,7 +3502,9 @@ namespace OpenSim.Region.Framework.Scenes
2909 // If we aren't using a cached appearance, then clear out the baked textures 3502 // If we aren't using a cached appearance, then clear out the baked textures
2910 if (!cachedappearance) 3503 if (!cachedappearance)
2911 { 3504 {
2912 Appearance.ResetAppearance(); 3505// Appearance.ResetAppearance();
3506// save what ????
3507// maybe needed so the tryretry repair works?
2913 if (m_scene.AvatarFactory != null) 3508 if (m_scene.AvatarFactory != null)
2914 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3509 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
2915 } 3510 }
@@ -2919,13 +3514,18 @@ namespace OpenSim.Region.Framework.Scenes
2919 // again here... this comes after the cached appearance check because the avatars 3514 // again here... this comes after the cached appearance check because the avatars
2920 // appearance goes into the avatar update packet 3515 // appearance goes into the avatar update packet
2921 SendAvatarDataToAllAgents(); 3516 SendAvatarDataToAllAgents();
3517
3518 // This invocation always shows up in the viewer logs as an error. Is it needed?
3519 // send all information we have
3520 // possible not needed since viewer should ask about it
3521 // least it all ask for baked
2922 SendAppearanceToAgent(this); 3522 SendAppearanceToAgent(this);
2923 3523
2924 // If we are using the the cached appearance then send it out to everyone 3524 // If we are using the the cached appearance then send it out to everyone
3525 // send even grays
2925 if (cachedappearance) 3526 if (cachedappearance)
2926 { 3527 {
2927 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3528// m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
2928
2929 // If the avatars baked textures are all in the cache, then we have a 3529 // 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 3530 // complete appearance... send it out, if not, then we'll send it when
2931 // the avatar finishes updating its appearance 3531 // the avatar finishes updating its appearance
@@ -2951,17 +3551,17 @@ namespace OpenSim.Region.Framework.Scenes
2951 } 3551 }
2952 3552
2953 m_lastSize = Appearance.AvatarSize; 3553 m_lastSize = Appearance.AvatarSize;
2954
2955 int count = 0; 3554 int count = 0;
3555
2956 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3556 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2957 { 3557 {
2958 SendAvatarDataToAgent(scenePresence); 3558 SendAvatarDataToAgent(scenePresence);
2959 count++; 3559 count++;
2960 }); 3560 });
2961 3561
2962 m_scene.StatsReporter.AddAgentUpdates(count); 3562 m_scene.StatsReporter.AddAgentUpdates(count);
2963 } 3563 }
2964 3564
2965 /// <summary> 3565 /// <summary>
2966 /// Send avatar data for all other root agents to this agent, this agent 3566 /// Send avatar data for all other root agents to this agent, this agent
2967 /// can be either a child or root 3567 /// can be either a child or root
@@ -2969,12 +3569,13 @@ namespace OpenSim.Region.Framework.Scenes
2969 public void SendOtherAgentsAvatarDataToMe() 3569 public void SendOtherAgentsAvatarDataToMe()
2970 { 3570 {
2971 int count = 0; 3571 int count = 0;
3572
2972 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3573 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
2973 { 3574 {
2974 // only send information about other root agents 3575 // only send information about other root agents
2975 if (scenePresence.UUID == UUID) 3576 if (scenePresence.UUID == UUID)
2976 return; 3577 return;
2977 3578
2978 scenePresence.SendAvatarDataToAgent(this); 3579 scenePresence.SendAvatarDataToAgent(this);
2979 count++; 3580 count++;
2980 }); 3581 });
@@ -2989,7 +3590,8 @@ namespace OpenSim.Region.Framework.Scenes
2989 public void SendAvatarDataToAgent(ScenePresence avatar) 3590 public void SendAvatarDataToAgent(ScenePresence avatar)
2990 { 3591 {
2991 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3592 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2992 3593 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3594 return;
2993 avatar.ControllingClient.SendAvatarDataImmediate(this); 3595 avatar.ControllingClient.SendAvatarDataImmediate(this);
2994 Animator.SendAnimPackToClient(avatar.ControllingClient); 3596 Animator.SendAnimPackToClient(avatar.ControllingClient);
2995 } 3597 }
@@ -3000,7 +3602,7 @@ namespace OpenSim.Region.Framework.Scenes
3000 /// </summary> 3602 /// </summary>
3001 public void SendAppearanceToAllOtherAgents() 3603 public void SendAppearanceToAllOtherAgents()
3002 { 3604 {
3003// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); 3605 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3004 3606
3005 // only send update from root agents to other clients; children are only "listening posts" 3607 // only send update from root agents to other clients; children are only "listening posts"
3006 if (IsChildAgent) 3608 if (IsChildAgent)
@@ -3011,7 +3613,7 @@ namespace OpenSim.Region.Framework.Scenes
3011 3613
3012 return; 3614 return;
3013 } 3615 }
3014 3616
3015 int count = 0; 3617 int count = 0;
3016 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3618 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3017 { 3619 {
@@ -3022,7 +3624,6 @@ namespace OpenSim.Region.Framework.Scenes
3022 SendAppearanceToAgent(scenePresence); 3624 SendAppearanceToAgent(scenePresence);
3023 count++; 3625 count++;
3024 }); 3626 });
3025
3026 m_scene.StatsReporter.AddAgentUpdates(count); 3627 m_scene.StatsReporter.AddAgentUpdates(count);
3027 } 3628 }
3028 3629
@@ -3056,11 +3657,10 @@ namespace OpenSim.Region.Framework.Scenes
3056 { 3657 {
3057// m_log.DebugFormat( 3658// m_log.DebugFormat(
3058// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3659// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3059 3660 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3661 return;
3060 avatar.ControllingClient.SendAppearance( 3662 avatar.ControllingClient.SendAppearance(
3061 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3663 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3062
3063
3064 } 3664 }
3065 3665
3066 #endregion 3666 #endregion
@@ -3079,11 +3679,10 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3679 }
3080 3680
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3681 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3682 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3683 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3684 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3685// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3686
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3687 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3688 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3110,7 +3709,7 @@ namespace OpenSim.Region.Framework.Scenes
3110 cadu.Velocity = Velocity; 3709 cadu.Velocity = Velocity;
3111 3710
3112 AgentPosition agentpos = new AgentPosition(); 3711 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3712 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3114 3713
3115 // Let's get this out of the update loop 3714 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3715 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3130,7 +3729,7 @@ namespace OpenSim.Region.Framework.Scenes
3130 protected void CheckForBorderCrossing() 3729 protected void CheckForBorderCrossing()
3131 { 3730 {
3132 // Check that we we are not a child 3731 // Check that we we are not a child
3133 if (IsChildAgent) 3732 if (IsChildAgent)
3134 return; 3733 return;
3135 3734
3136 // If we don't have a PhysActor, we can't cross anyway 3735 // If we don't have a PhysActor, we can't cross anyway
@@ -3140,140 +3739,127 @@ namespace OpenSim.Region.Framework.Scenes
3140 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3739 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3141 return; 3740 return;
3142 3741
3143 if (!IsInTransit) 3742 if (IsInTransit)
3144 { 3743 return;
3145 Vector3 pos2 = AbsolutePosition;
3146 Vector3 vel = Velocity;
3147 int neighbor = 0;
3148 int[] fix = new int[2];
3149 3744
3150 float timeStep = 0.1f; 3745 Vector3 pos2 = AbsolutePosition;
3151 pos2.X = pos2.X + (vel.X * timeStep); 3746 Vector3 vel = Velocity;
3152 pos2.Y = pos2.Y + (vel.Y * timeStep); 3747 int neighbor = 0;
3153 pos2.Z = pos2.Z + (vel.Z * timeStep); 3748 int[] fix = new int[2];
3154 3749
3155 if (!IsInTransit) 3750 float timeStep = 0.1f;
3156 { 3751 pos2.X = pos2.X + (vel.X * timeStep);
3157// m_log.DebugFormat( 3752 pos2.Y = pos2.Y + (vel.Y * timeStep);
3158// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", 3753 pos2.Z = pos2.Z + (vel.Z * timeStep);
3159// pos2, Name, Scene.Name);
3160 3754
3161 // Checks if where it's headed exists a region
3162 bool needsTransit = false;
3163 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3164 {
3165 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3166 {
3167 needsTransit = true;
3168 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3169 }
3170 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3171 {
3172 needsTransit = true;
3173 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3174 }
3175 else
3176 {
3177 needsTransit = true;
3178 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3179 }
3180 }
3181 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3182 {
3183 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3184 {
3185 needsTransit = true;
3186 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3187 }
3188 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3189 {
3190 needsTransit = true;
3191 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3192 }
3193 else
3194 {
3195 needsTransit = true;
3196 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3197 }
3198 }
3199 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3200 {
3201 needsTransit = true;
3202 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3203 }
3204 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3205 {
3206 needsTransit = true;
3207 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3208 }
3209 3755
3210 // Makes sure avatar does not end up outside region 3756 // m_log.DebugFormat(
3211 if (neighbor <= 0) 3757 // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3212 { 3758 // pos2, Name, Scene.Name);
3213 if (needsTransit) 3759
3214 { 3760 // Checks if where it's headed exists a region
3215 if (m_requestedSitTargetUUID == UUID.Zero) 3761 bool needsTransit = false;
3216 { 3762 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3217 bool isFlying = Flying; 3763 {
3218 RemoveFromPhysicalScene(); 3764 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3219 3765 {
3220 Vector3 pos = AbsolutePosition; 3766 needsTransit = true;
3221 if (AbsolutePosition.X < 0) 3767 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3222 pos.X += Velocity.X * 2; 3768 }
3223 else if (AbsolutePosition.X > Constants.RegionSize) 3769 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3224 pos.X -= Velocity.X * 2; 3770 {
3225 if (AbsolutePosition.Y < 0) 3771 needsTransit = true;
3226 pos.Y += Velocity.Y * 2; 3772 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3227 else if (AbsolutePosition.Y > Constants.RegionSize) 3773 }
3228 pos.Y -= Velocity.Y * 2; 3774 else
3229 Velocity = Vector3.Zero; 3775 {
3230 AbsolutePosition = pos; 3776 needsTransit = true;
3231 3777 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3232// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition); 3778 }
3233 3779 }
3234 AddToPhysicalScene(isFlying); 3780 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3235 } 3781 {
3236 } 3782 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3237 } 3783 {
3238 else if (neighbor > 0) 3784 needsTransit = true;
3785 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3786 }
3787 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3788 {
3789 needsTransit = true;
3790 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3791 }
3792 else
3793 {
3794 needsTransit = true;
3795 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3796 }
3797 }
3798 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3799 {
3800 needsTransit = true;
3801 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3802 }
3803 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3804 {
3805 needsTransit = true;
3806 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3807 }
3808
3809 // Makes sure avatar does not end up outside region
3810 if (neighbor <= 0)
3811 {
3812 if (needsTransit)
3813 {
3814 if (m_requestedSitTargetUUID == UUID.Zero)
3239 { 3815 {
3240 if (!CrossToNewRegion()) 3816 bool isFlying = Flying;
3241 { 3817 RemoveFromPhysicalScene();
3242 if (m_requestedSitTargetUUID == UUID.Zero) 3818
3243 { 3819 Vector3 pos = AbsolutePosition;
3244 bool isFlying = Flying; 3820 if (AbsolutePosition.X < 0)
3245 RemoveFromPhysicalScene(); 3821 pos.X += Velocity.X * 2;
3246 3822 else if (AbsolutePosition.X > Constants.RegionSize)
3247 Vector3 pos = AbsolutePosition; 3823 pos.X -= Velocity.X * 2;
3248 if (AbsolutePosition.X < 0) 3824 if (AbsolutePosition.Y < 0)
3249 pos.X += Velocity.X * 2; 3825 pos.Y += Velocity.Y * 2;
3250 else if (AbsolutePosition.X > Constants.RegionSize) 3826 else if (AbsolutePosition.Y > Constants.RegionSize)
3251 pos.X -= Velocity.X * 2; 3827 pos.Y -= Velocity.Y * 2;
3252 if (AbsolutePosition.Y < 0) 3828 Velocity = Vector3.Zero;
3253 pos.Y += Velocity.Y * 2; 3829 AbsolutePosition = pos;
3254 else if (AbsolutePosition.Y > Constants.RegionSize) 3830
3255 pos.Y -= Velocity.Y * 2; 3831 // m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3256 Velocity = Vector3.Zero; 3832
3257 AbsolutePosition = pos; 3833 AddToPhysicalScene(isFlying);
3258
3259 AddToPhysicalScene(isFlying);
3260 }
3261 }
3262 } 3834 }
3263 } 3835 }
3264 else 3836 }
3837 else if (neighbor > 0)
3838 {
3839 if (!CrossToNewRegion())
3265 { 3840 {
3266 // This constant has been inferred from experimentation 3841 if (m_requestedSitTargetUUID == UUID.Zero)
3267 // I'm not sure what this value should be, so I tried a few values. 3842 {
3268 timeStep = 0.04f; 3843 bool isFlying = Flying;
3269 pos2 = AbsolutePosition; 3844 RemoveFromPhysicalScene();
3270 pos2.X = pos2.X + (vel.X * timeStep); 3845
3271 pos2.Y = pos2.Y + (vel.Y * timeStep); 3846 Vector3 pos = AbsolutePosition;
3272 // Don't touch the Z 3847 if (AbsolutePosition.X < 0)
3273 m_pos = pos2; 3848 pos.X += Velocity.X * 2;
3274 m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos); 3849 else if (AbsolutePosition.X > Constants.RegionSize)
3850 pos.X -= Velocity.X * 2;
3851 if (AbsolutePosition.Y < 0)
3852 pos.Y += Velocity.Y * 2;
3853 else if (AbsolutePosition.Y > Constants.RegionSize)
3854 pos.Y -= Velocity.Y * 2;
3855 Velocity = Vector3.Zero;
3856 AbsolutePosition = pos;
3857
3858 AddToPhysicalScene(isFlying);
3859 }
3275 } 3860 }
3276 } 3861 }
3862
3277 } 3863 }
3278 3864
3279 /// <summary> 3865 /// <summary>
@@ -3284,19 +3870,21 @@ namespace OpenSim.Region.Framework.Scenes
3284 /// </summary> 3870 /// </summary>
3285 protected bool CrossToNewRegion() 3871 protected bool CrossToNewRegion()
3286 { 3872 {
3873 bool result = false;
3874 parcelRegionCross(false);
3287 try 3875 try
3288 { 3876 {
3289 return m_scene.CrossAgentToNewRegion(this, Flying); 3877 result = m_scene.CrossAgentToNewRegion(this, Flying);
3290 } 3878 }
3291 catch 3879 catch
3292 { 3880 {
3293 return m_scene.CrossAgentToNewRegion(this, false); 3881 result = m_scene.CrossAgentToNewRegion(this, false);
3294 } 3882 }
3295 } 3883 if(!result)
3884 parcelRegionCross(true);
3885
3886 return result;
3296 3887
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 } 3888 }
3301 3889
3302 public void Reset() 3890 public void Reset()
@@ -3348,10 +3936,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 3936 if (byebyeRegions.Count > 0)
3349 { 3937 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 3938 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 3939
3352 { 3940 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 3941 string auth = string.Empty;
3354 }); 3942 if (acd != null)
3943 auth = acd.SessionID.ToString();
3944 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 3945 }
3356 3946
3357 foreach (ulong handle in byebyeRegions) 3947 foreach (ulong handle in byebyeRegions)
@@ -3368,6 +3958,8 @@ namespace OpenSim.Region.Framework.Scenes
3368 /// </summary> 3958 /// </summary>
3369 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 3959 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3370 { 3960 {
3961 int oldgodlevel = GodLevel;
3962
3371 if (godStatus) 3963 if (godStatus)
3372 { 3964 {
3373 // For now, assign god level 200 to anyone 3965 // For now, assign god level 200 to anyone
@@ -3388,11 +3980,14 @@ namespace OpenSim.Region.Framework.Scenes
3388 } 3980 }
3389 3981
3390 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 3982 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
3983
3984 if(oldgodlevel != GodLevel)
3985 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3391 } 3986 }
3392 3987
3393 #region Child Agent Updates 3988 #region Child Agent Updates
3394 3989
3395 public void ChildAgentDataUpdate(AgentData cAgentData) 3990 public void UpdateChildAgent(AgentData cAgentData)
3396 { 3991 {
3397// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3992// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3398 if (!IsChildAgent) 3993 if (!IsChildAgent)
@@ -3402,15 +3997,17 @@ namespace OpenSim.Region.Framework.Scenes
3402 } 3997 }
3403 3998
3404 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3999 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
4000
3405 private void RaiseUpdateThrottles() 4001 private void RaiseUpdateThrottles()
3406 { 4002 {
3407 m_scene.EventManager.TriggerThrottleUpdate(this); 4003 m_scene.EventManager.TriggerThrottleUpdate(this);
3408 } 4004 }
4005
3409 /// <summary> 4006 /// <summary>
3410 /// This updates important decision making data about a child agent 4007 /// 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 4008 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3412 /// </summary> 4009 /// </summary>
3413 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 4010 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3414 { 4011 {
3415 if (!IsChildAgent) 4012 if (!IsChildAgent)
3416 return; 4013 return;
@@ -3452,6 +4049,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 4049
3453 cAgent.AgentID = UUID; 4050 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 4051 cAgent.RegionID = Scene.RegionInfo.RegionID;
4052 cAgent.SessionID = ControllingClient.SessionId;
3455 4053
3456 cAgent.Position = AbsolutePosition; 4054 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 4055 cAgent.Velocity = m_velocity;
@@ -3517,7 +4115,6 @@ namespace OpenSim.Region.Framework.Scenes
3517 4115
3518 private void CopyFrom(AgentData cAgent) 4116 private void CopyFrom(AgentData cAgent)
3519 { 4117 {
3520 m_originRegionID = cAgent.RegionID;
3521 4118
3522 m_callbackURI = cAgent.CallbackURI; 4119 m_callbackURI = cAgent.CallbackURI;
3523// m_log.DebugFormat( 4120// m_log.DebugFormat(
@@ -3591,6 +4188,10 @@ namespace OpenSim.Region.Framework.Scenes
3591 4188
3592 if (Scene.AttachmentsModule != null) 4189 if (Scene.AttachmentsModule != null)
3593 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 4190 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4191
4192 lock (m_originRegionIDAccessLock)
4193 m_originRegionID = cAgent.RegionID;
4194
3594 } 4195 }
3595 4196
3596 public bool CopyAgent(out IAgentData agent) 4197 public bool CopyAgent(out IAgentData agent)
@@ -3607,12 +4208,12 @@ namespace OpenSim.Region.Framework.Scenes
3607 /// </summary> 4208 /// </summary>
3608 public void UpdateMovement() 4209 public void UpdateMovement()
3609 { 4210 {
4211 if (IsInTransit)
4212 return;
3610 if (m_forceToApply.HasValue) 4213 if (m_forceToApply.HasValue)
3611 { 4214 {
3612 Vector3 force = m_forceToApply.Value; 4215 Vector3 force = m_forceToApply.Value;
3613 4216
3614 Updated = true;
3615
3616 Velocity = force; 4217 Velocity = force;
3617 4218
3618 m_forceToApply = null; 4219 m_forceToApply = null;
@@ -3687,14 +4288,17 @@ namespace OpenSim.Region.Framework.Scenes
3687 { 4288 {
3688 if (IsChildAgent || Animator == null) 4289 if (IsChildAgent || Animator == null)
3689 return; 4290 return;
3690 4291
4292 if(IsInTransit)
4293 return;
3691 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4294 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3692 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( 4295 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3693 // as of this comment the interval is set in AddToPhysicalScene 4296 // as of this comment the interval is set in AddToPhysicalScene
3694 4297
3695// if (m_updateCount > 0) 4298// if (m_updateCount > 0)
3696// { 4299// {
3697 Animator.UpdateMovementAnimations(); 4300 if (Animator.UpdateMovementAnimations())
4301 TriggerScenePresenceUpdated();
3698// m_updateCount--; 4302// m_updateCount--;
3699// } 4303// }
3700 4304
@@ -3858,6 +4462,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4462// Animator.Close();
3859 Animator = null; 4463 Animator = null;
3860 4464
4465 LifecycleState = ScenePresenceState.Removed;
3861 } 4466 }
3862 4467
3863 public void AddAttachment(SceneObjectGroup gobj) 4468 public void AddAttachment(SceneObjectGroup gobj)
@@ -4033,6 +4638,18 @@ namespace OpenSim.Region.Framework.Scenes
4033 return validated; 4638 return validated;
4034 } 4639 }
4035 4640
4641
4642 public void SendAttachmentsToClient(IClientAPI client)
4643 {
4644 lock (m_attachments)
4645 {
4646 foreach (SceneObjectGroup gobj in m_attachments)
4647 {
4648 gobj.SendFullUpdateToClient(client);
4649 }
4650 }
4651 }
4652
4036 /// <summary> 4653 /// <summary>
4037 /// Send a script event to this scene presence's attachments 4654 /// Send a script event to this scene presence's attachments
4038 /// </summary> 4655 /// </summary>
@@ -4151,6 +4768,15 @@ namespace OpenSim.Region.Framework.Scenes
4151 ControllingClient.SendTakeControls(int.MaxValue, false, false); 4768 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4152 } 4769 }
4153 4770
4771 public void ClearControls()
4772 {
4773 IgnoredControls = ScriptControlled.CONTROL_ZERO;
4774 lock (scriptedcontrols)
4775 {
4776 scriptedcontrols.Clear();
4777 }
4778 }
4779
4154 private void UnRegisterSeatControls(UUID obj) 4780 private void UnRegisterSeatControls(UUID obj)
4155 { 4781 {
4156 List<UUID> takers = new List<UUID>(); 4782 List<UUID> takers = new List<UUID>();
@@ -4678,6 +5304,8 @@ namespace OpenSim.Region.Framework.Scenes
4678 5304
4679 else 5305 else
4680 { 5306 {
5307 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5308
4681 foreach (uint id in coldata.Keys) 5309 foreach (uint id in coldata.Keys)
4682 { 5310 {
4683 thisHitColliders.Add(id); 5311 thisHitColliders.Add(id);
@@ -4685,7 +5313,7 @@ namespace OpenSim.Region.Framework.Scenes
4685 { 5313 {
4686 startedColliders.Add(id); 5314 startedColliders.Add(id);
4687 curcontact = coldata[id]; 5315 curcontact = coldata[id];
4688 if (Math.Abs(curcontact.RelativeSpeed) > 0.2) 5316 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
4689 { 5317 {
4690 soundinfo = new CollisionForSoundInfo(); 5318 soundinfo = new CollisionForSoundInfo();
4691 soundinfo.colliderID = id; 5319 soundinfo.colliderID = id;
@@ -4764,5 +5392,404 @@ namespace OpenSim.Region.Framework.Scenes
4764 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5392 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4765 5393
4766 } 5394 }
5395
5396 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5397 {
5398 List<ScenePresence> allpresences = null;
5399
5400
5401 allpresences = m_scene.GetScenePresences();
5402
5403 if (isGod)
5404 {
5405 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5406
5407 foreach (ScenePresence p in allpresences)
5408 {
5409 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5410 continue;
5411
5412 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5413 {
5414 viewsToSendme.Add(p); // i see them
5415 }
5416 }
5417
5418 if (viewsToSendme.Count > 0)
5419 {
5420 foreach (ScenePresence p in viewsToSendme)
5421 {
5422 if (p.IsChildAgent)
5423 continue;
5424 m_log.Debug("[AVATAR]: viewMe: " + Lastname + " " + p.Lastname);
5425 ControllingClient.SendAvatarDataImmediate(p);
5426 p.SendAppearanceToAgent(this);
5427 p.SendAttachmentsToClient(ControllingClient);
5428 if (p.Animator != null)
5429 p.Animator.SendAnimPackToClient(ControllingClient);
5430 }
5431 }
5432 }
5433 else
5434 {
5435 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5436
5437 foreach (ScenePresence p in allpresences)
5438 {
5439 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5440 continue;
5441
5442 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5443 {
5444 killsToSendme.Add(p);
5445 }
5446 }
5447
5448 if (killsToSendme.Count > 0)
5449 {
5450 foreach (ScenePresence p in killsToSendme)
5451 {
5452 m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname);
5453 try { ControllingClient.SendKillObject(new List<uint> { p.LocalId }); }
5454 catch (NullReferenceException) { }
5455 }
5456 }
5457 }
5458
5459 }
5460
5461 private void ParcelLoginCheck(UUID currentParcelID)
5462 {
5463 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5464 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5465 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5466 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5467 List<ScenePresence> allpresences = null;
5468
5469 allpresences = m_scene.GetScenePresences();
5470
5471 foreach (ScenePresence p in allpresences)
5472 {
5473 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5474 continue;
5475
5476 if (currentParcelID != p.currentParcelUUID)
5477 {
5478 if (p.GodLevel < 200)
5479 killsToSendto.Add(p);
5480 if (GodLevel < 200 && p.ParcelHideThisAvatar)
5481 killsToSendme.Add(p);
5482 }
5483 else
5484 {
5485 viewsToSendto.Add(p);
5486 viewsToSendme.Add(p);
5487 }
5488 }
5489 allpresences.Clear();
5490
5491 // send the things
5492 // kill main avatar object
5493 if (killsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5494 {
5495 foreach (ScenePresence p in killsToSendto)
5496 {
5497 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
5498 try { p.ControllingClient.SendKillObject(new List<uint> { LocalId }); }
5499 catch (NullReferenceException) { }
5500 }
5501 }
5502
5503 if (killsToSendme.Count > 0)
5504 {
5505 foreach (ScenePresence p in killsToSendme)
5506 {
5507 m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname);
5508 try { ControllingClient.SendKillObject(new List<uint> { p.LocalId }); }
5509 catch (NullReferenceException) { }
5510 }
5511 }
5512
5513 if (viewsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5514 {
5515 foreach (ScenePresence p in viewsToSendto)
5516 {
5517 m_log.Debug("[AVATAR]: viewTo: " + Lastname + " " + p.Lastname);
5518 p.ControllingClient.SendAvatarDataImmediate(this);
5519 SendAppearanceToAgent(p);
5520 SendAttachmentsToClient(p.ControllingClient);
5521 if (Animator != null)
5522 Animator.SendAnimPackToClient(p.ControllingClient);
5523 }
5524 }
5525
5526 if (viewsToSendme.Count > 0)
5527 {
5528 foreach (ScenePresence p in viewsToSendme)
5529 {
5530 m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
5531 if (p.IsChildAgent)
5532 continue;
5533 ControllingClient.SendAvatarDataImmediate(p);
5534 p.SendAppearanceToAgent(this);
5535 p.SendAttachmentsToClient(ControllingClient);
5536 if (p.Animator != null)
5537 p.Animator.SendAnimPackToClient(ControllingClient);
5538 }
5539 }
5540 }
5541
5542 private void parcelRegionCross(bool abort)
5543 {
5544 if (!ParcelHideThisAvatar)
5545 return;
5546
5547 List<ScenePresence> allpresences = null;
5548 allpresences = m_scene.GetScenePresences();
5549
5550 if (abort)
5551 {
5552 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5553
5554 foreach (ScenePresence p in allpresences)
5555 {
5556 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5557 continue;
5558
5559 if (p.currentParcelUUID == m_currentParcelUUID)
5560 {
5561 viewsToSendme.Add(p);
5562 }
5563 }
5564
5565 if (viewsToSendme.Count > 0)
5566 {
5567 foreach (ScenePresence p in viewsToSendme)
5568 {
5569 if (p.IsChildAgent)
5570 continue;
5571// m_log.Debug("[AVATAR]: viewMe: " + Lastname + " " + p.Lastname);
5572 ControllingClient.SendAvatarDataImmediate(p);
5573 p.SendAppearanceToAgent(this);
5574 p.SendAttachmentsToClient(ControllingClient);
5575 if (p.Animator != null)
5576 p.Animator.SendAnimPackToClient(ControllingClient);
5577 }
5578 }
5579 }
5580 else
5581 {
5582 if (GodLevel >= 200)
5583 return;
5584
5585 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5586 foreach (ScenePresence p in allpresences)
5587 {
5588 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5589 continue;
5590
5591 if (p.currentParcelUUID == m_currentParcelUUID)
5592 {
5593 killsToSendme.Add(p);
5594 }
5595 }
5596
5597 if (killsToSendme.Count > 0)
5598 {
5599 foreach (ScenePresence p in killsToSendme)
5600 {
5601 m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname);
5602 try { ControllingClient.SendKillObject(new List<uint> { p.LocalId }); }
5603 catch (NullReferenceException) { }
5604 }
5605 }
5606 }
5607 }
5608
5609
5610 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5611 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5612 {
5613 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5614 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5615 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5616 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5617 List<ScenePresence> allpresences = null;
5618
5619 if (IsInTransit)
5620 return;
5621
5622 if (check)
5623 {
5624 // check is relative to current parcel only
5625 if (currentParcelUUID == null || oldhide == currentParcelHide)
5626 return;
5627
5628 allpresences = m_scene.GetScenePresences();
5629
5630 if (oldhide)
5631 { // where private
5632 foreach (ScenePresence p in allpresences)
5633 {
5634 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5635 continue;
5636
5637 // those on not on parcel see me
5638 if (currentParcelID != p.currentParcelUUID)
5639 {
5640 viewsToSendto.Add(p); // they see me
5641 }
5642 }
5643 } // where private end
5644
5645 else
5646 { // where public
5647 foreach (ScenePresence p in allpresences)
5648 {
5649 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5650 continue;
5651
5652 // those not on parcel dont see me
5653 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5654 {
5655 killsToSendto.Add(p); // they dont see me
5656 }
5657 }
5658 } // where public end
5659
5660 allpresences.Clear();
5661 }
5662 else
5663 {
5664 if (currentParcelHide)
5665 {
5666 // now on a private parcel
5667 allpresences = m_scene.GetScenePresences();
5668
5669 if (previusParcelHide && previusParcelID != UUID.Zero)
5670 {
5671 foreach (ScenePresence p in allpresences)
5672 {
5673 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5674 continue;
5675
5676 // only those on previus parcel need receive kills
5677 if (previusParcelID == p.currentParcelUUID)
5678 {
5679 if(p.GodLevel < 200)
5680 killsToSendto.Add(p); // they dont see me
5681 if(GodLevel < 200)
5682 killsToSendme.Add(p); // i dont see them
5683 }
5684 // only those on new parcel need see
5685 if (currentParcelID == p.currentParcelUUID)
5686 {
5687 viewsToSendto.Add(p); // they see me
5688 viewsToSendme.Add(p); // i see them
5689 }
5690 }
5691 }
5692 else
5693 {
5694 //was on a public area
5695 allpresences = m_scene.GetScenePresences();
5696
5697 foreach (ScenePresence p in allpresences)
5698 {
5699 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5700 continue;
5701
5702 // those not on new parcel dont see me
5703 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5704 {
5705 killsToSendto.Add(p); // they dont see me
5706 }
5707 else
5708 {
5709 viewsToSendme.Add(p); // i see those on it
5710 }
5711 }
5712 }
5713 allpresences.Clear();
5714 } // now on a private parcel end
5715
5716 else
5717 {
5718 // now on public parcel
5719 if (previusParcelHide && previusParcelID != UUID.Zero)
5720 {
5721 // was on private area
5722 allpresences = m_scene.GetScenePresences();
5723
5724 foreach (ScenePresence p in allpresences)
5725 {
5726 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5727 continue;
5728 // only those old parcel need receive kills
5729 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
5730 {
5731 killsToSendme.Add(p); // i dont see them
5732 }
5733 else
5734 {
5735 viewsToSendto.Add(p); // they see me
5736 }
5737 }
5738 }
5739 else
5740 return; // was on a public area also
5741 } // now on public parcel end
5742 }
5743
5744 // send the things
5745 // kill main avatar object
5746 if (killsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5747 {
5748 foreach (ScenePresence p in killsToSendto)
5749 {
5750 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
5751 try { p.ControllingClient.SendKillObject(new List<uint> { LocalId }); }
5752 catch (NullReferenceException) { }
5753 }
5754 }
5755
5756 if (killsToSendme.Count > 0 )
5757 {
5758 foreach (ScenePresence p in killsToSendme)
5759 {
5760 m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname);
5761 try {ControllingClient.SendKillObject(new List<uint> { p.LocalId }); }
5762 catch (NullReferenceException) { }
5763 }
5764 }
5765
5766 if (viewsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5767 {
5768 foreach (ScenePresence p in viewsToSendto)
5769 {
5770 p.ControllingClient.SendAvatarDataImmediate(this);
5771// m_log.Debug("[AVATAR]: viewTo: " + Lastname + " " + p.Lastname);
5772 SendAppearanceToAgent(p);
5773 SendAttachmentsToClient(p.ControllingClient);
5774 if (Animator != null)
5775 Animator.SendAnimPackToClient(p.ControllingClient);
5776 }
5777 }
5778
5779 if (viewsToSendme.Count > 0 )
5780 {
5781 foreach (ScenePresence p in viewsToSendme)
5782 {
5783 if (p.IsChildAgent)
5784 continue;
5785// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
5786 ControllingClient.SendAvatarDataImmediate(p);
5787 p.SendAppearanceToAgent(this);
5788 p.SendAttachmentsToClient(ControllingClient);
5789 if (p.Animator != null)
5790 p.Animator.SendAnimPackToClient(ControllingClient);
5791 }
5792 }
5793 }
4767 } 5794 }
4768} 5795}
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..52bd5c9 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -271,7 +271,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
271 // Script state may, or may not, exist. Not having any, is NOT 271 // Script state may, or may not, exist. Not having any, is NOT
272 // ever a problem. 272 // ever a problem.
273 sceneObject.LoadScriptState(doc); 273 sceneObject.LoadScriptState(doc);
274 274
275 return sceneObject; 275 return sceneObject;
276 } 276 }
277 catch (Exception e) 277 catch (Exception e)
@@ -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);
@@ -390,6 +391,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
390 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset); 391 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset);
391 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset); 392 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset);
392 393
394 m_SOPXmlProcessors.Add("SoundID", ProcessSoundID);
395 m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain);
396 m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags);
397 m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius);
398 m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing);
399
393 #endregion 400 #endregion
394 401
395 #region TaskInventoryXmlProcessors initialization 402 #region TaskInventoryXmlProcessors initialization
@@ -443,6 +450,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
443 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); 450 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
444 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); 451 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
445 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); 452 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
453 m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
446 m_ShapeXmlProcessors.Add("State", ProcessShpState); 454 m_ShapeXmlProcessors.Add("State", ProcessShpState);
447 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); 455 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
448 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); 456 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@@ -652,6 +660,30 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
652 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset")); 660 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset"));
653 } 661 }
654 662
663 private static void ProcessSoundID(SceneObjectPart obj, XmlTextReader reader)
664 {
665 obj.Sound = Util.ReadUUID(reader, "SoundID");
666 }
667
668 private static void ProcessSoundGain(SceneObjectPart obj, XmlTextReader reader)
669 {
670 obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty);
671 }
672
673 private static void ProcessSoundFlags(SceneObjectPart obj, XmlTextReader reader)
674 {
675 obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty);
676 }
677
678 private static void ProcessSoundRadius(SceneObjectPart obj, XmlTextReader reader)
679 {
680 obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty);
681 }
682
683 private static void ProcessSoundQueueing(SceneObjectPart obj, XmlTextReader reader)
684 {
685 obj.SoundQueueing = Util.ReadBoolean(reader);
686 }
655 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader) 687 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
656 { 688 {
657 SOPVehicle vehicle = SOPVehicle.FromXml2(reader); 689 SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
@@ -798,6 +830,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 830 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
799 } 831 }
800 832
833 private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
834 {
835 obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
836 }
837
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) 838 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 { 839 {
803 obj.DynAttrs.ReadXml(reader); 840 obj.DynAttrs.ReadXml(reader);
@@ -1099,6 +1136,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1099 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); 1136 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
1100 } 1137 }
1101 1138
1139 private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
1140 {
1141 shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
1142 }
1143
1102 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) 1144 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
1103 { 1145 {
1104 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); 1146 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@@ -1253,6 +1295,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1253 writer.WriteBase64(data, 0, data.Length); 1295 writer.WriteBase64(data, 0, data.Length);
1254 writer.WriteEndElement(); 1296 writer.WriteEndElement();
1255 } 1297 }
1298
1256 1299
1257 writer.WriteEndElement(); 1300 writer.WriteEndElement();
1258 } 1301 }
@@ -1267,7 +1310,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1267 1310
1268 WriteUUID(writer, "CreatorID", sop.CreatorID, options); 1311 WriteUUID(writer, "CreatorID", sop.CreatorID, options);
1269 1312
1270 if (sop.CreatorData != null && sop.CreatorData != string.Empty) 1313 if (!string.IsNullOrEmpty(sop.CreatorData))
1271 writer.WriteElementString("CreatorData", sop.CreatorData); 1314 writer.WriteElementString("CreatorData", sop.CreatorData);
1272 else if (options.ContainsKey("home")) 1315 else if (options.ContainsKey("home"))
1273 { 1316 {
@@ -1345,8 +1388,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1388 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1346 if (sop.MediaUrl != null) 1389 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1390 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1391 WriteVector(writer, "AttachedPos", sop.AttachedPos);
1348 1392
1349 if (sop.DynAttrs.Count > 0) 1393 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1394 {
1351 writer.WriteStartElement("DynAttrs"); 1395 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer); 1396 sop.DynAttrs.WriteXml(writer);
@@ -1384,6 +1428,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1384 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); 1428 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1385 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); 1429 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1386 1430
1431 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1432 {
1433 WriteUUID(writer, "SoundID", sop.Sound, options);
1434 writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower());
1435 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1436 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower());
1437 }
1438 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1439
1387 writer.WriteEndElement(); 1440 writer.WriteEndElement();
1388 } 1441 }
1389 1442
@@ -1451,7 +1504,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1451 1504
1452 WriteUUID(writer, "CreatorID", item.CreatorID, options); 1505 WriteUUID(writer, "CreatorID", item.CreatorID, options);
1453 1506
1454 if (item.CreatorData != null && item.CreatorData != string.Empty) 1507 if (!string.IsNullOrEmpty(item.CreatorData))
1455 writer.WriteElementString("CreatorData", item.CreatorData); 1508 writer.WriteElementString("CreatorData", item.CreatorData);
1456 else if (options.ContainsKey("home")) 1509 else if (options.ContainsKey("home"))
1457 { 1510 {
@@ -1539,6 +1592,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1592 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1593 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1594 writer.WriteElementString("State", shp.State.ToString());
1595 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1596
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1597 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1598 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