aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs114
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs44
-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.cs208
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs58
-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.cs1168
-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.cs2284
-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
33 files changed, 4831 insertions, 1900 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..668087f 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()
@@ -535,6 +557,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
535 /// <param name="objectIDs"></param> 557 /// <param name="objectIDs"></param>
536 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) 558 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
537 { 559 {
560/*
538 if (m_scenePresence.IsChildAgent) 561 if (m_scenePresence.IsChildAgent)
539 return; 562 return;
540 563
@@ -549,6 +572,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
549 { 572 {
550 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs); 573 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
551 }); 574 });
575 */
576 m_scenePresence.SendAnimPack(animations, seqs, objectIDs);
552 } 577 }
553 578
554 public void SendAnimPackToClient(IClientAPI client) 579 public void SendAnimPackToClient(IClientAPI client)
@@ -580,7 +605,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
580 605
581 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 606 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
582 607
583 SendAnimPack(animIDs, sequenceNums, objectIDs); 608// SendAnimPack(animIDs, sequenceNums, objectIDs);
609 m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs);
584 } 610 }
585 611
586 public string GetAnimName(UUID animId) 612 public string GetAnimName(UUID animId)
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..902e60b 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 {
@@ -303,22 +323,25 @@ namespace OpenSim.Region.Framework.Scenes
303 m_group = grp; 323 m_group = grp;
304 m_scene = grp.Scene; 324 m_scene = grp.Scene;
305 325
306 Vector3 grppos = grp.AbsolutePosition; 326 lock (m_frames)
307 Vector3 offset = grppos - m_serializedPosition; 327 {
308 // avoid doing it more than once 328 Vector3 grppos = grp.AbsolutePosition;
309 // current this will happen draging a prim to other region 329 Vector3 offset = grppos - m_serializedPosition;
310 m_serializedPosition = grppos; 330 // avoid doing it more than once
331 // current this will happen draging a prim to other region
332 m_serializedPosition = grppos;
311 333
312 m_basePosition += offset; 334 m_basePosition += offset;
313 m_currentFrame.Position += offset; 335 m_currentFrame.Position += offset;
314 336
315 m_nextPosition += offset; 337 m_nextPosition += offset;
316 338
317 for (int i = 0; i < m_frames.Count; i++) 339 for (int i = 0; i < m_frames.Count; i++)
318 { 340 {
319 Keyframe k = m_frames[i]; 341 Keyframe k = m_frames[i];
320 k.Position += offset; 342 k.Position += offset;
321 m_frames[i]=k; 343 m_frames[i] = k;
344 }
322 } 345 }
323 346
324 if (m_running) 347 if (m_running)
@@ -363,25 +386,28 @@ namespace OpenSim.Region.Framework.Scenes
363 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 386 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
364 } 387 }
365 388
366 newmotion.m_frames = new List<Keyframe>(m_frames); 389 lock (m_frames)
390 {
391 newmotion.m_frames = new List<Keyframe>(m_frames);
367 392
368 newmotion.m_basePosition = m_basePosition; 393 newmotion.m_basePosition = m_basePosition;
369 newmotion.m_baseRotation = m_baseRotation; 394 newmotion.m_baseRotation = m_baseRotation;
370 395
371 if (m_selected) 396 if (m_selected)
372 newmotion.m_serializedPosition = m_serializedPosition;
373 else
374 {
375 if (m_group != null)
376 newmotion.m_serializedPosition = m_group.AbsolutePosition;
377 else
378 newmotion.m_serializedPosition = m_serializedPosition; 397 newmotion.m_serializedPosition = m_serializedPosition;
379 } 398 else
399 {
400 if (m_group != null)
401 newmotion.m_serializedPosition = m_group.AbsolutePosition;
402 else
403 newmotion.m_serializedPosition = m_serializedPosition;
404 }
380 405
381 newmotion.m_currentFrame = m_currentFrame; 406 newmotion.m_currentFrame = m_currentFrame;
382 407
383 newmotion.m_iterations = m_iterations; 408 newmotion.m_iterations = m_iterations;
384 newmotion.m_running = m_running; 409 newmotion.m_running = m_running;
410 }
385 411
386 if (m_running && !m_waitingCrossing) 412 if (m_running && !m_waitingCrossing)
387 StartTimer(); 413 StartTimer();
@@ -633,27 +659,29 @@ namespace OpenSim.Region.Framework.Scenes
633 659
634 if (m_frames.Count == 0) 660 if (m_frames.Count == 0)
635 { 661 {
636 GetNextList(); 662 lock (m_frames)
637
638 if (m_frames.Count == 0)
639 { 663 {
640 Done(); 664 GetNextList();
641 Scene scene = m_group.Scene;
642 665
643 IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>(); 666 if (m_frames.Count == 0)
644 foreach (IScriptModule m in scriptModules)
645 { 667 {
646 if (m == null) 668 Done();
647 continue; 669 Scene scene = m_group.Scene;
648 m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
649 }
650 670
651 return; 671 IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
652 } 672 foreach (IScriptModule m in scriptModules)
673 {
674 if (m == null)
675 continue;
676 m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
677 }
653 678
654 m_currentFrame = m_frames[0]; 679 return;
655 m_currentFrame.TimeMS += (int)tickDuration; 680 }
656 681
682 m_currentFrame = m_frames[0];
683 m_currentFrame.TimeMS += (int)tickDuration;
684 }
657 //force a update on a keyframe transition 685 //force a update on a keyframe transition
658 update = true; 686 update = true;
659 } 687 }
@@ -662,7 +690,7 @@ namespace OpenSim.Region.Framework.Scenes
662 690
663 // Do the frame processing 691 // Do the frame processing
664 double steps = (double)m_currentFrame.TimeMS / tickDuration; 692 double steps = (double)m_currentFrame.TimeMS / tickDuration;
665 693
666 if (steps <= 0.0) 694 if (steps <= 0.0)
667 { 695 {
668 m_group.RootPart.Velocity = Vector3.Zero; 696 m_group.RootPart.Velocity = Vector3.Zero;
@@ -675,9 +703,13 @@ namespace OpenSim.Region.Framework.Scenes
675 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); 703 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
676 704
677 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 705 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
678 m_frames.RemoveAt(0); 706
679 if (m_frames.Count > 0) 707 lock (m_frames)
680 m_currentFrame = m_frames[0]; 708 {
709 m_frames.RemoveAt(0);
710 if (m_frames.Count > 0)
711 m_currentFrame = m_frames[0];
712 }
681 713
682 update = true; 714 update = true;
683 } 715 }
@@ -693,7 +725,6 @@ namespace OpenSim.Region.Framework.Scenes
693 { 725 {
694 // m_group.AbsolutePosition += motionThisFrame; 726 // m_group.AbsolutePosition += motionThisFrame;
695 m_nextPosition = m_group.AbsolutePosition + motionThisFrame; 727 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
696 m_group.AbsolutePosition = m_nextPosition;
697 728
698 //m_group.RootPart.Velocity = v; 729 //m_group.RootPart.Velocity = v;
699 update = true; 730 update = true;
@@ -705,43 +736,43 @@ namespace OpenSim.Region.Framework.Scenes
705 736
706 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); 737 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
707 step.Normalize(); 738 step.Normalize();
708/* use simpler change detection 739 /* use simpler change detection
709* float angle = 0; 740 * float angle = 0;
710 741
711 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 742 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
712 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 743 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
713 float aa_bb = aa * bb; 744 float aa_bb = aa * bb;
714 745
715 if (aa_bb == 0) 746 if (aa_bb == 0)
716 { 747 {
717 angle = 0; 748 angle = 0;
718 } 749 }
719 else 750 else
720 { 751 {
721 float ab = current.X * step.X + 752 float ab = current.X * step.X +
722 current.Y * step.Y + 753 current.Y * step.Y +
723 current.Z * step.Z + 754 current.Z * step.Z +
724 current.W * step.W; 755 current.W * step.W;
725 float q = (ab * ab) / aa_bb; 756 float q = (ab * ab) / aa_bb;
726 757
727 if (q > 1.0f) 758 if (q > 1.0f)
728 { 759 {
729 angle = 0; 760 angle = 0;
730 } 761 }
731 else 762 else
732 { 763 {
733 angle = (float)Math.Acos(2 * q - 1); 764 angle = (float)Math.Acos(2 * q - 1);
734 } 765 }
735 } 766 }
736 767
737 if (angle > 0.01f) 768 if (angle > 0.01f)
738*/ 769 */
739 if (Math.Abs(step.X - current.X) > 0.001f 770 if (Math.Abs(step.X - current.X) > 0.001f
740 || Math.Abs(step.Y - current.Y) > 0.001f 771 || Math.Abs(step.Y - current.Y) > 0.001f
741 || Math.Abs(step.Z - current.Z) > 0.001f) 772 || Math.Abs(step.Z - current.Z) > 0.001f)
742 // assuming w is a dependente var 773 // assuming w is a dependente var
743 { 774 {
744// m_group.UpdateGroupRotationR(step); 775 // m_group.UpdateGroupRotationR(step);
745 m_group.RootPart.RotationOffset = step; 776 m_group.RootPart.RotationOffset = step;
746 777
747 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); 778 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
@@ -752,6 +783,7 @@ namespace OpenSim.Region.Framework.Scenes
752 783
753 if (update) 784 if (update)
754 { 785 {
786 m_group.AbsolutePosition = m_nextPosition;
755 m_group.SendGroupRootTerseUpdate(); 787 m_group.SendGroupRootTerseUpdate();
756 } 788 }
757 } 789 }
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index ddae073..c0405ad 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -91,6 +91,11 @@ namespace OpenSim.Region.Framework.Scenes
91 return 0; 91 return 0;
92 92
93 uint priority; 93 uint priority;
94
95
96 // HACK
97 return GetPriorityByBestAvatarResponsiveness(client, entity);
98
94 99
95 switch (m_scene.UpdatePrioritizationScheme) 100 switch (m_scene.UpdatePrioritizationScheme)
96 { 101 {
@@ -157,30 +162,31 @@ namespace OpenSim.Region.Framework.Scenes
157 162
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 163 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 164 {
160 uint pqueue = ComputeDistancePriority(client,entity,false); 165 uint pqueue = 2; // keep compiler happy
161 166
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 167 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 168 if (presence != null)
164 { 169 {
165 if (!presence.IsChildAgent) 170 // All avatars other than our own go into pqueue 1
171 if (entity is ScenePresence)
172 return 1;
173
174 if (entity is SceneObjectPart)
166 { 175 {
167 // All avatars other than our own go into pqueue 1 176 // Attachments are high priority,
168 if (entity is ScenePresence) 177 if (((SceneObjectPart)entity).ParentGroup.IsAttachment)
169 return 1; 178 return 2;
170 179
171 if (entity is SceneObjectPart) 180 pqueue = ComputeDistancePriority(client, entity, false);
172 { 181
173 // Attachments are high priority, 182 // Non physical prims are lower priority than physical prims
174 if (((SceneObjectPart)entity).ParentGroup.IsAttachment) 183 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
175 return 1; 184 if (physActor == null || !physActor.IsPhysical)
176 185 pqueue++;
177 // Non physical prims are lower priority than physical prims
178 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
179 if (physActor == null || !physActor.IsPhysical)
180 pqueue++;
181 }
182 } 186 }
183 } 187 }
188 else
189 pqueue = ComputeDistancePriority(client, entity, false);
184 190
185 return pqueue; 191 return pqueue;
186 } 192 }
@@ -227,16 +233,28 @@ namespace OpenSim.Region.Framework.Scenes
227 233
228 // And convert the distance to a priority queue, this computation gives queues 234 // And convert the distance to a priority queue, this computation gives queues
229 // at 10, 20, 40, 80, 160, 320, 640, and 1280m 235 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
230 uint pqueue = PriorityQueue.NumberOfImmediateQueues; 236 uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue
231 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; 237 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
232 238/*
233 for (int i = 0; i < queues - 1; i++) 239 for (int i = 0; i < queues - 1; i++)
234 { 240 {
235 if (distance < 30 * Math.Pow(2.0,i)) 241 if (distance < 30 * Math.Pow(2.0,i))
236 break; 242 break;
237 pqueue++; 243 pqueue++;
238 } 244 }
239 245*/
246 if (distance > 10f)
247 {
248 float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f;
249 // for a map identical to original:
250 // now
251 // 1st constant is 1/(log(2)) (natural log) so we get log2(distance)
252 // 2st constant makes it be log2(distance/10)
253 pqueue += (uint)tmp;
254 if (pqueue > queues - 1)
255 pqueue = queues - 1;
256 }
257
240 // If this is a root agent, then determine front & back 258 // If this is a root agent, then determine front & back
241 // Bump up the priority queue (drop the priority) for any objects behind the avatar 259 // Bump up the priority queue (drop the priority) for any objects behind the avatar
242 if (useFrontBack && ! presence.IsChildAgent) 260 if (useFrontBack && ! presence.IsChildAgent)
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..f5be7a7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -1,575 +1,593 @@
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 public uint AllocatePresenceLocalId()
300 /// Add a region-module to this scene. TODO: This will replace AddModule in the future. 300 {
301 /// </summary> 301 uint myID;
302 /// <param name="name"></param> 302
303 /// <param name="module"></param> 303 _primAllocateMutex.WaitOne();
304 public void AddRegionModule(string name, IRegionModuleBase module) 304 myID = ++m_lastAllocatedLocalId;
305 { 305 ++m_lastAllocatedLocalId;
306 if (!RegionModules.ContainsKey(name)) 306 _primAllocateMutex.ReleaseMutex();
307 { 307
308 RegionModules.Add(name, module); 308 return myID;
309 } 309 }
310 } 310
311 311 #region Module Methods
312 public void RemoveRegionModule(string name) 312
313 { 313 /// <summary>
314 RegionModules.Remove(name); 314 /// Add a region-module to this scene. TODO: This will replace AddModule in the future.
315 } 315 /// </summary>
316 316 /// <param name="name"></param>
317 /// <summary> 317 /// <param name="module"></param>
318 /// Register a module commander. 318 public void AddRegionModule(string name, IRegionModuleBase module)
319 /// </summary> 319 {
320 /// <param name="commander"></param> 320 if (!RegionModules.ContainsKey(name))
321 public void RegisterModuleCommander(ICommander commander) 321 {
322 { 322 RegionModules.Add(name, module);
323 lock (m_moduleCommanders) 323 }
324 { 324 }
325 m_moduleCommanders.Add(commander.Name, commander); 325
326 } 326 public void RemoveRegionModule(string name)
327 } 327 {
328 328 RegionModules.Remove(name);
329 /// <summary> 329 }
330 /// Unregister a module commander and all its commands 330
331 /// </summary> 331 /// <summary>
332 /// <param name="name"></param> 332 /// Register a module commander.
333 public void UnregisterModuleCommander(string name) 333 /// </summary>
334 { 334 /// <param name="commander"></param>
335 lock (m_moduleCommanders) 335 public void RegisterModuleCommander(ICommander commander)
336 { 336 {
337 ICommander commander; 337 lock (m_moduleCommanders)
338 if (m_moduleCommanders.TryGetValue(name, out commander)) 338 {
339 m_moduleCommanders.Remove(name); 339 m_moduleCommanders.Add(commander.Name, commander);
340 } 340 }
341 } 341 }
342 342
343 /// <summary> 343 /// <summary>
344 /// Get a module commander 344 /// Unregister a module commander and all its commands
345 /// </summary> 345 /// </summary>
346 /// <param name="name"></param> 346 /// <param name="name"></param>
347 /// <returns>The module commander, null if no module commander with that name was found</returns> 347 public void UnregisterModuleCommander(string name)
348 public ICommander GetCommander(string name) 348 {
349 { 349 lock (m_moduleCommanders)
350 lock (m_moduleCommanders) 350 {
351 { 351 ICommander commander;
352 if (m_moduleCommanders.ContainsKey(name)) 352 if (m_moduleCommanders.TryGetValue(name, out commander))
353 return m_moduleCommanders[name]; 353 m_moduleCommanders.Remove(name);
354 } 354 }
355 355 }
356 return null; 356
357 } 357 /// <summary>
358 358 /// Get a module commander
359 public Dictionary<string, ICommander> GetCommanders() 359 /// </summary>
360 { 360 /// <param name="name"></param>
361 return m_moduleCommanders; 361 /// <returns>The module commander, null if no module commander with that name was found</returns>
362 } 362 public ICommander GetCommander(string name)
363 363 {
364 /// <summary> 364 lock (m_moduleCommanders)
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 if (m_moduleCommanders.ContainsKey(name))
367 /// (is this the best behaviour?) 367 return m_moduleCommanders[name];
368 /// </summary> 368 }
369 /// <param name="mod"></param> 369
370 public void RegisterModuleInterface<M>(M mod) 370 return null;
371 { 371 }
372// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); 372
373 373 public Dictionary<string, ICommander> GetCommanders()
374 List<Object> l = null; 374 {
375 if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) 375 return m_moduleCommanders;
376 { 376 }
377 l = new List<Object>(); 377
378 ModuleInterfaces.Add(typeof(M), l); 378 /// <summary>
379 } 379 /// Register an interface to a region module. This allows module methods to be called directly as
380 380 /// well as via events. If there is already a module registered for this interface, it is not replaced
381 if (l.Count > 0) 381 /// (is this the best behaviour?)
382 return; 382 /// </summary>
383 383 /// <param name="mod"></param>
384 l.Add(mod); 384 public void RegisterModuleInterface<M>(M mod)
385 385 {
386 if (mod is IEntityCreator) 386// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M));
387 { 387
388 IEntityCreator entityCreator = (IEntityCreator)mod; 388 List<Object> l = null;
389 foreach (PCode pcode in entityCreator.CreationCapabilities) 389 if (!ModuleInterfaces.TryGetValue(typeof(M), out l))
390 { 390 {
391 m_entityCreators[pcode] = entityCreator; 391 l = new List<Object>();
392 } 392 ModuleInterfaces.Add(typeof(M), l);
393 } 393 }
394 } 394
395 395 if (l.Count > 0)
396 public void UnregisterModuleInterface<M>(M mod) 396 return;
397 { 397
398 List<Object> l; 398 l.Add(mod);
399 if (ModuleInterfaces.TryGetValue(typeof(M), out l)) 399
400 { 400 if (mod is IEntityCreator)
401 if (l.Remove(mod)) 401 {
402 { 402 IEntityCreator entityCreator = (IEntityCreator)mod;
403 if (mod is IEntityCreator) 403 foreach (PCode pcode in entityCreator.CreationCapabilities)
404 { 404 {
405 IEntityCreator entityCreator = (IEntityCreator)mod; 405 m_entityCreators[pcode] = entityCreator;
406 foreach (PCode pcode in entityCreator.CreationCapabilities) 406 }
407 { 407 }
408 m_entityCreators[pcode] = null; 408 }
409 } 409
410 } 410 public void UnregisterModuleInterface<M>(M mod)
411 } 411 {
412 } 412 List<Object> l;
413 } 413 if (ModuleInterfaces.TryGetValue(typeof(M), out l))
414 414 {
415 public void StackModuleInterface<M>(M mod) 415 if (l.Remove(mod))
416 { 416 {
417 List<Object> l; 417 if (mod is IEntityCreator)
418 if (ModuleInterfaces.ContainsKey(typeof(M))) 418 {
419 l = ModuleInterfaces[typeof(M)]; 419 IEntityCreator entityCreator = (IEntityCreator)mod;
420 else 420 foreach (PCode pcode in entityCreator.CreationCapabilities)
421 l = new List<Object>(); 421 {
422 422 m_entityCreators[pcode] = null;
423 if (l.Contains(mod)) 423 }
424 return; 424 }
425 425 }
426 l.Add(mod); 426 }
427 427 }
428 if (mod is IEntityCreator) 428
429 { 429 public void StackModuleInterface<M>(M mod)
430 IEntityCreator entityCreator = (IEntityCreator)mod; 430 {
431 foreach (PCode pcode in entityCreator.CreationCapabilities) 431 List<Object> l;
432 { 432 if (ModuleInterfaces.ContainsKey(typeof(M)))
433 m_entityCreators[pcode] = entityCreator; 433 l = ModuleInterfaces[typeof(M)];
434 } 434 else
435 } 435 l = new List<Object>();
436 436
437 ModuleInterfaces[typeof(M)] = l; 437 if (l.Contains(mod))
438 } 438 return;
439 439
440 /// <summary> 440 l.Add(mod);
441 /// For the given interface, retrieve the region module which implements it. 441
442 /// </summary> 442 if (mod is IEntityCreator)
443 /// <returns>null if there is no registered module implementing that interface</returns> 443 {
444 public T RequestModuleInterface<T>() 444 IEntityCreator entityCreator = (IEntityCreator)mod;
445 { 445 foreach (PCode pcode in entityCreator.CreationCapabilities)
446 if (ModuleInterfaces.ContainsKey(typeof(T)) && 446 {
447 (ModuleInterfaces[typeof(T)].Count > 0)) 447 m_entityCreators[pcode] = entityCreator;
448 return (T)ModuleInterfaces[typeof(T)][0]; 448 }
449 else 449 }
450 return default(T); 450
451 } 451 ModuleInterfaces[typeof(M)] = l;
452 452 }
453 /// <summary> 453
454 /// For the given interface, retrieve an array of region modules that implement it. 454 /// <summary>
455 /// </summary> 455 /// For the given interface, retrieve the region module which implements it.
456 /// <returns>an empty array if there are no registered modules implementing that interface</returns> 456 /// </summary>
457 public T[] RequestModuleInterfaces<T>() 457 /// <returns>null if there is no registered module implementing that interface</returns>
458 { 458 public T RequestModuleInterface<T>()
459 if (ModuleInterfaces.ContainsKey(typeof(T))) 459 {
460 { 460 if (ModuleInterfaces.ContainsKey(typeof(T)) &&
461 List<T> ret = new List<T>(); 461 (ModuleInterfaces[typeof(T)].Count > 0))
462 462 return (T)ModuleInterfaces[typeof(T)][0];
463 foreach (Object o in ModuleInterfaces[typeof(T)]) 463 else
464 ret.Add((T)o); 464 return default(T);
465 return ret.ToArray(); 465 }
466 } 466
467 else 467 /// <summary>
468 { 468 /// For the given interface, retrieve an array of region modules that implement it.
469 return new T[] {}; 469 /// </summary>
470 } 470 /// <returns>an empty array if there are no registered modules implementing that interface</returns>
471 } 471 public T[] RequestModuleInterfaces<T>()
472 472 {
473 #endregion 473 if (ModuleInterfaces.ContainsKey(typeof(T)))
474 474 {
475 /// <summary> 475 List<T> ret = new List<T>();
476 /// Call this from a region module to add a command to the OpenSim console. 476
477 /// </summary> 477 foreach (Object o in ModuleInterfaces[typeof(T)])
478 /// <param name="mod"></param> 478 ret.Add((T)o);
479 /// <param name="command"></param> 479 return ret.ToArray();
480 /// <param name="shorthelp"></param> 480 }
481 /// <param name="longhelp"></param> 481 else
482 /// <param name="callback"></param> 482 {
483 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) 483 return new T[] {};
484 { 484 }
485 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); 485 }
486 } 486
487 487 #endregion
488 /// <summary> 488
489 /// Call this from a region module to add a command to the OpenSim console. 489 /// <summary>
490 /// </summary> 490 /// Call this from a region module to add a command to the OpenSim console.
491 /// <param name="mod"> 491 /// </summary>
492 /// The use of IRegionModuleBase is a cheap trick to get a different method signature, 492 /// <param name="mod"></param>
493 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. 493 /// <param name="command"></param>
494 /// </param> 494 /// <param name="shorthelp"></param>
495 /// <param name="category"> 495 /// <param name="longhelp"></param>
496 /// Category of the command. This is the section under which it will appear when the user asks for help 496 /// <param name="callback"></param>
497 /// </param> 497 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
498 /// <param name="command"></param> 498 {
499 /// <param name="shorthelp"></param> 499 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback);
500 /// <param name="longhelp"></param> 500 }
501 /// <param name="callback"></param> 501
502 public void AddCommand( 502 /// <summary>
503 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) 503 /// Call this from a region module to add a command to the OpenSim console.
504 { 504 /// </summary>
505 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); 505 /// <param name="mod">
506 } 506 /// The use of IRegionModuleBase is a cheap trick to get a different method signature,
507 507 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway.
508 /// <summary> 508 /// </param>
509 /// Call this from a region module to add a command to the OpenSim console. 509 /// <param name="category">
510 /// </summary> 510 /// Category of the command. This is the section under which it will appear when the user asks for help
511 /// <param name="mod"></param> 511 /// </param>
512 /// <param name="command"></param> 512 /// <param name="command"></param>
513 /// <param name="shorthelp"></param> 513 /// <param name="shorthelp"></param>
514 /// <param name="longhelp"></param> 514 /// <param name="longhelp"></param>
515 /// <param name="descriptivehelp"></param> 515 /// <param name="callback"></param>
516 /// <param name="callback"></param> 516 public void AddCommand(
517 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 517 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
518 { 518 {
519 string moduleName = ""; 519 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback);
520 520 }
521 if (module != null) 521
522 moduleName = module.Name; 522 /// <summary>
523 523 /// Call this from a region module to add a command to the OpenSim console.
524 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); 524 /// </summary>
525 } 525 /// <param name="mod"></param>
526 526 /// <param name="command"></param>
527 /// <summary> 527 /// <param name="shorthelp"></param>
528 /// Call this from a region module to add a command to the OpenSim console. 528 /// <param name="longhelp"></param>
529 /// </summary> 529 /// <param name="descriptivehelp"></param>
530 /// <param name="category"> 530 /// <param name="callback"></param>
531 /// Category of the command. This is the section under which it will appear when the user asks for help 531 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
532 /// </param> 532 {
533 /// <param name="mod"></param> 533 string moduleName = "";
534 /// <param name="command"></param> 534
535 /// <param name="shorthelp"></param> 535 if (module != null)
536 /// <param name="longhelp"></param> 536 moduleName = module.Name;
537 /// <param name="descriptivehelp"></param> 537
538 /// <param name="callback"></param> 538 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback);
539 public void AddCommand( 539 }
540 string category, IRegionModuleBase module, string command, 540
541 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 541 /// <summary>
542 { 542 /// Call this from a region module to add a command to the OpenSim console.
543 if (MainConsole.Instance == null) 543 /// </summary>
544 return; 544 /// <param name="category">
545 545 /// Category of the command. This is the section under which it will appear when the user asks for help
546 bool shared = false; 546 /// </param>
547 547 /// <param name="mod"></param>
548 if (module != null) 548 /// <param name="command"></param>
549 shared = module is ISharedRegionModule; 549 /// <param name="shorthelp"></param>
550 550 /// <param name="longhelp"></param>
551 MainConsole.Instance.Commands.AddCommand( 551 /// <param name="descriptivehelp"></param>
552 category, shared, command, shorthelp, longhelp, descriptivehelp, callback); 552 /// <param name="callback"></param>
553 } 553 public void AddCommand(
554 554 string category, IRegionModuleBase module, string command,
555 public virtual ISceneObject DeserializeObject(string representation) 555 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
556 { 556 {
557 return null; 557 if (MainConsole.Instance == null)
558 } 558 return;
559 559
560 public virtual bool AllowScriptCrossings 560 bool shared = false;
561 { 561
562 get { return false; } 562 if (module != null)
563 } 563 shared = module is ISharedRegionModule;
564 564
565 public void Restart() 565 MainConsole.Instance.Commands.AddCommand(
566 { 566 category, shared, command, shorthelp, longhelp, descriptivehelp, callback);
567 // This has to be here to fire the event 567 }
568 restart handlerPhysicsCrash = OnRestart; 568
569 if (handlerPhysicsCrash != null) 569 public virtual ISceneObject DeserializeObject(string representation)
570 handlerPhysicsCrash(RegionInfo); 570 {
571 } 571 return null;
572 572 }
573 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); 573
574 } 574 public virtual bool AllowScriptCrossings
575} 575 {
576 get { return false; }
577 }
578
579 public virtual void Start()
580 {
581 }
582
583 public void Restart()
584 {
585 // This has to be here to fire the event
586 restart handlerPhysicsCrash = OnRestart;
587 if (handlerPhysicsCrash != null)
588 handlerPhysicsCrash(RegionInfo);
589 }
590
591 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
592 }
593}
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..73283ed 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;
113 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 }
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
@@ -380,11 +530,8 @@ namespace OpenSim.Region.Framework.Scenes
380 get 530 get
381 { 531 {
382 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 532 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
383 533 a.Normalize();
384 if (a == Vector3.Zero) 534 return a;
385 return a;
386
387 return Util.GetNormalizedVector(a);
388 } 535 }
389 } 536 }
390 #endregion 537 #endregion
@@ -424,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes
424 } 571 }
425 } 572 }
426 573
574
427 public byte State { get; set; } 575 public byte State { get; set; }
428 576
429 private AgentManager.ControlFlags m_AgentControlFlags; 577 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -462,6 +610,7 @@ namespace OpenSim.Region.Framework.Scenes
462 } 610 }
463 else 611 else
464 { 612 {
613// 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. 614 // Obtain the correct position of a seated avatar.
466 // In addition to providing the correct position while 615 // In addition to providing the correct position while
467 // the avatar is seated, this value will also 616 // the avatar is seated, this value will also
@@ -475,17 +624,21 @@ namespace OpenSim.Region.Framework.Scenes
475 // in the sim unless the avatar is on a sit target. While 624 // in the sim unless the avatar is on a sit target. While
476 // on a sit target, m_pos will contain the desired offset 625 // on a sit target, m_pos will contain the desired offset
477 // without the parent rotation applied. 626 // without the parent rotation applied.
478 SceneObjectPart sitPart = ParentPart; 627 if (ParentPart != null)
479 628 {
480 if (sitPart != null) 629 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
481 return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 630 // if (sitPart != null)
631 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
632 if (rootPart != null)
633 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
634 }
482 } 635 }
483 636
484 return m_pos; 637 return m_pos;
485 } 638 }
486 set 639 set
487 { 640 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 641// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
489// Util.PrintCallStack(); 642// Util.PrintCallStack();
490 643
491 if (PhysicsActor != null) 644 if (PhysicsActor != null)
@@ -502,10 +655,7 @@ namespace OpenSim.Region.Framework.Scenes
502 655
503 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 656 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
504 if (ParentID == 0) 657 if (ParentID == 0)
505 {
506 m_pos = value; 658 m_pos = value;
507// ParentPosition = Vector3.Zero;
508 }
509 659
510 //m_log.DebugFormat( 660 //m_log.DebugFormat(
511 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 661 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -768,6 +918,14 @@ namespace OpenSim.Region.Framework.Scenes
768 set { m_speedModifier = value; } 918 set { m_speedModifier = value; }
769 } 919 }
770 920
921 /// <summary>
922 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
923 /// </summary>
924 /// <remarks>
925 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
926 /// </remarks>
927 private float AgentControlStopSlowWhilstMoving = 0.5f;
928
771 private bool m_forceFly; 929 private bool m_forceFly;
772 930
773 public bool ForceFly 931 public bool ForceFly
@@ -795,7 +953,7 @@ namespace OpenSim.Region.Framework.Scenes
795 953
796 public ScenePresence( 954 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 955 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 956 {
799 AttachmentsSyncLock = new Object(); 957 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 958 AllowMovement = true;
801 IsChildAgent = true; 959 IsChildAgent = true;
@@ -811,7 +969,7 @@ namespace OpenSim.Region.Framework.Scenes
811 m_name = String.Format("{0} {1}", Firstname, Lastname); 969 m_name = String.Format("{0} {1}", Firstname, Lastname);
812 m_scene = world; 970 m_scene = world;
813 m_uuid = client.AgentId; 971 m_uuid = client.AgentId;
814 LocalId = m_scene.AllocateLocalId(); 972 LocalId = m_scene.AllocatePresenceLocalId();
815 973
816 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 974 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
817 if (account != null) 975 if (account != null)
@@ -824,7 +982,7 @@ namespace OpenSim.Region.Framework.Scenes
824 982
825 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 983 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
826 if (gm != null) 984 if (gm != null)
827 Grouptitle = gm.GetGroupTitle(m_uuid); 985 Grouptitle = gm.GetGroupTitle(m_uuid);
828 986
829 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 987 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
830 988
@@ -841,6 +999,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 999 SetDirectionVectors();
842 1000
843 Appearance = appearance; 1001 Appearance = appearance;
1002
1003 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 1004 }
845 1005
846 private void RegionHeartbeatEnd(Scene scene) 1006 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +1034,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 1034 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 1035 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 1036 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
1037 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 1038 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 1039 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1040 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -927,6 +1088,7 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <summary> 1088 /// <summary>
928 /// Turns a child agent into a root agent. 1089 /// Turns a child agent into a root agent.
929 /// </summary> 1090 /// </summary>
1091 /// <remarks>
930 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 1092 /// 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. 1093 /// 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, 1094 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -934,48 +1096,56 @@ namespace OpenSim.Region.Framework.Scenes
934 /// 1096 ///
935 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1097 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
936 /// delays that crossing. 1098 /// delays that crossing.
937 /// </summary> 1099 /// </remarks>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 1100
939 {
940 m_log.DebugFormat(
941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName);
943 1101
944 if (ParentUUID != UUID.Zero) 1102 // only in use as part of completemovement
1103 // other uses need fix
1104 private bool MakeRootAgent(Vector3 pos, bool isFlying)
1105 {
1106 lock (m_completeMovementLock)
945 { 1107 {
946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1108 if (!IsChildAgent)
947 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1109 return false;
948 if (part == null) 1110
1111 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1112
1113 // m_log.InfoFormat(
1114 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1115 // Name, m_scene.RegionInfo.RegionName);
1116
1117 if (ParentUUID != UUID.Zero)
949 { 1118 {
950 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1119 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1120 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1121 if (part == null)
1122 {
1123 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1124 }
1125 else
1126 {
1127 part.ParentGroup.AddAvatar(UUID);
1128 if (part.SitTargetPosition != Vector3.Zero)
1129 part.SitTargetAvatar = UUID;
1130 ParentID = part.LocalId;
1131 ParentPart = part;
1132 m_pos = PrevSitOffset;
1133 pos = part.GetWorldPosition();
1134 }
1135 ParentUUID = UUID.Zero;
951 } 1136 }
952 else 1137 else
953 { 1138 {
954 part.ParentGroup.AddAvatar(UUID); 1139 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 } 1140 }
964 ParentUUID = UUID.Zero;
965 1141
966 IsChildAgent = false; 1142 IsChildAgent = false;
967
968// Animator.TrySetMovementAnimation("SIT");
969 }
970 else
971 {
972 IsChildAgent = false;
973 IsLoggingIn = false;
974 } 1143 }
975 1144
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1145 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
977 1146 // set and prevent the close of the connection on a subsequent re-teleport.
978 IsChildAgent = false; 1147 // Should not be needed if we are not trying to tell this region to close
1148 // DoNotCloseAfterTeleport = false;
979 1149
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1150 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1151 if (gm != null)
@@ -985,39 +1155,45 @@ namespace OpenSim.Region.Framework.Scenes
985 1155
986 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1156 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
987 1157
1158/* this should be done by groups module on TriggerOnMakeRootAgent(this) below
1159 at least XmlIRpcGroups
988 UUID groupUUID = UUID.Zero; 1160 UUID groupUUID = UUID.Zero;
989 string GroupName = string.Empty; 1161 string GroupName = string.Empty;
990 ulong groupPowers = 0; 1162 ulong groupPowers = 0;
991 1163
992 // ----------------------------------
993 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
994 try
995 {
996 if (gm != null)
997 {
998 groupUUID = ControllingClient.ActiveGroupId;
999 GroupRecord record = gm.GetGroupRecord(groupUUID);
1000 if (record != null)
1001 GroupName = record.GroupName;
1002 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1003 if (groupMembershipData != null)
1004 groupPowers = groupMembershipData.GroupPowers;
1005 }
1006 ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName,
1007 Grouptitle);
1008 }
1009 catch (Exception e)
1010 {
1011 m_log.Debug("[AGENTUPDATE]: " + e.ToString());
1012 }
1013 // ------------------------------------
1014 1164
1165
1166
1167 // ----------------------------------
1168 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
1169 try
1170 {
1171
1172 if (gm != null)
1173 {
1174 groupUUID = ControllingClient.ActiveGroupId;
1175 GroupRecord record = gm.GetGroupRecord(groupUUID);
1176 if (record != null)
1177 GroupName = record.GroupName;
1178 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1179 if (groupMembershipData != null)
1180 groupPowers = groupMembershipData.GroupPowers;
1181 }
1182 ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName,
1183 Grouptitle);
1184 }
1185 catch (Exception e)
1186 {
1187 m_log.Debug("[AGENTUPDATE]: " + e.ToString());
1188 }
1189 // ------------------------------------
1190*/
1015 if (ParentID == 0) 1191 if (ParentID == 0)
1016 { 1192 {
1017 // Moved this from SendInitialData to ensure that Appearance is initialized 1193 // Moved this from SendInitialData to ensure that Appearance is initialized
1018 // before the inventory is processed in MakeRootAgent. This fixes a race condition 1194 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1019 // related to the handling of attachments 1195 // related to the handling of attachments
1020 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); 1196
1021 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1197 if (m_scene.TestBorderCross(pos, Cardinals.E))
1022 { 1198 {
1023 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1199 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
@@ -1051,7 +1227,7 @@ namespace OpenSim.Region.Framework.Scenes
1051 1227
1052 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1228 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
1053 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1229 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1054 1230
1055 float newPosZ = posZLimit + localAVHeight / 2; 1231 float newPosZ = posZLimit + localAVHeight / 2;
1056 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1232 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1057 { 1233 {
@@ -1096,6 +1272,7 @@ namespace OpenSim.Region.Framework.Scenes
1096 // and it has already rezzed the attachments and started their scripts. 1272 // and it has already rezzed the attachments and started their scripts.
1097 // We do the following only for non-login agents, because their scripts 1273 // We do the following only for non-login agents, because their scripts
1098 // haven't started yet. 1274 // haven't started yet.
1275/* moved down
1099 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0) 1276 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1100 { 1277 {
1101 // Viewers which have a current outfit folder will actually rez their own attachments. However, 1278 // Viewers which have a current outfit folder will actually rez their own attachments. However,
@@ -1111,31 +1288,50 @@ namespace OpenSim.Region.Framework.Scenes
1111 }); 1288 });
1112 } 1289 }
1113 else 1290 else
1291
1114 { 1292 {
1115 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT 1293 // 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 1294 // 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 1295 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data. 1296 // not transporting the required data.
1119 lock (m_attachments) 1297 //
1298 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1299 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1300 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1301 // not transporting the required data.
1302 //
1303 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1304 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1305 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1306 //
1307 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1308 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1309 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1310 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1311 //
1312 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1313 // be locked, allowing race conditions if other code changes the attachments list.
1314
1315 List<SceneObjectGroup> attachments = GetAttachments();
1316
1317 if (attachments.Count > 0)
1120 { 1318 {
1121 if (HasAttachments()) 1319 m_log.DebugFormat(
1122 { 1320 "[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 1321
1126 // Resume scripts 1322 // Resume scripts this possible should also be moved down after sending the avatar to viewer ?
1127 Util.FireAndForget(delegate(object x) { 1323 foreach (SceneObjectGroup sog in attachments)
1128 foreach (SceneObjectGroup sog in m_attachments) 1324 {
1129 { 1325// sending attachments before the avatar ?
1130 sog.ScheduleGroupForFullUpdate(); 1326// moved to completemovement where it already was
1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1327// sog.ScheduleGroupForFullUpdate();
1132 sog.ResumeScripts(); 1328 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1133 } 1329 sog.ResumeScripts();
1134 });
1135 } 1330 }
1136 } 1331 }
1137 } 1332 }
1138 1333*/
1334/*
1139 SendAvatarDataToAllAgents(); 1335 SendAvatarDataToAllAgents();
1140 1336
1141 // send the animations of the other presences to me 1337 // send the animations of the other presences to me
@@ -1144,6 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 if (presence != this) 1340 if (presence != this)
1145 presence.Animator.SendAnimPackToClient(ControllingClient); 1341 presence.Animator.SendAnimPackToClient(ControllingClient);
1146 }); 1342 });
1343*/
1147 1344
1148 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1345 // 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 1346 // stall on the border crossing since the existing child agent will still have the last movement
@@ -1153,7 +1350,7 @@ namespace OpenSim.Region.Framework.Scenes
1153 1350
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1351 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1155 1352
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1353 return true;
1157 } 1354 }
1158 1355
1159 public int GetStateSource() 1356 public int GetStateSource()
@@ -1185,6 +1382,11 @@ namespace OpenSim.Region.Framework.Scenes
1185 1382
1186 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1383 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
1187 1384
1385 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1386 // from the source simulator has completed on a V2 teleport.
1387 lock (m_originRegionIDAccessLock)
1388 m_originRegionID = UUID.Zero;
1389
1188 // Reset these so that teleporting in and walking out isn't seen 1390 // Reset these so that teleporting in and walking out isn't seen
1189 // as teleporting back 1391 // as teleporting back
1190 TeleportFlags = TeleportFlags.Default; 1392 TeleportFlags = TeleportFlags.Default;
@@ -1198,7 +1400,7 @@ namespace OpenSim.Region.Framework.Scenes
1198 else 1400 else
1199 Animator.ResetAnimations(); 1401 Animator.ResetAnimations();
1200 1402
1201 1403
1202// m_log.DebugFormat( 1404// m_log.DebugFormat(
1203// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1405// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1204// Name, UUID, m_scene.RegionInfo.RegionName); 1406// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1306,7 +1508,29 @@ namespace OpenSim.Region.Framework.Scenes
1306 1508
1307 public void StopFlying() 1509 public void StopFlying()
1308 { 1510 {
1309 ControllingClient.StopFlying(this); 1511 if (IsInTransit)
1512 return;
1513
1514 Vector3 pos = AbsolutePosition;
1515 if (Appearance.AvatarHeight != 127.0f)
1516 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1517 else
1518 pos += new Vector3(0f, 0f, (1.56f / 6f));
1519
1520 AbsolutePosition = pos;
1521
1522 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1523 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1524 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1525 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1526
1527 // why are we still testing for this really old height value default???
1528 if (Appearance.AvatarHeight != 127.0f)
1529 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1530 else
1531 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1532
1533 SendAgentTerseUpdate(this);
1310 } 1534 }
1311 1535
1312 /// <summary> 1536 /// <summary>
@@ -1426,6 +1650,14 @@ namespace OpenSim.Region.Framework.Scenes
1426 } 1650 }
1427 } 1651 }
1428 1652
1653 public void DropThisRootRegionFromNeighbours()
1654 {
1655 ulong handle = m_scene.RegionInfo.RegionHandle;
1656 RemoveNeighbourRegion(handle);
1657 Scene.CapsModule.DropChildSeed(UUID, handle);
1658 }
1659
1660
1429 public Dictionary<ulong, string> KnownRegions 1661 public Dictionary<ulong, string> KnownRegions
1430 { 1662 {
1431 get 1663 get
@@ -1480,6 +1712,37 @@ namespace OpenSim.Region.Framework.Scenes
1480 1712
1481 } 1713 }
1482 1714
1715 private bool WaitForUpdateAgent(IClientAPI client)
1716 {
1717 // Before the source region executes UpdateAgent
1718 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1719 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1720 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1721 int count = 50;
1722 UUID originID;
1723
1724 lock (m_originRegionIDAccessLock)
1725 originID = m_originRegionID;
1726
1727 while (originID.Equals(UUID.Zero) && count-- > 0)
1728 {
1729 lock (m_originRegionIDAccessLock)
1730 originID = m_originRegionID;
1731
1732 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1733 Thread.Sleep(200);
1734 }
1735
1736 if (originID.Equals(UUID.Zero))
1737 {
1738 // Movement into region will fail
1739 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1740 return false;
1741 }
1742
1743 return true;
1744 }
1745
1483 /// <summary> 1746 /// <summary>
1484 /// Complete Avatar's movement into the region. 1747 /// Complete Avatar's movement into the region.
1485 /// </summary> 1748 /// </summary>
@@ -1491,53 +1754,108 @@ namespace OpenSim.Region.Framework.Scenes
1491 /// </param> 1754 /// </param>
1492 public void CompleteMovement(IClientAPI client, bool openChildAgents) 1755 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1493 { 1756 {
1494// DateTime startTime = DateTime.Now; 1757 int ts = Util.EnvironmentTickCount();
1495 1758
1496 m_log.DebugFormat( 1759 m_log.InfoFormat(
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1760 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1761 client.Name, Scene.Name, AbsolutePosition);
1762
1763 m_inTransit = true;
1764 bool newhide = false;
1765 try
1766 {
1767 // Make sure it's not a login agent. We don't want to wait for updates during login
1768 if (!isNPC && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1769 {
1499 1770
1500 Vector3 look = Velocity; 1771 // Let's wait until UpdateAgent (called by departing region) is done
1772 if (!WaitForUpdateAgent(client))
1773 // The sending region never sent the UpdateAgent data, we have to refuse
1774 return;
1775 }
1501 1776
1502 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1777 // Prevent teleporting to an underground location
1503 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) 1778 // (may crash client otherwise)
1504 { 1779 //
1505 look = new Vector3(0.99f, 0.042f, 0);
1506 }
1507 1780
1508 // Prevent teleporting to an underground location 1781/* this is done in MakeRootAgent
1509 // (may crash client otherwise) 1782 Vector3 pos = AbsolutePosition;
1510 // 1783 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1511 Vector3 pos = AbsolutePosition; 1784 if (pos.Z < ground + 1.5f)
1512 float ground = m_scene.GetGroundHeight(pos.X, pos.Y); 1785 {
1513 if (pos.Z < ground + 1.5f) 1786 pos.Z = ground + 1.5f;
1514 { 1787 AbsolutePosition = pos;
1515 pos.Z = ground + 1.5f; 1788 }
1516 AbsolutePosition = pos; 1789*/
1517 }
1518 1790
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1791 m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1520 MakeRootAgent(AbsolutePosition, flying);
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1522 1792
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1793 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1794 if (!MakeRootAgent(AbsolutePosition, flying))
1795 {
1796 m_log.DebugFormat(
1797 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1798 Name, Scene.Name);
1524 1799
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1800 return;
1526 { 1801 }
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 1802
1534 m_log.DebugFormat( 1803 m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1535 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1536 client.Name, client.AgentId, m_callbackURI);
1537 1804
1538 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1805 Vector3 look = Lookat;
1539 m_callbackURI = null; 1806 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1540 } 1807 {
1808 look = Velocity;
1809 look.Z = 0;
1810 look.Normalize();
1811 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1812 look = new Vector3(0.99f, 0.042f, 0);
1813 }
1814
1815 if (!IsChildAgent)
1816 {
1817 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
1818 if (cof == null)
1819 COF = UUID.Zero;
1820 else
1821 COF = cof.ID;
1822
1823 m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1824 }
1825
1826 // Tell the client that we're totally ready
1827 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1828
1829 // Remember in HandleUseCircuitCode, we delayed this to here
1830// this prims etc, moved down
1831// if (m_teleportFlags > 0)
1832// SendInitialDataToMe();
1833
1834 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1835
1836 m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1837
1838 if (!string.IsNullOrEmpty(m_callbackURI))
1839 {
1840 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1841 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1842 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1843 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1844 // region as the current region, meaning that a close sent before then will fail the teleport.
1845 // System.Threading.Thread.Sleep(2000);
1846
1847 m_log.DebugFormat(
1848 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1849 client.Name, client.AgentId, m_callbackURI);
1850
1851 UUID originID;
1852
1853 lock (m_originRegionIDAccessLock)
1854 originID = m_originRegionID;
1855
1856 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1857 m_callbackURI = null;
1858 }
1541// else 1859// else
1542// { 1860// {
1543// m_log.DebugFormat( 1861// m_log.DebugFormat(
@@ -1545,34 +1863,123 @@ namespace OpenSim.Region.Framework.Scenes
1545// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 1863// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1546// } 1864// }
1547 1865
1548 ValidateAndSendAppearanceAndAgentData(); 1866 m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1549 1867
1550 // Create child agents in neighbouring regions 1868 m_previusParcelHide = false;
1551 if (openChildAgents && !IsChildAgent) 1869 m_previusParcelUUID = UUID.Zero;
1552 { 1870 m_currentParcelHide = false;
1871 m_currentParcelUUID = UUID.Zero;
1553 1872
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1873 // send initial land overlay and parcel
1555 if (m_agentTransfer != null) 1874 ILandChannel landch = m_scene.LandChannel;
1556 m_agentTransfer.EnableChildAgents(this); 1875 if (landch != null)
1876 landch.sendClientInitialLandInfo(client);
1557 1877
1558 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1878 if (!IsChildAgent)
1559 if (friendsModule != null) 1879 {
1560 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1561 1880
1562 } 1881 ValidateAndSendAppearanceAndAgentData();
1563 1882
1564 // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region 1883 m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1565 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. 1884
1566 // This may be due to viewer code or it may be something we're not doing properly simulator side. 1885 // attachments
1567 lock (m_attachments) 1886 if (isNPC || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1887 {
1888 if (Scene.AttachmentsModule != null)
1889// Util.FireAndForget(
1890// o =>
1891// {
1892 Scene.AttachmentsModule.RezAttachments(this);
1893 // });
1894 }
1895 else
1896 {
1897 if (m_attachments.Count > 0)
1898 {
1899 m_log.DebugFormat(
1900 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1901
1902 // Resume scripts this possible should also be moved down after sending the avatar to viewer ?
1903 foreach (SceneObjectGroup sog in m_attachments)
1904 {
1905 sog.SendFullUpdateToClient(ControllingClient);
1906 SendFullUpdateToClient(ControllingClient);
1907
1908 if (!sog.HasPrivateAttachmentPoint)
1909 {
1910 // sog.ScheduleGroupForFullUpdate();
1911 m_scene.ForEachScenePresence(delegate(ScenePresence p)
1912 {
1913 if (p == this)
1914 return;
1915
1916 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1917 return;
1918
1919 p.ControllingClient.SendPartFullUpdate(sog.RootPart,LocalId + 1);
1920 sog.SendFullUpdateToClient(p.ControllingClient);
1921 SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path
1922 });
1923 }
1924
1925 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1926 sog.ResumeScripts();
1927 }
1928 }
1929 }
1930
1931 m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1932
1933 // Create child agents in neighbouring regions
1934 if (openChildAgents)
1935 {
1936 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1937 if (m_agentTransfer != null)
1938 m_agentTransfer.EnableChildAgents(this);
1939 }
1940 }
1941
1942 m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1943
1944 // send the rest of the world
1945 if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
1946 SendInitialDataToMe();
1947
1948 m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1949
1950 if (!IsChildAgent)
1951 {
1952// moved from makeroot missing in sendInitialDataToMe
1953// its already there
1954/*
1955 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1956 {
1957 if (presence != this)
1958 presence.Animator.SendAnimPackToClient(ControllingClient);
1959 });
1960*/
1961 if (openChildAgents)
1962 {
1963 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1964 if (friendsModule != null)
1965 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1966
1967 m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1968 }
1969 }
1970 }
1971 finally
1568 { 1972 {
1569 foreach (SceneObjectGroup sog in m_attachments) 1973 m_inTransit = false;
1570 sog.ScheduleGroupForFullUpdate();
1571 } 1974 }
1975 // if hide force a check
1976 // if (!IsChildAgent && newhide)
1977 // {
1978 // ParcelLoginCheck(m_currentParcelUUID);
1979 // m_currentParcelHide = newhide;
1980 // }
1572 1981
1573// m_log.DebugFormat( 1982 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1576 } 1983 }
1577 1984
1578 /// <summary> 1985 /// <summary>
@@ -1653,9 +2060,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 2060 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 2061 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 2062 {
1656// m_log.DebugFormat( 2063 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 2064 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 2065 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 2066
1660 if (IsChildAgent) 2067 if (IsChildAgent)
1661 { 2068 {
@@ -1663,9 +2070,8 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 2070 return;
1664 } 2071 }
1665 2072
1666 ++m_movementUpdateCount; 2073 if (IsInTransit)
1667 if (m_movementUpdateCount < 1) 2074 return;
1668 m_movementUpdateCount = 1;
1669 2075
1670 #region Sanity Checking 2076 #region Sanity Checking
1671 2077
@@ -1697,21 +2103,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 2103
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 2104 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 2105
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 2106 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 2107 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 2108 // changes, then start using the agent's drawdistance rather than the
@@ -1733,6 +2124,7 @@ namespace OpenSim.Region.Framework.Scenes
1733// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2124// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1734// m_updateCount = UPDATE_COUNT; 2125// m_updateCount = UPDATE_COUNT;
1735 2126
2127
1736 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2128 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1737 { 2129 {
1738 StandUp(); 2130 StandUp();
@@ -1783,9 +2175,16 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 2175 // Here's where you get them.
1784 m_AgentControlFlags = flags; 2176 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 2177 m_headrotation = agentData.HeadRotation;
2178 byte oldState = State;
1786 State = agentData.State; 2179 State = agentData.State;
1787 2180
2181 // We need to send this back to the client in order to stop the edit beams
2182 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2183 SendAgentTerseUpdate(this);
2184
1788 PhysicsActor actor = PhysicsActor; 2185 PhysicsActor actor = PhysicsActor;
2186
2187 // This will be the case if the agent is sitting on the groudn or on an object.
1789 if (actor == null) 2188 if (actor == null)
1790 { 2189 {
1791 SendControlsToScripts(flagsForScripts); 2190 SendControlsToScripts(flagsForScripts);
@@ -1794,12 +2193,11 @@ namespace OpenSim.Region.Framework.Scenes
1794 2193
1795 if (AllowMovement && !SitGround) 2194 if (AllowMovement && !SitGround)
1796 { 2195 {
1797 Quaternion bodyRotation = agentData.BodyRotation; 2196// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1798 bool update_rotation = false; 2197 bool update_rotation = false;
1799 2198 if (agentData.BodyRotation != Rotation)
1800 if (bodyRotation != Rotation)
1801 { 2199 {
1802 Rotation = bodyRotation; 2200 Rotation = agentData.BodyRotation;
1803 update_rotation = true; 2201 update_rotation = true;
1804 } 2202 }
1805 2203
@@ -1845,10 +2243,7 @@ namespace OpenSim.Region.Framework.Scenes
1845 else 2243 else
1846 dirVectors = Dir_Vectors; 2244 dirVectors = Dir_Vectors;
1847 2245
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. 2246 // 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) 2247 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1853 { 2248 {
1854 if (((uint)flags & (uint)DCF) != 0) 2249 if (((uint)flags & (uint)DCF) != 0)
@@ -1865,29 +2260,19 @@ namespace OpenSim.Region.Framework.Scenes
1865 // Why did I get this? 2260 // Why did I get this?
1866 } 2261 }
1867 2262
1868 if ((MovementFlag & (byte)(uint)DCF) == 0) 2263 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive)
1869 { 2264 {
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); 2265 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1877 MovementFlag += (byte)(uint)DCF; 2266 MovementFlag += (uint)DCF;
1878 update_movementflag = true; 2267 update_movementflag = true;
1879 } 2268 }
1880 } 2269 }
1881 else 2270 else
1882 { 2271 {
1883 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2272 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 { 2273 {
1889 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2274 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1890 MovementFlag -= ((byte)(uint)DCF); 2275 MovementFlag -= (uint)DCF;
1891 update_movementflag = true; 2276 update_movementflag = true;
1892 2277
1893 /* 2278 /*
@@ -1907,6 +2292,13 @@ namespace OpenSim.Region.Framework.Scenes
1907 i++; 2292 i++;
1908 } 2293 }
1909 2294
2295 // Detect AGENT_CONTROL_STOP state changes
2296 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2297 {
2298 AgentControlStopActive = !AgentControlStopActive;
2299 update_movementflag = true;
2300 }
2301
1910 if (MovingToTarget) 2302 if (MovingToTarget)
1911 { 2303 {
1912 // If the user has pressed a key then we want to cancel any move to target. 2304 // If the user has pressed a key then we want to cancel any move to target.
@@ -1932,53 +2324,79 @@ namespace OpenSim.Region.Framework.Scenes
1932 // Only do this if we're flying 2324 // Only do this if we're flying
1933 if (Flying && !ForceFly) 2325 if (Flying && !ForceFly)
1934 { 2326 {
1935 // Landing detection code 2327 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1936 2328 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 { 2329 {
1945 ApplyFlyingRoll( 2330 agent_control_v3 = Vector3.Zero;
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 {
1953 ApplyFlyingRoll(
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 } 2331 }
1958 else 2332 else
1959 { 2333 {
1960 if (m_AngularVelocity.Z != 0) 2334 // Landing detection code
1961 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1962 }
1963 2335
1964 if (Flying && IsColliding && controlland) 2336 // Are the landing controls requirements filled?
1965 { 2337 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1966 // nesting this check because LengthSquared() is expensive and we don't 2338 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1967 // want to do it every step when flying. 2339
1968 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2340 //m_log.Debug("[CONTROL]: " +flags);
1969 StopFlying(); 2341 // Applies a satisfying roll effect to the avatar when flying.
2342 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2343 {
2344 ApplyFlyingRoll(
2345 FLY_ROLL_RADIANS_PER_UPDATE,
2346 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2347 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2348 }
2349 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2350 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2351 {
2352 ApplyFlyingRoll(
2353 -FLY_ROLL_RADIANS_PER_UPDATE,
2354 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2355 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2356 }
2357 else
2358 {
2359 if (m_AngularVelocity.Z != 0)
2360 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2361 }
2362
2363 if (Flying && IsColliding && controlland)
2364 {
2365 // nesting this check because LengthSquared() is expensive and we don't
2366 // want to do it every step when flying.
2367 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2368 StopFlying();
2369 }
1970 } 2370 }
1971 } 2371 }
1972 2372
2373// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2374
1973 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2375 // 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 2376 // which occurs later in the main scene loop
1975 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2377 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2378 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2379 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2380 // avatar location in place).
2381 if (update_movementflag
2382 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1976 { 2383 {
1977// m_log.DebugFormat( 2384// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
1978// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 2385// {
1979// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 2386// m_log.DebugFormat(
2387// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2388// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2389// update_movementflag, MovementFlag, update_rotation);
2390
2391 float speedModifier;
1980 2392
1981 AddNewMovement(agent_control_v3); 2393 if (AgentControlStopActive)
2394 speedModifier = AgentControlStopSlowWhilstMoving;
2395 else
2396 speedModifier = 1;
2397
2398 AddNewMovement(agent_control_v3, speedModifier);
2399// }
1982 } 2400 }
1983// else 2401// else
1984// { 2402// {
@@ -1991,15 +2409,86 @@ namespace OpenSim.Region.Framework.Scenes
1991// } 2409// }
1992 2410
1993 if (update_movementflag && ParentID == 0) 2411 if (update_movementflag && ParentID == 0)
2412 {
2413// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1994 Animator.UpdateMovementAnimations(); 2414 Animator.UpdateMovementAnimations();
2415 }
1995 2416
1996 SendControlsToScripts(flagsForScripts); 2417 SendControlsToScripts(flagsForScripts);
1997 } 2418 }
1998 2419
2420 // We need to send this back to the client in order to see the edit beams
2421 if ((State & (uint)AgentState.Editing) != 0)
2422 SendAgentTerseUpdate(this);
2423
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2424 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2425 }
2002 2426
2427
2428 /// <summary>
2429 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2430 /// </summary>
2431 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2432 {
2433 //m_log.DebugFormat(
2434 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2435 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2436
2437 if (IsChildAgent)
2438 {
2439 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2440 return;
2441 }
2442
2443 ++m_movementUpdateCount;
2444 if (m_movementUpdateCount < 1)
2445 m_movementUpdateCount = 1;
2446
2447// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2448
2449 // Camera location in world. We'll need to raytrace
2450 // from this location from time to time.
2451 CameraPosition = agentData.CameraCenter;
2452 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2453 {
2454 ReprioritizeUpdates();
2455 m_lastCameraPosition = CameraPosition;
2456 }
2457
2458 // Use these three vectors to figure out what the agent is looking at
2459 // Convert it to a Matrix and/or Quaternion
2460 CameraAtAxis = agentData.CameraAtAxis;
2461 CameraLeftAxis = agentData.CameraLeftAxis;
2462 CameraUpAxis = agentData.CameraUpAxis;
2463
2464 // The Agent's Draw distance setting
2465 // When we get to the point of re-computing neighbors everytime this
2466 // changes, then start using the agent's drawdistance rather than the
2467 // region's draw distance.
2468 // DrawDistance = agentData.Far;
2469 DrawDistance = Scene.DefaultDrawDistance;
2470
2471 // Check if Client has camera in 'follow cam' or 'build' mode.
2472 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2473
2474 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2475 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2476
2477
2478 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2479 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2480 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2481 {
2482 if (m_followCamAuto)
2483 {
2484 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2485 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2486 }
2487 }
2488
2489 TriggerScenePresenceUpdated();
2490 }
2491
2003 /// <summary> 2492 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2493 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2494 /// </summary>
@@ -2185,6 +2674,8 @@ namespace OpenSim.Region.Framework.Scenes
2185 targetScene = m_scene; 2674 targetScene = m_scene;
2186 2675
2187 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2676 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
2677 // dont try to land underground
2678 terrainHeight += Appearance.AvatarHeight / 2;
2188 pos.Z = Math.Max(terrainHeight, pos.Z); 2679 pos.Z = Math.Max(terrainHeight, pos.Z);
2189 2680
2190 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2681 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2196,10 +2687,11 @@ namespace OpenSim.Region.Framework.Scenes
2196// m_log.DebugFormat( 2687// m_log.DebugFormat(
2197// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2688// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2198// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2689// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2690
2199 2691
2200 if (noFly) 2692 if (noFly)
2201 Flying = false; 2693 Flying = false;
2202 else if (pos.Z > terrainHeight) 2694 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2203 Flying = true; 2695 Flying = true;
2204 2696
2205 LandAtTarget = landAtTarget; 2697 LandAtTarget = landAtTarget;
@@ -2252,17 +2744,13 @@ namespace OpenSim.Region.Framework.Scenes
2252 { 2744 {
2253// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2745// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2254 2746
2747 bool satOnObject = IsSatOnObject;
2748 SceneObjectPart part = ParentPart;
2255 SitGround = false; 2749 SitGround = false;
2256 2750
2257/* move this down so avatar gets physical in the new position and not where it is siting 2751 if (satOnObject)
2258 if (PhysicsActor == null)
2259 AddToPhysicalScene(false);
2260 */
2261
2262 if (ParentID != 0)
2263 { 2752 {
2264 PrevSitOffset = m_pos; // Save sit offset 2753 PrevSitOffset = m_pos; // Save sit offset
2265 SceneObjectPart part = ParentPart;
2266 UnRegisterSeatControls(part.ParentGroup.UUID); 2754 UnRegisterSeatControls(part.ParentGroup.UUID);
2267 2755
2268 TaskInventoryDictionary taskIDict = part.TaskInventory; 2756 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2281,34 +2769,67 @@ namespace OpenSim.Region.Framework.Scenes
2281 } 2769 }
2282 2770
2283 part.ParentGroup.DeleteAvatar(UUID); 2771 part.ParentGroup.DeleteAvatar(UUID);
2284// ParentPosition = part.GetWorldPosition();
2285 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2286 2772
2287// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2773 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2288// ParentPosition = Vector3.Zero; 2774 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); 2775 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2290 if (part.SitTargetAvatar == UUID)
2291 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2292 2776
2293 ParentID = 0; 2777 ParentID = 0;
2294 ParentPart = null; 2778 ParentPart = null;
2295 2779
2296 if (PhysicsActor == null)
2297 AddToPhysicalScene(false);
2298 2780
2299 SendAvatarDataToAllAgents(); 2781 if (part.SitTargetAvatar == UUID)
2300 m_requestedSitTargetID = 0; 2782 standRotation = standRotation * part.SitTargetOrientation;
2783 else
2784 standRotation = standRotation * m_bodyRot;
2301 2785
2302 part.RemoveSittingAvatar(UUID); 2786 m_bodyRot = standRotation;
2303 2787
2304 if (part != null) 2788 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2789
2790 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2791 if (t > 0)
2792 {
2793 t = 1.0f / (float)Math.Sqrt(t);
2794 standRotationZ.W *= t;
2795 standRotationZ.Z *= t;
2796 }
2797 else
2798 {
2799 standRotationZ.W = 1.0f;
2800 standRotationZ.Z = 0f;
2801 }
2802
2803 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2804
2805 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2806
2807// m_log.DebugFormat(
2808// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2809// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2810
2811 standPos.X = Util.Clamp<float>(standPos.X, 0.5f, (float)Constants.RegionSize - 0.5f);
2812 standPos.Y = Util.Clamp<float>(standPos.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
2813 m_pos = standPos;
2306 } 2814 }
2307 2815
2308 else if (PhysicsActor == null) 2816 // We need to wait until we have calculated proper stand positions before sitting up the physical
2817 // avatar to avoid race conditions.
2818 if (PhysicsActor == null)
2309 AddToPhysicalScene(false); 2819 AddToPhysicalScene(false);
2310 2820
2821 if (satOnObject)
2822 {
2823 m_requestedSitTargetID = 0;
2824 part.RemoveSittingAvatar(UUID);
2825 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2826
2827 SendAvatarDataToAllAgents();
2828 }
2829
2311 Animator.TrySetMovementAnimation("STAND"); 2830 Animator.TrySetMovementAnimation("STAND");
2831
2832 TriggerScenePresenceUpdated();
2312 } 2833 }
2313 2834
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2835 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2355,20 +2876,17 @@ namespace OpenSim.Region.Framework.Scenes
2355 if (part == null) 2876 if (part == null)
2356 return; 2877 return;
2357 2878
2879
2358 if (PhysicsActor != null) 2880 if (PhysicsActor != null)
2359 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2881 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2360 2882
2361 bool canSit = false; 2883 bool canSit = false;
2362 Vector3 pos = part.AbsolutePosition + offset;
2363 2884
2364 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2885 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2365 { 2886 {
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; 2887 offset = part.SitTargetPosition;
2371 sitOrientation = part.SitTargetOrientation; 2888 sitOrientation = part.SitTargetOrientation;
2889
2372 canSit = true; 2890 canSit = true;
2373 } 2891 }
2374 else 2892 else
@@ -2376,9 +2894,10 @@ namespace OpenSim.Region.Framework.Scenes
2376 if (PhysicsSit(part,offset)) // physics engine 2894 if (PhysicsSit(part,offset)) // physics engine
2377 return; 2895 return;
2378 2896
2897 Vector3 pos = part.AbsolutePosition + offset;
2898
2379 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2899 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2380 { 2900 {
2381
2382 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2901 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2383 canSit = true; 2902 canSit = true;
2384 } 2903 }
@@ -2404,10 +2923,31 @@ namespace OpenSim.Region.Framework.Scenes
2404 cameraEyeOffset = part.GetCameraEyeOffset(); 2923 cameraEyeOffset = part.GetCameraEyeOffset();
2405 forceMouselook = part.GetForceMouselook(); 2924 forceMouselook = part.GetForceMouselook();
2406 2925
2926 if (!part.IsRoot)
2927 {
2928 sitOrientation = part.RotationOffset * sitOrientation;
2929 offset = offset * part.RotationOffset;
2930 offset += part.OffsetPosition;
2931
2932 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2933 {
2934 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
2935 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2936 }
2937 else
2938 {
2939 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2940 cameraAtOffset += part.OffsetPosition;
2941 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
2942 cameraEyeOffset += part.OffsetPosition;
2943 }
2944 }
2945
2946
2407 ControllingClient.SendSitResponse( 2947 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2948 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2949
2410 m_requestedSitTargetUUID = targetID; 2950 m_requestedSitTargetUUID = part.UUID;
2411 2951
2412 HandleAgentSit(ControllingClient, UUID); 2952 HandleAgentSit(ControllingClient, UUID);
2413 2953
@@ -2435,7 +2975,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2975 if (part != null)
2436 { 2976 {
2437 m_requestedSitTargetID = part.LocalId; 2977 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2978 m_requestedSitTargetUUID = part.UUID;
2439 2979
2440 } 2980 }
2441 else 2981 else
@@ -2529,24 +3069,48 @@ namespace OpenSim.Region.Framework.Scenes
2529 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3069 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2530 bool forceMouselook = part.GetForceMouselook(); 3070 bool forceMouselook = part.GetForceMouselook();
2531 3071
2532 ControllingClient.SendSitResponse( 3072 m_bodyRot = Orientation;
2533 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3073
3074 if (!part.IsRoot)
3075 {
3076 Orientation = part.RotationOffset * Orientation;
3077 offset = offset * part.RotationOffset;
3078 offset += part.OffsetPosition;
3079
3080 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3081 {
3082 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3083 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3084 }
3085 else
3086 {
3087 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3088 cameraAtOffset += part.OffsetPosition;
3089 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3090 cameraEyeOffset += part.OffsetPosition;
3091 }
2534 3092
2535 // not using autopilot 3093 }
2536 3094
2537 Rotation = Orientation;
2538 m_pos = offset; 3095 m_pos = offset;
2539 3096
3097 ControllingClient.SendSitResponse(
3098 part.ParentGroup.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
3099
3100
2540 m_requestedSitTargetID = 0; 3101 m_requestedSitTargetID = 0;
2541 part.ParentGroup.AddAvatar(UUID); 3102 part.ParentGroup.AddAvatar(UUID);
2542 3103
2543 ParentPart = part; 3104 ParentPart = part;
2544 ParentID = part.LocalId; 3105 ParentID = part.LocalId;
3106
3107 SendAvatarDataToAllAgents();
3108
2545 if(status == 3) 3109 if(status == 3)
2546 Animator.TrySetMovementAnimation("SIT_GROUND"); 3110 Animator.TrySetMovementAnimation("SIT_GROUND");
2547 else 3111 else
2548 Animator.TrySetMovementAnimation("SIT"); 3112 Animator.TrySetMovementAnimation("SIT");
2549 SendAvatarDataToAllAgents(); 3113
2550 3114
2551 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3115 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2552 } 3116 }
@@ -2554,6 +3118,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 3118
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 3119 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 3120 {
3121 if (IsChildAgent)
3122 return;
3123
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3124 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 3125
2559 if (part != null) 3126 if (part != null)
@@ -2603,45 +3170,67 @@ namespace OpenSim.Region.Framework.Scenes
2603 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3170 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2604 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 3171 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2605 3172
2606 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 3173 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3174 Quaternion newRot;
3175
3176 if (part.IsRoot)
3177 {
3178 newRot = sitTargetOrient;
3179 }
3180 else
3181 {
3182 newPos = newPos * part.RotationOffset;
3183 newRot = part.RotationOffset * sitTargetOrient;
3184 }
3185
3186 newPos += part.OffsetPosition;
3187
3188 m_pos = newPos;
3189 Rotation = newRot;
2607 3190
2608// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2609 Rotation = sitTargetOrient;
2610// ParentPosition = part.AbsolutePosition; 3191// ParentPosition = part.AbsolutePosition;
2611 part.ParentGroup.AddAvatar(UUID);
2612 } 3192 }
2613 else 3193 else
2614 { 3194 {
2615 m_pos -= part.AbsolutePosition; 3195 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
3196 // being sat upon.
3197 m_pos -= part.GroupPosition;
3198
2616// ParentPosition = part.AbsolutePosition; 3199// ParentPosition = part.AbsolutePosition;
2617 part.ParentGroup.AddAvatar(UUID);
2618 3200
2619// m_log.DebugFormat( 3201// m_log.DebugFormat(
2620// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 3202// "[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); 3203// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2622 } 3204 }
2623 3205
3206 part.ParentGroup.AddAvatar(UUID);
2624 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3207 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2625 ParentID = m_requestedSitTargetID; 3208 ParentID = m_requestedSitTargetID;
2626 m_AngularVelocity = Vector3.Zero; 3209 m_AngularVelocity = Vector3.Zero;
2627 Velocity = Vector3.Zero; 3210 Velocity = Vector3.Zero;
2628 RemoveFromPhysicalScene(); 3211 RemoveFromPhysicalScene();
2629 3212
3213 SendAvatarDataToAllAgents();
3214
2630 String sitAnimation = "SIT"; 3215 String sitAnimation = "SIT";
2631 if (!String.IsNullOrEmpty(part.SitAnimation)) 3216 if (!String.IsNullOrEmpty(part.SitAnimation))
2632 { 3217 {
2633 sitAnimation = part.SitAnimation; 3218 sitAnimation = part.SitAnimation;
2634 } 3219 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 3220 Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 3221 TriggerScenePresenceUpdated();
2637 } 3222 }
2638 } 3223 }
2639 3224
2640 public void HandleAgentSitOnGround() 3225 public void HandleAgentSitOnGround()
2641 { 3226 {
3227 if (IsChildAgent)
3228 return;
3229
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3230// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 3231 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3232 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3233 TriggerScenePresenceUpdated();
2645 SitGround = true; 3234 SitGround = true;
2646 RemoveFromPhysicalScene(); 3235 RemoveFromPhysicalScene();
2647 } 3236 }
@@ -2658,11 +3247,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 3247 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 3248 {
2660 Animator.AddAnimation(animID, UUID.Zero); 3249 Animator.AddAnimation(animID, UUID.Zero);
3250 TriggerScenePresenceUpdated();
2661 } 3251 }
2662 3252
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 3253 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 3254 {
2665 Animator.RemoveAnimation(animID, false); 3255 Animator.RemoveAnimation(animID, false);
3256 TriggerScenePresenceUpdated();
2666 } 3257 }
2667 3258
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 3259 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2676,10 +3267,13 @@ namespace OpenSim.Region.Framework.Scenes
2676 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3267 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2677 /// </summary> 3268 /// </summary>
2678 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3269 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2679 public void AddNewMovement(Vector3 vec) 3270 /// <param name="thisAddSpeedModifier">
3271 /// Optional additional speed modifier for this particular add. Default is 1</param>
3272 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
2680 { 3273 {
2681// m_log.DebugFormat( 3274// m_log.DebugFormat(
2682// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3275// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3276// vec, Rotation, thisAddSpeedModifier, Name);
2683 3277
2684 Vector3 direc = vec * Rotation; 3278 Vector3 direc = vec * Rotation;
2685 direc.Normalize(); 3279 direc.Normalize();
@@ -2697,7 +3291,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 if ((vec.Z == 0f) && !Flying) 3291 if ((vec.Z == 0f) && !Flying)
2698 direc.Z = 0f; // Prevent camera WASD up. 3292 direc.Z = 0f; // Prevent camera WASD up.
2699 3293
2700 direc *= 0.03f * 128f * SpeedModifier; 3294 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2701 3295
2702// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3296// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2703 3297
@@ -2753,6 +3347,9 @@ namespace OpenSim.Region.Framework.Scenes
2753 3347
2754 if (IsChildAgent == false) 3348 if (IsChildAgent == false)
2755 { 3349 {
3350 if (IsInTransit)
3351 return;
3352
2756 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3353 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
2757 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3354 // grab the latest PhysicsActor velocity, whereas m_velocity is often
2758 // storing a requested force instead of an actual traveling velocity 3355 // storing a requested force instead of an actual traveling velocity
@@ -2781,9 +3378,38 @@ namespace OpenSim.Region.Framework.Scenes
2781 3378
2782 #region Update Client(s) 3379 #region Update Client(s)
2783 3380
3381 public void SendUpdateToAgent(ScenePresence p)
3382 {
3383 IClientAPI remoteClient = p.ControllingClient;
3384
3385 if (remoteClient.IsActive)
3386 {
3387 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3388 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3389 m_scene.StatsReporter.AddAgentUpdates(1);
3390 }
3391 }
3392
3393 public void SendFullUpdateToClient(IClientAPI remoteClient)
3394 {
3395 if (remoteClient.IsActive)
3396 {
3397 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3398 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3399 m_scene.StatsReporter.AddAgentUpdates(1);
3400 }
3401 }
3402
3403 // this is diferente from SendTerseUpdateToClient
3404 // this sends bypassing entities updates
3405 public void SendAgentTerseUpdate(ISceneEntity p)
3406 {
3407 ControllingClient.SendAgentTerseUpdate(p);
3408 }
2784 3409
2785 /// <summary> 3410 /// <summary>
2786 /// Sends a location update to the client connected to this scenePresence 3411 /// Sends a location update to the client connected to this scenePresence
3412 /// via entity updates
2787 /// </summary> 3413 /// </summary>
2788 /// <param name="remoteClient"></param> 3414 /// <param name="remoteClient"></param>
2789 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3415 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -2793,7 +3419,6 @@ namespace OpenSim.Region.Framework.Scenes
2793 if (remoteClient.IsActive) 3419 if (remoteClient.IsActive)
2794 { 3420 {
2795 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3421 //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( 3422 remoteClient.SendEntityUpdate(
2798 this, 3423 this,
2799 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3424 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -2803,6 +3428,36 @@ namespace OpenSim.Region.Framework.Scenes
2803 } 3428 }
2804 } 3429 }
2805 3430
3431 public void SendTerseUpdateToAgent(ScenePresence p)
3432 {
3433 IClientAPI remoteClient = p.ControllingClient;
3434
3435 if (!remoteClient.IsActive)
3436 return;
3437
3438 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3439 return;
3440
3441 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3442 remoteClient.SendEntityUpdate(
3443 this,
3444 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3445 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3446
3447 m_scene.StatsReporter.AddAgentUpdates(1);
3448 }
3449
3450 public void SendTerseUpdateToAgentNF(ScenePresence p)
3451 {
3452 IClientAPI remoteClient = p.ControllingClient;
3453 if (remoteClient.IsActive)
3454 {
3455 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3456 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3457 m_scene.StatsReporter.AddAgentUpdates(1);
3458 }
3459 }
3460
2806 3461
2807 // vars to support reduced update frequency when velocity is unchanged 3462 // vars to support reduced update frequency when velocity is unchanged
2808 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3463 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -2843,7 +3498,9 @@ namespace OpenSim.Region.Framework.Scenes
2843 lastTerseUpdateToAllClientsTick = currentTick; 3498 lastTerseUpdateToAllClientsTick = currentTick;
2844 lastPositionSentToAllClients = OffsetPosition; 3499 lastPositionSentToAllClients = OffsetPosition;
2845 3500
2846 m_scene.ForEachClient(SendTerseUpdateToClient); 3501// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3502// m_scene.ForEachClient(SendTerseUpdateToClient);
3503 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
2847 } 3504 }
2848 TriggerScenePresenceUpdated(); 3505 TriggerScenePresenceUpdated();
2849 } 3506 }
@@ -2876,15 +3533,24 @@ namespace OpenSim.Region.Framework.Scenes
2876 // we created a new ScenePresence (a new child agent) in a fresh region. 3533 // we created a new ScenePresence (a new child agent) in a fresh region.
2877 // Request info about all the (root) agents in this region 3534 // 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) 3535 // Note: This won't send data *to* other clients in that region (children don't send)
2879 SendOtherAgentsAvatarDataToMe(); 3536 if (m_teleportFlags <= 0)
2880 SendOtherAgentsAppearanceToMe(); 3537 {
3538 ILandChannel landch = m_scene.LandChannel;
3539 if (landch != null)
3540 {
3541 landch.sendClientInitialLandInfo(ControllingClient);
3542 }
3543 }
3544
3545 SendOtherAgentsAvatarFullToMe();
2881 3546
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3547 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3548 foreach (EntityBase e in entities)
2884 { 3549 {
2885 if (e != null && e is SceneObjectGroup) 3550 if (e != null && e is SceneObjectGroup)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3551 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3552 }
3553
2888 }); 3554 });
2889 } 3555 }
2890 3556
@@ -2905,32 +3571,56 @@ namespace OpenSim.Region.Framework.Scenes
2905 // to see if all the baked textures are already here. 3571 // to see if all the baked textures are already here.
2906 if (m_scene.AvatarFactory != null) 3572 if (m_scene.AvatarFactory != null)
2907 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); 3573 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
2908 3574
2909 // If we aren't using a cached appearance, then clear out the baked textures 3575 // If we aren't using a cached appearance, then clear out the baked textures
2910 if (!cachedappearance) 3576 if (!cachedappearance)
2911 { 3577 {
2912 Appearance.ResetAppearance();
2913 if (m_scene.AvatarFactory != null) 3578 if (m_scene.AvatarFactory != null)
2914 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3579 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
2915 } 3580 }
2916 3581
2917 // This agent just became root. We are going to tell everyone about it. The process of 3582 bool newhide = m_currentParcelHide;
2918 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it 3583 m_currentParcelHide = false;
2919 // again here... this comes after the cached appearance check because the avatars 3584
2920 // appearance goes into the avatar update packet
2921 SendAvatarDataToAllAgents(); 3585 SendAvatarDataToAllAgents();
3586
3587 if (newhide)
3588 {
3589 ParcelLoginCheck(m_currentParcelUUID);
3590 m_currentParcelHide = true;
3591 }
3592
2922 SendAppearanceToAgent(this); 3593 SendAppearanceToAgent(this);
2923 3594
2924 // If we are using the the cached appearance then send it out to everyone 3595// if (cachedappearance)
2925 if (cachedappearance) 3596// {
3597 SendAppearanceToAllOtherAgents();
3598// }
3599 if(Animator!= null)
3600 Animator.SendAnimPack();
3601 }
3602
3603 /// <summary>
3604 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3605 /// can be either a child or root
3606 /// </summary>
3607 public void SendOtherAgentsAvatarFullToMe()
3608 {
3609 int count = 0;
3610 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
2926 { 3611 {
2927 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3612 // only send information about other root agents
3613 if (scenePresence.UUID == UUID)
3614 return;
2928 3615
2929 // If the avatars baked textures are all in the cache, then we have a 3616 scenePresence.SendAvatarDataToAgent(this);
2930 // complete appearance... send it out, if not, then we'll send it when 3617 scenePresence.SendAppearanceToAgent(this);
2931 // the avatar finishes updating its appearance 3618 scenePresence.SendAnimPackToAgent(this);
2932 SendAppearanceToAllOtherAgents(); 3619 // for now attachments are sent with all SOG
2933 } 3620 count++;
3621 });
3622
3623 m_scene.StatsReporter.AddAgentUpdates(count);
2934 } 3624 }
2935 3625
2936 /// <summary> 3626 /// <summary>
@@ -2951,33 +3641,13 @@ namespace OpenSim.Region.Framework.Scenes
2951 } 3641 }
2952 3642
2953 m_lastSize = Appearance.AvatarSize; 3643 m_lastSize = Appearance.AvatarSize;
2954
2955 int count = 0; 3644 int count = 0;
2956 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2957 {
2958 SendAvatarDataToAgent(scenePresence);
2959 count++;
2960 });
2961
2962 m_scene.StatsReporter.AddAgentUpdates(count);
2963 }
2964 3645
2965 /// <summary> 3646 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2966 /// Send avatar data for all other root agents to this agent, this agent 3647 {
2967 /// can be either a child or root 3648 SendAvatarDataToAgent(scenePresence);
2968 /// </summary> 3649 count++;
2969 public void SendOtherAgentsAvatarDataToMe() 3650 });
2970 {
2971 int count = 0;
2972 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
2973 {
2974 // only send information about other root agents
2975 if (scenePresence.UUID == UUID)
2976 return;
2977
2978 scenePresence.SendAvatarDataToAgent(this);
2979 count++;
2980 });
2981 3651
2982 m_scene.StatsReporter.AddAgentUpdates(count); 3652 m_scene.StatsReporter.AddAgentUpdates(count);
2983 } 3653 }
@@ -2989,9 +3659,14 @@ namespace OpenSim.Region.Framework.Scenes
2989 public void SendAvatarDataToAgent(ScenePresence avatar) 3659 public void SendAvatarDataToAgent(ScenePresence avatar)
2990 { 3660 {
2991 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3661 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
3662 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3663 return;
3664 avatar.ControllingClient.SendAvatarDataImmediate(this);
3665 }
2992 3666
3667 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3668 {
2993 avatar.ControllingClient.SendAvatarDataImmediate(this); 3669 avatar.ControllingClient.SendAvatarDataImmediate(this);
2994 Animator.SendAnimPackToClient(avatar.ControllingClient);
2995 } 3670 }
2996 3671
2997 /// <summary> 3672 /// <summary>
@@ -3000,7 +3675,7 @@ namespace OpenSim.Region.Framework.Scenes
3000 /// </summary> 3675 /// </summary>
3001 public void SendAppearanceToAllOtherAgents() 3676 public void SendAppearanceToAllOtherAgents()
3002 { 3677 {
3003// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); 3678 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3004 3679
3005 // only send update from root agents to other clients; children are only "listening posts" 3680 // only send update from root agents to other clients; children are only "listening posts"
3006 if (IsChildAgent) 3681 if (IsChildAgent)
@@ -3011,7 +3686,7 @@ namespace OpenSim.Region.Framework.Scenes
3011 3686
3012 return; 3687 return;
3013 } 3688 }
3014 3689
3015 int count = 0; 3690 int count = 0;
3016 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3691 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3017 { 3692 {
@@ -3022,29 +3697,6 @@ namespace OpenSim.Region.Framework.Scenes
3022 SendAppearanceToAgent(scenePresence); 3697 SendAppearanceToAgent(scenePresence);
3023 count++; 3698 count++;
3024 }); 3699 });
3025
3026 m_scene.StatsReporter.AddAgentUpdates(count);
3027 }
3028
3029 /// <summary>
3030 /// Send appearance from all other root agents to this agent. this agent
3031 /// can be either root or child
3032 /// </summary>
3033 public void SendOtherAgentsAppearanceToMe()
3034 {
3035// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID);
3036
3037 int count = 0;
3038 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
3039 {
3040 // only send information about other root agents
3041 if (scenePresence.UUID == UUID)
3042 return;
3043
3044 scenePresence.SendAppearanceToAgent(this);
3045 count++;
3046 });
3047
3048 m_scene.StatsReporter.AddAgentUpdates(count); 3700 m_scene.StatsReporter.AddAgentUpdates(count);
3049 } 3701 }
3050 3702
@@ -3056,11 +3708,34 @@ namespace OpenSim.Region.Framework.Scenes
3056 { 3708 {
3057// m_log.DebugFormat( 3709// m_log.DebugFormat(
3058// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3710// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3059 3711 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3712 return;
3060 avatar.ControllingClient.SendAppearance( 3713 avatar.ControllingClient.SendAppearance(
3061 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3714 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3715 }
3062 3716
3063 3717 public void SendAnimPackToAgent(ScenePresence p)
3718 {
3719 if (IsChildAgent || Animator == null)
3720 return;
3721
3722 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3723 return;
3724
3725 Animator.SendAnimPackToClient(p.ControllingClient);
3726 }
3727
3728 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3729 {
3730 if (IsChildAgent)
3731 return;
3732
3733 m_scene.ForEachScenePresence(delegate(ScenePresence p)
3734 {
3735 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3736 return;
3737 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3738 });
3064 } 3739 }
3065 3740
3066 #endregion 3741 #endregion
@@ -3079,11 +3754,10 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3754 }
3080 3755
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3756 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3757 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3758 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3759 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3760// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3761
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3762 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3763 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3110,7 +3784,7 @@ namespace OpenSim.Region.Framework.Scenes
3110 cadu.Velocity = Velocity; 3784 cadu.Velocity = Velocity;
3111 3785
3112 AgentPosition agentpos = new AgentPosition(); 3786 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3787 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3114 3788
3115 // Let's get this out of the update loop 3789 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3790 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3130,7 +3804,7 @@ namespace OpenSim.Region.Framework.Scenes
3130 protected void CheckForBorderCrossing() 3804 protected void CheckForBorderCrossing()
3131 { 3805 {
3132 // Check that we we are not a child 3806 // Check that we we are not a child
3133 if (IsChildAgent) 3807 if (IsChildAgent)
3134 return; 3808 return;
3135 3809
3136 // If we don't have a PhysActor, we can't cross anyway 3810 // If we don't have a PhysActor, we can't cross anyway
@@ -3140,140 +3814,127 @@ namespace OpenSim.Region.Framework.Scenes
3140 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3814 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3141 return; 3815 return;
3142 3816
3143 if (!IsInTransit) 3817 if (IsInTransit)
3144 { 3818 return;
3145 Vector3 pos2 = AbsolutePosition;
3146 Vector3 vel = Velocity;
3147 int neighbor = 0;
3148 int[] fix = new int[2];
3149 3819
3150 float timeStep = 0.1f; 3820 Vector3 pos2 = AbsolutePosition;
3151 pos2.X = pos2.X + (vel.X * timeStep); 3821 Vector3 vel = Velocity;
3152 pos2.Y = pos2.Y + (vel.Y * timeStep); 3822 int neighbor = 0;
3153 pos2.Z = pos2.Z + (vel.Z * timeStep); 3823 int[] fix = new int[2];
3154 3824
3155 if (!IsInTransit) 3825 float timeStep = 0.1f;
3156 { 3826 pos2.X = pos2.X + (vel.X * timeStep);
3157// m_log.DebugFormat( 3827 pos2.Y = pos2.Y + (vel.Y * timeStep);
3158// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", 3828 pos2.Z = pos2.Z + (vel.Z * timeStep);
3159// pos2, Name, Scene.Name);
3160 3829
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 3830
3210 // Makes sure avatar does not end up outside region 3831 // m_log.DebugFormat(
3211 if (neighbor <= 0) 3832 // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3212 { 3833 // pos2, Name, Scene.Name);
3213 if (needsTransit) 3834
3214 { 3835 // Checks if where it's headed exists a region
3215 if (m_requestedSitTargetUUID == UUID.Zero) 3836 bool needsTransit = false;
3216 { 3837 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3217 bool isFlying = Flying; 3838 {
3218 RemoveFromPhysicalScene(); 3839 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3219 3840 {
3220 Vector3 pos = AbsolutePosition; 3841 needsTransit = true;
3221 if (AbsolutePosition.X < 0) 3842 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3222 pos.X += Velocity.X * 2; 3843 }
3223 else if (AbsolutePosition.X > Constants.RegionSize) 3844 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3224 pos.X -= Velocity.X * 2; 3845 {
3225 if (AbsolutePosition.Y < 0) 3846 needsTransit = true;
3226 pos.Y += Velocity.Y * 2; 3847 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3227 else if (AbsolutePosition.Y > Constants.RegionSize) 3848 }
3228 pos.Y -= Velocity.Y * 2; 3849 else
3229 Velocity = Vector3.Zero; 3850 {
3230 AbsolutePosition = pos; 3851 needsTransit = true;
3231 3852 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3232// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition); 3853 }
3233 3854 }
3234 AddToPhysicalScene(isFlying); 3855 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3235 } 3856 {
3236 } 3857 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3237 } 3858 {
3238 else if (neighbor > 0) 3859 needsTransit = true;
3860 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3861 }
3862 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3863 {
3864 needsTransit = true;
3865 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3866 }
3867 else
3868 {
3869 needsTransit = true;
3870 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3871 }
3872 }
3873 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3874 {
3875 needsTransit = true;
3876 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3877 }
3878 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3879 {
3880 needsTransit = true;
3881 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3882 }
3883
3884 // Makes sure avatar does not end up outside region
3885 if (neighbor <= 0)
3886 {
3887 if (needsTransit)
3888 {
3889 if (m_requestedSitTargetUUID == UUID.Zero)
3239 { 3890 {
3240 if (!CrossToNewRegion()) 3891 bool isFlying = Flying;
3241 { 3892 RemoveFromPhysicalScene();
3242 if (m_requestedSitTargetUUID == UUID.Zero) 3893
3243 { 3894 Vector3 pos = AbsolutePosition;
3244 bool isFlying = Flying; 3895 if (AbsolutePosition.X < 0)
3245 RemoveFromPhysicalScene(); 3896 pos.X += Velocity.X * 2;
3246 3897 else if (AbsolutePosition.X > Constants.RegionSize)
3247 Vector3 pos = AbsolutePosition; 3898 pos.X -= Velocity.X * 2;
3248 if (AbsolutePosition.X < 0) 3899 if (AbsolutePosition.Y < 0)
3249 pos.X += Velocity.X * 2; 3900 pos.Y += Velocity.Y * 2;
3250 else if (AbsolutePosition.X > Constants.RegionSize) 3901 else if (AbsolutePosition.Y > Constants.RegionSize)
3251 pos.X -= Velocity.X * 2; 3902 pos.Y -= Velocity.Y * 2;
3252 if (AbsolutePosition.Y < 0) 3903 Velocity = Vector3.Zero;
3253 pos.Y += Velocity.Y * 2; 3904 AbsolutePosition = pos;
3254 else if (AbsolutePosition.Y > Constants.RegionSize) 3905
3255 pos.Y -= Velocity.Y * 2; 3906 // m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3256 Velocity = Vector3.Zero; 3907
3257 AbsolutePosition = pos; 3908 AddToPhysicalScene(isFlying);
3258
3259 AddToPhysicalScene(isFlying);
3260 }
3261 }
3262 } 3909 }
3263 } 3910 }
3264 else 3911 }
3912 else if (neighbor > 0)
3913 {
3914 if (!CrossToNewRegion())
3265 { 3915 {
3266 // This constant has been inferred from experimentation 3916 if (m_requestedSitTargetUUID == UUID.Zero)
3267 // I'm not sure what this value should be, so I tried a few values. 3917 {
3268 timeStep = 0.04f; 3918 bool isFlying = Flying;
3269 pos2 = AbsolutePosition; 3919 RemoveFromPhysicalScene();
3270 pos2.X = pos2.X + (vel.X * timeStep); 3920
3271 pos2.Y = pos2.Y + (vel.Y * timeStep); 3921 Vector3 pos = AbsolutePosition;
3272 // Don't touch the Z 3922 if (AbsolutePosition.X < 0)
3273 m_pos = pos2; 3923 pos.X += Velocity.X * 2;
3274 m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos); 3924 else if (AbsolutePosition.X > Constants.RegionSize)
3925 pos.X -= Velocity.X * 2;
3926 if (AbsolutePosition.Y < 0)
3927 pos.Y += Velocity.Y * 2;
3928 else if (AbsolutePosition.Y > Constants.RegionSize)
3929 pos.Y -= Velocity.Y * 2;
3930 Velocity = Vector3.Zero;
3931 AbsolutePosition = pos;
3932
3933 AddToPhysicalScene(isFlying);
3934 }
3275 } 3935 }
3276 } 3936 }
3937
3277 } 3938 }
3278 3939
3279 /// <summary> 3940 /// <summary>
@@ -3284,19 +3945,21 @@ namespace OpenSim.Region.Framework.Scenes
3284 /// </summary> 3945 /// </summary>
3285 protected bool CrossToNewRegion() 3946 protected bool CrossToNewRegion()
3286 { 3947 {
3948 bool result = false;
3949// parcelRegionCross(false);
3287 try 3950 try
3288 { 3951 {
3289 return m_scene.CrossAgentToNewRegion(this, Flying); 3952 result = m_scene.CrossAgentToNewRegion(this, Flying);
3290 } 3953 }
3291 catch 3954 catch
3292 { 3955 {
3293 return m_scene.CrossAgentToNewRegion(this, false); 3956 result = m_scene.CrossAgentToNewRegion(this, false);
3294 } 3957 }
3295 } 3958 // if(!result)
3959 // parcelRegionCross(true);
3960
3961 return result;
3296 3962
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 } 3963 }
3301 3964
3302 public void Reset() 3965 public void Reset()
@@ -3348,10 +4011,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 4011 if (byebyeRegions.Count > 0)
3349 { 4012 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 4013 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 4014
3352 { 4015 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 4016 string auth = string.Empty;
3354 }); 4017 if (acd != null)
4018 auth = acd.SessionID.ToString();
4019 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 4020 }
3356 4021
3357 foreach (ulong handle in byebyeRegions) 4022 foreach (ulong handle in byebyeRegions)
@@ -3368,6 +4033,8 @@ namespace OpenSim.Region.Framework.Scenes
3368 /// </summary> 4033 /// </summary>
3369 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 4034 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3370 { 4035 {
4036 int oldgodlevel = GodLevel;
4037
3371 if (godStatus) 4038 if (godStatus)
3372 { 4039 {
3373 // For now, assign god level 200 to anyone 4040 // For now, assign god level 200 to anyone
@@ -3388,11 +4055,14 @@ namespace OpenSim.Region.Framework.Scenes
3388 } 4055 }
3389 4056
3390 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4057 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4058
4059 if(oldgodlevel != GodLevel)
4060 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3391 } 4061 }
3392 4062
3393 #region Child Agent Updates 4063 #region Child Agent Updates
3394 4064
3395 public void ChildAgentDataUpdate(AgentData cAgentData) 4065 public void UpdateChildAgent(AgentData cAgentData)
3396 { 4066 {
3397// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 4067// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3398 if (!IsChildAgent) 4068 if (!IsChildAgent)
@@ -3402,15 +4072,17 @@ namespace OpenSim.Region.Framework.Scenes
3402 } 4072 }
3403 4073
3404 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4074 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
4075
3405 private void RaiseUpdateThrottles() 4076 private void RaiseUpdateThrottles()
3406 { 4077 {
3407 m_scene.EventManager.TriggerThrottleUpdate(this); 4078 m_scene.EventManager.TriggerThrottleUpdate(this);
3408 } 4079 }
4080
3409 /// <summary> 4081 /// <summary>
3410 /// This updates important decision making data about a child agent 4082 /// 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 4083 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3412 /// </summary> 4084 /// </summary>
3413 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 4085 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3414 { 4086 {
3415 if (!IsChildAgent) 4087 if (!IsChildAgent)
3416 return; 4088 return;
@@ -3452,6 +4124,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 4124
3453 cAgent.AgentID = UUID; 4125 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 4126 cAgent.RegionID = Scene.RegionInfo.RegionID;
4127 cAgent.SessionID = ControllingClient.SessionId;
3455 4128
3456 cAgent.Position = AbsolutePosition; 4129 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 4130 cAgent.Velocity = m_velocity;
@@ -3464,6 +4137,9 @@ namespace OpenSim.Region.Framework.Scenes
3464 4137
3465 // Throttles 4138 // Throttles
3466 float multiplier = 1; 4139 float multiplier = 1;
4140
4141/* this is also used to send to new main regions not children
4142
3467 int childRegions = KnownRegionCount; 4143 int childRegions = KnownRegionCount;
3468 if (childRegions != 0) 4144 if (childRegions != 0)
3469 multiplier = 1f / childRegions; 4145 multiplier = 1f / childRegions;
@@ -3471,7 +4147,7 @@ namespace OpenSim.Region.Framework.Scenes
3471 // Minimum throttle for a child region is 1/4 of the root region throttle 4147 // Minimum throttle for a child region is 1/4 of the root region throttle
3472 if (multiplier <= 0.25f) 4148 if (multiplier <= 0.25f)
3473 multiplier = 0.25f; 4149 multiplier = 0.25f;
3474 4150*/
3475 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); 4151 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
3476 4152
3477 cAgent.HeadRotation = m_headrotation; 4153 cAgent.HeadRotation = m_headrotation;
@@ -3485,7 +4161,8 @@ namespace OpenSim.Region.Framework.Scenes
3485 4161
3486 cAgent.AlwaysRun = SetAlwaysRun; 4162 cAgent.AlwaysRun = SetAlwaysRun;
3487 4163
3488 cAgent.Appearance = new AvatarAppearance(Appearance); 4164 // make clear we want the all thing
4165 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3489 4166
3490 cAgent.ParentPart = ParentUUID; 4167 cAgent.ParentPart = ParentUUID;
3491 cAgent.SitOffset = PrevSitOffset; 4168 cAgent.SitOffset = PrevSitOffset;
@@ -3517,7 +4194,6 @@ namespace OpenSim.Region.Framework.Scenes
3517 4194
3518 private void CopyFrom(AgentData cAgent) 4195 private void CopyFrom(AgentData cAgent)
3519 { 4196 {
3520 m_originRegionID = cAgent.RegionID;
3521 4197
3522 m_callbackURI = cAgent.CallbackURI; 4198 m_callbackURI = cAgent.CallbackURI;
3523// m_log.DebugFormat( 4199// m_log.DebugFormat(
@@ -3581,16 +4257,22 @@ namespace OpenSim.Region.Framework.Scenes
3581 } 4257 }
3582 catch { } 4258 catch { }
3583 4259
4260 Animator.ResetAnimations();
4261
3584 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4262 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
3585 if (cAgent.Anims != null)
3586 Animator.Animations.FromArray(cAgent.Anims);
3587 if (cAgent.DefaultAnim != null) 4263 if (cAgent.DefaultAnim != null)
3588 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4264 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3589 if (cAgent.AnimState != null) 4265 if (cAgent.AnimState != null)
3590 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4266 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4267 if (cAgent.Anims != null)
4268 Animator.Animations.FromArray(cAgent.Anims);
3591 4269
3592 if (Scene.AttachmentsModule != null) 4270 if (Scene.AttachmentsModule != null)
3593 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 4271 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4272
4273 lock (m_originRegionIDAccessLock)
4274 m_originRegionID = cAgent.RegionID;
4275
3594 } 4276 }
3595 4277
3596 public bool CopyAgent(out IAgentData agent) 4278 public bool CopyAgent(out IAgentData agent)
@@ -3607,12 +4289,12 @@ namespace OpenSim.Region.Framework.Scenes
3607 /// </summary> 4289 /// </summary>
3608 public void UpdateMovement() 4290 public void UpdateMovement()
3609 { 4291 {
4292 if (IsInTransit)
4293 return;
3610 if (m_forceToApply.HasValue) 4294 if (m_forceToApply.HasValue)
3611 { 4295 {
3612 Vector3 force = m_forceToApply.Value; 4296 Vector3 force = m_forceToApply.Value;
3613 4297
3614 Updated = true;
3615
3616 Velocity = force; 4298 Velocity = force;
3617 4299
3618 m_forceToApply = null; 4300 m_forceToApply = null;
@@ -3687,14 +4369,17 @@ namespace OpenSim.Region.Framework.Scenes
3687 { 4369 {
3688 if (IsChildAgent || Animator == null) 4370 if (IsChildAgent || Animator == null)
3689 return; 4371 return;
3690 4372
4373 if(IsInTransit)
4374 return;
3691 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4375 //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( 4376 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3693 // as of this comment the interval is set in AddToPhysicalScene 4377 // as of this comment the interval is set in AddToPhysicalScene
3694 4378
3695// if (m_updateCount > 0) 4379// if (m_updateCount > 0)
3696// { 4380// {
3697 Animator.UpdateMovementAnimations(); 4381 if (Animator.UpdateMovementAnimations())
4382 TriggerScenePresenceUpdated();
3698// m_updateCount--; 4383// m_updateCount--;
3699// } 4384// }
3700 4385
@@ -3858,6 +4543,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4543// Animator.Close();
3859 Animator = null; 4544 Animator = null;
3860 4545
4546 LifecycleState = ScenePresenceState.Removed;
3861 } 4547 }
3862 4548
3863 public void AddAttachment(SceneObjectGroup gobj) 4549 public void AddAttachment(SceneObjectGroup gobj)
@@ -4033,6 +4719,192 @@ namespace OpenSim.Region.Framework.Scenes
4033 return validated; 4719 return validated;
4034 } 4720 }
4035 4721
4722 public void SendAttachmentsToAllAgents()
4723 {
4724 lock (m_attachments)
4725 {
4726 foreach (SceneObjectGroup sog in m_attachments)
4727 {
4728 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4729 {
4730 if (p != this && sog.HasPrivateAttachmentPoint)
4731 return;
4732 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4733 return;
4734 sog.SendFullUpdateToClient(p.ControllingClient);
4735 SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path
4736 });
4737 }
4738 }
4739 }
4740
4741 // send attachments to a client without filters except for huds
4742 // for now they are checked in several places down the line...
4743 public void SendAttachmentsToAgentNF(ScenePresence p)
4744 {
4745 lock (m_attachments)
4746 {
4747 foreach (SceneObjectGroup sog in m_attachments)
4748 {
4749 if (p == this || !sog.HasPrivateAttachmentPoint)
4750 {
4751 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
4752 sog.SendFullUpdateToClient(p.ControllingClient);
4753 }
4754 }
4755 SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path
4756 }
4757 }
4758
4759 // send attachments to a client without filters except for huds
4760 // for now they are checked in several places down the line...
4761 // kills all parts before sending
4762 public void SendAttachmentsToAgentNFPK(ScenePresence p)
4763 {
4764 lock (m_attachments)
4765 {
4766 List<uint> pk = new List<uint>();
4767 foreach (SceneObjectGroup sog in m_attachments)
4768 {
4769 foreach (SceneObjectPart part in sog.Parts)
4770 pk.Add(part.LocalId);
4771 }
4772
4773 p.ControllingClient.SendKillObject(pk);
4774
4775 foreach (SceneObjectGroup sog in m_attachments)
4776 {
4777 if (p == this || !sog.HasPrivateAttachmentPoint)
4778 sog.SendFullUpdateToClient(p.ControllingClient);
4779 }
4780 SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path
4781 }
4782 }
4783
4784
4785 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
4786 {
4787 if (IsChildAgent)
4788 return;
4789
4790 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4791 {
4792 if (p != this && sog.HasPrivateAttachmentPoint)
4793 return;
4794 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4795 return;
4796
4797 SceneObjectPart[] parts = sog.Parts;
4798
4799 for (int i = 0; i < parts.Length; i++)
4800 {
4801 SceneObjectPart part = parts[i];
4802 if (part.UpdateFlag == UpdateRequired.TERSE)
4803 {
4804 p.ControllingClient.SendEntityUpdate(part,
4805 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4806 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4807 part.UpdateFlag = 0;
4808 }
4809 else if (part.UpdateFlag == UpdateRequired.FULL)
4810 {
4811 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4812 part.UpdateFlag = 0;
4813 }
4814 }
4815 });
4816 }
4817
4818 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
4819 {
4820 if (IsChildAgent)
4821 return;
4822
4823 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4824 {
4825 if (p != this && part.ParentGroup.HasPrivateAttachmentPoint)
4826 return;
4827
4828 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4829 return;
4830
4831 if (part.UpdateFlag == UpdateRequired.TERSE)
4832 {
4833 p.ControllingClient.SendEntityUpdate(part,
4834 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4835 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4836 part.UpdateFlag = 0;
4837 }
4838 else if (part.UpdateFlag == UpdateRequired.FULL)
4839 {
4840 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4841 part.UpdateFlag = 0;
4842 }
4843 });
4844 }
4845
4846 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
4847 {
4848 if (IsChildAgent)
4849 return;
4850
4851 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4852 {
4853 if (p != this && sog.HasPrivateAttachmentPoint)
4854 return;
4855
4856 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4857 return;
4858
4859 SceneObjectPart[] parts = sog.Parts;
4860
4861 for (int i = 0; i < parts.Length; i++)
4862 {
4863 SceneObjectPart part = parts[i];
4864 if (UpdateFlag == UpdateRequired.TERSE)
4865 {
4866 p.ControllingClient.SendEntityUpdate(part,
4867 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4868 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4869 part.UpdateFlag = 0;
4870 }
4871 else if (UpdateFlag == UpdateRequired.FULL)
4872 {
4873 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4874 part.UpdateFlag = 0;
4875 }
4876 }
4877 });
4878 }
4879
4880 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
4881 {
4882 if (IsChildAgent)
4883 return;
4884
4885 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4886 {
4887 if (p != this && part.ParentGroup.HasPrivateAttachmentPoint)
4888 return;
4889
4890 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4891 return;
4892
4893 if (UpdateFlag == UpdateRequired.TERSE)
4894 {
4895 p.ControllingClient.SendEntityUpdate(part,
4896 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4897 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4898 part.UpdateFlag = 0;
4899 }
4900 else if (UpdateFlag == UpdateRequired.FULL)
4901 {
4902 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4903 part.UpdateFlag = 0;
4904 }
4905 });
4906 }
4907
4036 /// <summary> 4908 /// <summary>
4037 /// Send a script event to this scene presence's attachments 4909 /// Send a script event to this scene presence's attachments
4038 /// </summary> 4910 /// </summary>
@@ -4151,6 +5023,15 @@ namespace OpenSim.Region.Framework.Scenes
4151 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5023 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4152 } 5024 }
4153 5025
5026 public void ClearControls()
5027 {
5028 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5029 lock (scriptedcontrols)
5030 {
5031 scriptedcontrols.Clear();
5032 }
5033 }
5034
4154 private void UnRegisterSeatControls(UUID obj) 5035 private void UnRegisterSeatControls(UUID obj)
4155 { 5036 {
4156 List<UUID> takers = new List<UUID>(); 5037 List<UUID> takers = new List<UUID>();
@@ -4540,8 +5421,8 @@ namespace OpenSim.Region.Framework.Scenes
4540 pos = land.LandData.UserLocation; 5421 pos = land.LandData.UserLocation;
4541 } 5422 }
4542 } 5423 }
4543 5424// this is now done in completeMovement for all cases and not just this
4544 land.SendLandUpdateToClient(ControllingClient); 5425// land.SendLandUpdateToClient(ControllingClient);
4545 } 5426 }
4546 } 5427 }
4547 5428
@@ -4678,6 +5559,8 @@ namespace OpenSim.Region.Framework.Scenes
4678 5559
4679 else 5560 else
4680 { 5561 {
5562 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5563
4681 foreach (uint id in coldata.Keys) 5564 foreach (uint id in coldata.Keys)
4682 { 5565 {
4683 thisHitColliders.Add(id); 5566 thisHitColliders.Add(id);
@@ -4685,7 +5568,7 @@ namespace OpenSim.Region.Framework.Scenes
4685 { 5568 {
4686 startedColliders.Add(id); 5569 startedColliders.Add(id);
4687 curcontact = coldata[id]; 5570 curcontact = coldata[id];
4688 if (Math.Abs(curcontact.RelativeSpeed) > 0.2) 5571 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
4689 { 5572 {
4690 soundinfo = new CollisionForSoundInfo(); 5573 soundinfo = new CollisionForSoundInfo();
4691 soundinfo.colliderID = id; 5574 soundinfo.colliderID = id;
@@ -4764,5 +5647,374 @@ namespace OpenSim.Region.Framework.Scenes
4764 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5647 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4765 5648
4766 } 5649 }
5650
5651 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5652 {
5653 List<ScenePresence> allpresences = null;
5654
5655
5656 allpresences = m_scene.GetScenePresences();
5657
5658 if (isGod)
5659 {
5660 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5661
5662 foreach (ScenePresence p in allpresences)
5663 {
5664 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5665 continue;
5666
5667 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5668 {
5669 viewsToSendme.Add(p); // i see them
5670 }
5671 }
5672
5673 if (viewsToSendme.Count > 0)
5674 {
5675 foreach (ScenePresence p in viewsToSendme)
5676 {
5677 if (p.IsChildAgent)
5678 continue;
5679
5680 p.SendAvatarDataToAgentNF(this);
5681 p.SendAppearanceToAgent(this);
5682 if (p.Animator != null)
5683 p.Animator.SendAnimPackToClient(ControllingClient);
5684 p.SendAttachmentsToAgentNF(this);
5685 }
5686 }
5687 }
5688 else
5689 {
5690 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5691
5692 foreach (ScenePresence p in allpresences)
5693 {
5694 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5695 continue;
5696
5697 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5698 {
5699 killsToSendme.Add(p);
5700 }
5701 }
5702
5703 if (killsToSendme.Count > 0)
5704 {
5705 foreach (ScenePresence p in killsToSendme)
5706 {
5707 m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname);
5708 try { ControllingClient.SendKillObject(new List<uint> { p.LocalId }); }
5709 catch (NullReferenceException) { }
5710 }
5711 }
5712 }
5713
5714 }
5715
5716 private void ParcelLoginCheck(UUID currentParcelID)
5717 {
5718 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5719 List<uint> killsToSendme = new List<uint>();
5720 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5721 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5722 List<ScenePresence> allpresences = null;
5723
5724 allpresences = m_scene.GetScenePresences();
5725
5726 foreach (ScenePresence p in allpresences)
5727 {
5728 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5729 continue;
5730
5731 if (currentParcelID != p.currentParcelUUID)
5732 {
5733 if (p.GodLevel < 200)
5734 killsToSendto.Add(p);
5735// if (GodLevel < 200 && p.ParcelHideThisAvatar)
5736// killsToSendme.Add(p.LocalId);
5737 }
5738 else
5739 {
5740 viewsToSendto.Add(p);
5741 viewsToSendme.Add(p);
5742 }
5743 }
5744 allpresences.Clear();
5745
5746 // send the things
5747 // kill main avatar object
5748 if (killsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5749 {
5750 foreach (ScenePresence p in killsToSendto)
5751 {
5752 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
5753 try { p.ControllingClient.SendKillObject(new List<uint> { LocalId }); }
5754 catch (NullReferenceException) { }
5755 }
5756 }
5757
5758 if (killsToSendme.Count > 0)
5759 {
5760 m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + killsToSendme.Count.ToString());
5761 try
5762 {
5763 ControllingClient.SendKillObject(killsToSendme);
5764 }
5765 catch (NullReferenceException) { }
5766
5767 }
5768/*
5769 if (viewsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5770 {
5771 foreach (ScenePresence p in viewsToSendto)
5772 {
5773 m_log.Debug("[AVATAR]: viewTo: " + Lastname + " " + p.Lastname);
5774 p.ControllingClient.SendAvatarDataImmediate(this);
5775 SendAppearanceToAgent(p);
5776 SendAttachmentsToClient(p.ControllingClient);
5777 if (Animator != null)
5778 Animator.SendAnimPackToClient(p.ControllingClient);
5779 }
5780 }
5781
5782 if (viewsToSendme.Count > 0)
5783 {
5784 foreach (ScenePresence p in viewsToSendme)
5785 {
5786 m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
5787 if (p.IsChildAgent)
5788 continue;
5789 ControllingClient.SendAvatarDataImmediate(p);
5790 p.SendAppearanceToAgent(this);
5791 p.SendAttachmentsToClient(ControllingClient);
5792 if (p.Animator != null)
5793 p.Animator.SendAnimPackToClient(ControllingClient);
5794 }
5795 }
5796*/
5797 }
5798
5799
5800 public void parcelRegionCross()
5801 {
5802 if (!ParcelHideThisAvatar || GodLevel >= 200)
5803 return;
5804
5805 List<ScenePresence> allpresences = null;
5806 allpresences = m_scene.GetScenePresences();
5807
5808 List<uint> killsToSendme = new List<uint>();
5809
5810 foreach (ScenePresence p in allpresences)
5811 {
5812 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5813 continue;
5814
5815 if (p.currentParcelUUID == m_currentParcelUUID)
5816 {
5817 killsToSendme.Add(p.LocalId);
5818 }
5819 }
5820
5821 if (killsToSendme.Count > 0)
5822 {
5823 try
5824 {
5825 ControllingClient.SendKillObject(killsToSendme);
5826 }
5827 catch (NullReferenceException) { }
5828 }
5829 }
5830
5831 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5832 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5833 {
5834 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5835 List<uint> killsToSendme = new List<uint>();
5836 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5837 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5838 List<ScenePresence> allpresences = null;
5839
5840 if (IsInTransit)
5841 return;
5842
5843 if (IsChildAgent)
5844 return;
5845
5846 if (check)
5847 {
5848 // check is relative to current parcel only
5849 if (currentParcelUUID == null || oldhide == currentParcelHide)
5850 return;
5851
5852 allpresences = m_scene.GetScenePresences();
5853
5854 if (oldhide)
5855 { // where private
5856 foreach (ScenePresence p in allpresences)
5857 {
5858 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5859 continue;
5860
5861 // those on not on parcel see me
5862 if (currentParcelID != p.currentParcelUUID)
5863 {
5864 viewsToSendto.Add(p); // they see me
5865 }
5866 }
5867 } // where private end
5868
5869 else
5870 { // where public
5871 foreach (ScenePresence p in allpresences)
5872 {
5873 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5874 continue;
5875
5876 // those not on parcel dont see me
5877 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5878 {
5879 killsToSendto.Add(p); // they dont see me
5880 }
5881 }
5882 } // where public end
5883
5884 allpresences.Clear();
5885 }
5886 else
5887 {
5888 if (currentParcelHide)
5889 {
5890 // now on a private parcel
5891 allpresences = m_scene.GetScenePresences();
5892
5893 if (previusParcelHide && previusParcelID != UUID.Zero)
5894 {
5895 foreach (ScenePresence p in allpresences)
5896 {
5897 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5898 continue;
5899
5900 // only those on previus parcel need receive kills
5901 if (previusParcelID == p.currentParcelUUID)
5902 {
5903 if(p.GodLevel < 200)
5904 killsToSendto.Add(p); // they dont see me
5905 if(GodLevel < 200)
5906 killsToSendme.Add(p.LocalId); // i dont see them
5907 }
5908 // only those on new parcel need see
5909 if (currentParcelID == p.currentParcelUUID)
5910 {
5911 viewsToSendto.Add(p); // they see me
5912 viewsToSendme.Add(p); // i see them
5913 }
5914 }
5915 }
5916 else
5917 {
5918 //was on a public area
5919 allpresences = m_scene.GetScenePresences();
5920
5921 foreach (ScenePresence p in allpresences)
5922 {
5923 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5924 continue;
5925
5926 // those not on new parcel dont see me
5927 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5928 {
5929 killsToSendto.Add(p); // they dont see me
5930 }
5931 else
5932 {
5933 viewsToSendme.Add(p); // i see those on it
5934 }
5935 }
5936 }
5937 allpresences.Clear();
5938 } // now on a private parcel end
5939
5940 else
5941 {
5942 // now on public parcel
5943 if (previusParcelHide && previusParcelID != UUID.Zero)
5944 {
5945 // was on private area
5946 allpresences = m_scene.GetScenePresences();
5947
5948 foreach (ScenePresence p in allpresences)
5949 {
5950 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5951 continue;
5952 // only those old parcel need receive kills
5953 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
5954 {
5955 killsToSendme.Add(p.LocalId); // i dont see them
5956 }
5957 else
5958 {
5959 viewsToSendto.Add(p); // they see me
5960 }
5961 }
5962 }
5963 else
5964 return; // was on a public area also
5965 } // now on public parcel end
5966 }
5967
5968 // send the things
5969 // kill main avatar object
5970 if (killsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5971 {
5972 foreach (ScenePresence p in killsToSendto)
5973 {
5974 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
5975 try { p.ControllingClient.SendKillObject(new List<uint> { LocalId }); }
5976 catch (NullReferenceException) { }
5977 }
5978 }
5979
5980 if (killsToSendme.Count > 0)
5981 {
5982 m_log.Debug("[AVATAR]: killtoMe: " + Lastname + " " + killsToSendme.Count.ToString());
5983 try
5984 {
5985 ControllingClient.SendKillObject(killsToSendme);
5986 }
5987 catch (NullReferenceException) { }
5988
5989 }
5990
5991 if (viewsToSendto.Count > 0 && PresenceType != PresenceType.Npc)
5992 {
5993 foreach (ScenePresence p in viewsToSendto)
5994 {
5995 SendAvatarDataToAgentNF(p);
5996 SendAppearanceToAgent(p);
5997 if (Animator != null)
5998 Animator.SendAnimPackToClient(p.ControllingClient);
5999 SendAttachmentsToAgentNF(p);
6000 }
6001 }
6002
6003 if (viewsToSendme.Count > 0 )
6004 {
6005 foreach (ScenePresence p in viewsToSendme)
6006 {
6007 if (p.IsChildAgent)
6008 continue;
6009// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
6010
6011 p.SendAvatarDataToAgentNF(this);
6012 p.SendAppearanceToAgent(this);
6013 if (p.Animator != null)
6014 p.Animator.SendAnimPackToClient(ControllingClient);
6015 p.SendAttachmentsToAgentNF(this);
6016 }
6017 }
6018 }
4767 } 6019 }
4768} 6020}
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