aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs48
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs19
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs8
-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.cs19
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs33
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs739
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs17
-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.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs109
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs270
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs2
-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.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs88
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs175
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs76
34 files changed, 1752 insertions, 514 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 292efa4..d49b24e 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
40 40
41 uint GetRegionFlags(); 41 uint GetRegionFlags();
42 bool IsManager(UUID avatarID); 42 bool IsManager(UUID avatarID);
43 43
44 /// <summary> 44 /// <summary>
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index 5512642..3780ece 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.Framework.Interfaces
53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
54 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 54 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
55 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); 55 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket);
56 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 56 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
57 bool isModerator, bool textMute); 57 bool isModerator, bool textMute);
58 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); 58 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
diff --git a/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
new file mode 100644
index 0000000..a730cfd
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
@@ -0,0 +1,48 @@
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 OpenMetaverse;
30using OpenSim.Framework;
31using Caps=OpenSim.Framework.Capabilities.Caps;
32
33namespace OpenSim.Region.Framework.Interfaces
34{
35 public interface IExternalCapsModule
36 {
37 /// <summary>
38 /// This function extends the simple URL configuration in the caps handlers
39 /// to facilitate more interesting computation when an external handler is
40 /// sent to the viewer.
41 /// </summary>
42 /// <param name="agentID">New user UUID</param>
43 /// <param name="caps">Internal caps registry, where the external handler will be registered</param>
44 /// <param name="capName">Name of the specific cap we are registering</param>
45 /// <param name="urlSkel">The skeleton URL provided in the caps configuration</param>
46 bool RegisterExternalUserCapsHandler(UUID agentID, Caps caps, String capName, String urlSkel);
47 }
48}
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
index 6885327..9ae5e87 100644
--- a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
@@ -97,5 +97,7 @@ namespace OpenSim.Region.Framework.Interfaces
97 void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID); 97 void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID);
98 void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID GroupID, UUID InviteeID, UUID RoleID); 98 void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID GroupID, UUID InviteeID, UUID RoleID);
99 void NotifyChange(UUID GroupID); 99 void NotifyChange(UUID GroupID);
100
101 List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query);
100 } 102 }
101} \ No newline at end of file 103} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
new file mode 100644
index 0000000..198256f
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
@@ -0,0 +1,19 @@
1using System;
2using System.Collections.Generic;
3
4namespace OpenSim.Region.Framework.Interfaces
5{
6 public interface IServiceThrottleModule
7 {
8 /// <summary>
9 /// Enqueue a continuation meant to get a resource from elsewhere.
10 /// As usual with CPS, caller beware: if that continuation is a never-ending computation,
11 /// the whole thread will be blocked, and no requests are processed
12 /// </summary>
13 /// <param name="category">Category of the resource (e.g. name, region)</param>
14 /// <param name="itemid">The resource identifier</param>
15 /// <param name="continuation">The continuation to be executed</param>
16 void Enqueue(string category, string itemid, Action continuation);
17 }
18
19}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 68af492..8372ddd 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
104 /// <param name="sound">Sound asset ID</param> 104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param> 105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param> 106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param> 107 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param> 108 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param> 109 /// <param name="isMaster">Play as sound master</param>
@@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces
123 /// <param name="max">AABB top north-east corner</param> 122 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume, 123 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max); 124 Vector3 min, Vector3 max);
125
126 /// <summary>
127 /// Set whether sounds on the given prim should be queued.
128 /// </summary>
129 /// <param name='objectID'></param>
130 /// <param name='shouldQueue'></param>
131 void SetSoundQueueing(UUID objectID, bool shouldQueue);
126 } 132 }
127} \ No newline at end of file 133} \ No newline at end of file
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..5529a25 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -93,7 +93,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
93 GetAnimName(animID), animID, m_scenePresence.Name); 93 GetAnimName(animID), animID, m_scenePresence.Name);
94 94
95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
96 {
96 SendAnimPack(); 97 SendAnimPack();
98 m_scenePresence.TriggerScenePresenceUpdated();
99 }
97 } 100 }
98 101
99 // Called from scripts 102 // Called from scripts
@@ -132,7 +135,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
132 GetAnimName(animID), animID, m_scenePresence.Name); 135 GetAnimName(animID), animID, m_scenePresence.Name);
133 136
134 if (m_animations.Remove(animID, allowNoDefault)) 137 if (m_animations.Remove(animID, allowNoDefault))
138 {
135 SendAnimPack(); 139 SendAnimPack();
140 m_scenePresence.TriggerScenePresenceUpdated();
141 }
136 } 142 }
137 143
138 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) 144 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
@@ -180,8 +186,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
180 /// The movement animation is reserved for "main" animations 186 /// The movement animation is reserved for "main" animations
181 /// that are mutually exclusive, e.g. flying and sitting. 187 /// that are mutually exclusive, e.g. flying and sitting.
182 /// </summary> 188 /// </summary>
183 public void TrySetMovementAnimation(string anim) 189 /// <returns>'true' if the animation was updated</returns>
190 public bool TrySetMovementAnimation(string anim)
184 { 191 {
192 bool ret = false;
185 if (!m_scenePresence.IsChildAgent) 193 if (!m_scenePresence.IsChildAgent)
186 { 194 {
187// m_log.DebugFormat( 195// m_log.DebugFormat(
@@ -198,6 +206,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
198 // 16384 is CHANGED_ANIMATION 206 // 16384 is CHANGED_ANIMATION
199 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 207 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION});
200 SendAnimPack(); 208 SendAnimPack();
209 ret = true;
201 } 210 }
202 } 211 }
203 else 212 else
@@ -206,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
206 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", 215 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
207 anim, m_scenePresence.Name); 216 anim, m_scenePresence.Name);
208 } 217 }
218 return ret;
209 } 219 }
210 220
211 /// <summary> 221 /// <summary>
@@ -439,8 +449,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
439 /// <summary> 449 /// <summary>
440 /// Update the movement animation of this avatar according to its current state 450 /// Update the movement animation of this avatar according to its current state
441 /// </summary> 451 /// </summary>
442 public void UpdateMovementAnimations() 452 /// <returns>'true' if the animation was changed</returns>
453 public bool UpdateMovementAnimations()
443 { 454 {
455 bool ret = false;
444 lock (m_animations) 456 lock (m_animations)
445 { 457 {
446 string newMovementAnimation = DetermineMovementAnimation(); 458 string newMovementAnimation = DetermineMovementAnimation();
@@ -454,9 +466,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
454 466
455 // Only set it if it's actually changed, give a script 467 // Only set it if it's actually changed, give a script
456 // a chance to stop a default animation 468 // a chance to stop a default animation
457 TrySetMovementAnimation(CurrentMovementAnimation); 469 ret = TrySetMovementAnimation(CurrentMovementAnimation);
458 } 470 }
459 } 471 }
472 return ret;
460 } 473 }
461 474
462 public UUID[] GetAnimationArray() 475 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index f555b49..11a0146 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
109 foreach (SceneObjectGroup g in objectGroups) 107 foreach (SceneObjectGroup g in objectGroups)
110 { killIDs.Add(g.LocalId); 108 g.DeleteGroupFromScene(false);
111 g.DeleteGroupFromScene(true);
112 }
113
114 m_scene.SendKillObject(killIDs);
115 } 109 }
116 } 110 }
117 111
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
160 if (x.permissionToDelete) 154 if (x.permissionToDelete)
161 { 155 {
162 foreach (SceneObjectGroup g in x.objectGroups) 156 foreach (SceneObjectGroup g in x.objectGroups)
163 m_scene.DeleteSceneObject(g, false); 157 m_scene.DeleteSceneObject(g, true);
164 } 158 }
165 } 159 }
166 catch (Exception e) 160 catch (Exception e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 4733547..6e8eb91 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -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;
@@ -2160,7 +2172,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 } 2172 }
2161 } 2173 }
2162 2174
2163 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) 2175 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel)
2164 { 2176 {
2165 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2177 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2166 if (handlerNewInventoryItemUpdateComplete != null) 2178 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2169,7 +2181,7 @@ namespace OpenSim.Region.Framework.Scenes
2169 { 2181 {
2170 try 2182 try
2171 { 2183 {
2172 d(agentID, AssetID, AssetName, userlevel); 2184 d(agentID, type, AssetID, AssetName, userlevel);
2173 } 2185 }
2174 catch (Exception e) 2186 catch (Exception e)
2175 { 2187 {
@@ -3096,6 +3108,27 @@ namespace OpenSim.Region.Framework.Scenes
3096 } 3108 }
3097 } 3109 }
3098 3110
3111 public void TriggerRegionHeartbeatStart(Scene scene)
3112 {
3113 RegionHeartbeatStart handler = OnRegionHeartbeatStart;
3114
3115 if (handler != null)
3116 {
3117 foreach (RegionHeartbeatStart d in handler.GetInvocationList())
3118 {
3119 try
3120 {
3121 d(scene);
3122 }
3123 catch (Exception e)
3124 {
3125 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}",
3126 e.Message, e.StackTrace);
3127 }
3128 }
3129 }
3130 }
3131
3099 public void TriggerRegionHeartbeatEnd(Scene scene) 3132 public void TriggerRegionHeartbeatEnd(Scene scene)
3100 { 3133 {
3101 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; 3134 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd;
@@ -3251,5 +3284,26 @@ namespace OpenSim.Region.Framework.Scenes
3251 handler(scenePresence); 3284 handler(scenePresence);
3252 } 3285 }
3253 } 3286 }
3287
3288// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3289// {
3290// GatherUuids handler = OnGatherUuids;
3291//
3292// if (handler != null)
3293// {
3294// foreach (GatherUuids d in handler.GetInvocationList())
3295// {
3296// try
3297// {
3298// d(sop, assetUuids);
3299// }
3300// catch (Exception e)
3301// {
3302// m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}",
3303// e.Message, e.StackTrace);
3304// }
3305// }
3306// }
3307// }
3254 } 3308 }
3255} 3309}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 276b61f..c0057ee 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 {
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..4337b5a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -139,7 +139,7 @@ namespace OpenSim.Region.Framework.Scenes
139 { 139 {
140 userlevel = 1; 140 userlevel = 1;
141 } 141 }
142 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 142 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
143 143
144 return true; 144 return true;
145 } 145 }
@@ -178,7 +178,7 @@ namespace OpenSim.Region.Framework.Scenes
178 { 178 {
179 userlevel = 1; 179 userlevel = 1;
180 } 180 }
181 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 181 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
182 182
183 if (originalFolder != UUID.Zero) 183 if (originalFolder != UUID.Zero)
184 { 184 {
@@ -411,19 +411,21 @@ namespace OpenSim.Region.Framework.Scenes
411// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, 411// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
412// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); 412// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
413 413
414 bool sendUpdate = false;
415
414 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid 416 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
415 { 417 {
416 // Create a set of base permissions that will not include export if the user 418 // Create a set of base permissions that will not include export if the user
417 // is not allowed to change the export flag. 419 // is not allowed to change the export flag.
418 bool denyExportChange = false; 420 bool denyExportChange = false;
419 421
420 m_log.InfoFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); 422// m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions);
421 423
422 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export 424 // 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) 425 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; 426 denyExportChange = true;
425 427
426 m_log.InfoFormat("[XXX]: Deny Export Update {0}", denyExportChange); 428// m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange);
427 429
428 // If it is already set, force it set and also force full perm 430 // 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 431 // else prevent setting it. It can and should never be set unless
@@ -447,7 +449,7 @@ namespace OpenSim.Region.Framework.Scenes
447 // If the new state is exportable, force full perm 449 // If the new state is exportable, force full perm
448 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) 450 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
449 { 451 {
450 m_log.InfoFormat("[XXX]: Force full perm"); 452// m_log.DebugFormat("[XXX]: Force full perm");
451 itemUpd.NextPermissions = (uint)(PermissionMask.All); 453 itemUpd.NextPermissions = (uint)(PermissionMask.All);
452 } 454 }
453 } 455 }
@@ -484,8 +486,13 @@ namespace OpenSim.Region.Framework.Scenes
484 item.SalePrice = itemUpd.SalePrice; 486 item.SalePrice = itemUpd.SalePrice;
485 item.SaleType = itemUpd.SaleType; 487 item.SaleType = itemUpd.SaleType;
486 488
489 if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0)
490 {
491 item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf);
492 sendUpdate = true;
493 }
494
487 InventoryService.UpdateItem(item); 495 InventoryService.UpdateItem(item);
488 remoteClient.SendBulkUpdateInventory(item);
489 } 496 }
490 497
491 if (UUID.Zero != transactionID) 498 if (UUID.Zero != transactionID)
@@ -495,6 +502,14 @@ namespace OpenSim.Region.Framework.Scenes
495 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); 502 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
496 } 503 }
497 } 504 }
505 else
506 {
507 // This MAY be problematic, if it is, another solution
508 // needs to be found. If inventory item flags are updated
509 // the viewer's notion of the item needs to be refreshed.
510 if (sendUpdate)
511 remoteClient.SendBulkUpdateInventory(item);
512 }
498 } 513 }
499 else 514 else
500 { 515 {
@@ -548,6 +563,9 @@ namespace OpenSim.Region.Framework.Scenes
548 { 563 {
549 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); 564 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
550 565
566 if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
567 return null;
568
551 InventoryItemBase item = new InventoryItemBase(itemId, senderId); 569 InventoryItemBase item = new InventoryItemBase(itemId, senderId);
552 item = InventoryService.GetItem(item); 570 item = InventoryService.GetItem(item);
553 571
@@ -2124,7 +2142,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2142 {
2125 // If we don't have permission, stop right here 2143 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2144 if (!permissionToTakeCopy)
2145 {
2146 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2147 return;
2148 }
2128 2149
2129 permissionToTake = true; 2150 permissionToTake = true;
2130 // Don't delete 2151 // Don't delete
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index ce6415a..421cb08 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -416,6 +416,7 @@ namespace OpenSim.Region.Framework.Scenes
416 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) 416 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args)
417 { 417 {
418 // TODO: don't create new blocks if recycling an old packet 418 // TODO: don't create new blocks if recycling an old packet
419 bool discardableEffects = true;
419 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; 420 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count];
420 for (int i = 0; i < args.Count; i++) 421 for (int i = 0; i < args.Count; i++)
421 { 422 {
@@ -427,17 +428,34 @@ namespace OpenSim.Region.Framework.Scenes
427 effect.Type = args[i].Type; 428 effect.Type = args[i].Type;
428 effect.TypeData = args[i].TypeData; 429 effect.TypeData = args[i].TypeData;
429 effectBlockArray[i] = effect; 430 effectBlockArray[i] = effect;
431
432 if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam)
433 discardableEffects = false;
434
435 //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type);
430 } 436 }
431 437
432 ForEachClient( 438 ForEachScenePresence(sp =>
433 delegate(IClientAPI client)
434 { 439 {
435 if (client.AgentId != remoteClient.AgentId) 440 if (sp.ControllingClient.AgentId != remoteClient.AgentId)
436 client.SendViewerEffect(effectBlockArray); 441 {
437 } 442 if (!discardableEffects ||
438 ); 443 (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp)))
444 {
445 //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID);
446 sp.ControllingClient.SendViewerEffect(effectBlockArray);
447 }
448 //else
449 // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID);
450 }
451 });
439 } 452 }
440 453
454 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
455 {
456 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
457 }
458
441 private class DescendentsRequestData 459 private class DescendentsRequestData
442 { 460 {
443 public IClientAPI RemoteClient; 461 public IClientAPI RemoteClient;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b189599..d6d2df4 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 }
@@ -859,9 +863,11 @@ namespace OpenSim.Region.Framework.Scenes
859 //Animation states 863 //Animation states
860 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 864 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
861 865
866
867 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
868
862 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 869 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
863 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 870 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
864
865 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 871 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
866 if (RegionInfo.NonphysPrimMin > 0) 872 if (RegionInfo.NonphysPrimMin > 0)
867 { 873 {
@@ -1332,7 +1338,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 Thread.Sleep(500); 1338 Thread.Sleep(500);
1333 1339
1334 // Stop all client threads. 1340 // Stop all client threads.
1335 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1341 ForEachScenePresence(delegate(ScenePresence avatar) { IncomingCloseAgent(avatar.UUID, false); });
1336 1342
1337 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1343 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1338 EventManager.TriggerSceneShuttingDown(this); 1344 EventManager.TriggerSceneShuttingDown(this);
@@ -1361,10 +1367,18 @@ namespace OpenSim.Region.Framework.Scenes
1361 } 1367 }
1362 } 1368 }
1363 1369
1370 public override void Start()
1371 {
1372 Start(true);
1373 }
1374
1364 /// <summary> 1375 /// <summary>
1365 /// Start the scene 1376 /// Start the scene
1366 /// </summary> 1377 /// </summary>
1367 public void Start() 1378 /// <param name='startScripts'>
1379 /// Start the scripts within the scene.
1380 /// </param>
1381 public void Start(bool startScripts)
1368 { 1382 {
1369 m_active = true; 1383 m_active = true;
1370 1384
@@ -1401,6 +1415,8 @@ namespace OpenSim.Region.Framework.Scenes
1401 m_heartbeatThread 1415 m_heartbeatThread
1402 = Watchdog.StartThread( 1416 = Watchdog.StartThread(
1403 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1417 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1418
1419 StartScripts();
1404 } 1420 }
1405 1421
1406 /// <summary> 1422 /// <summary>
@@ -1557,6 +1573,8 @@ namespace OpenSim.Region.Framework.Scenes
1557 1573
1558 try 1574 try
1559 { 1575 {
1576 EventManager.TriggerRegionHeartbeatStart(this);
1577
1560 // Apply taints in terrain module to terrain in physics scene 1578 // Apply taints in terrain module to terrain in physics scene
1561 if (Frame % m_update_terrain == 0) 1579 if (Frame % m_update_terrain == 0)
1562 { 1580 {
@@ -2939,6 +2957,7 @@ namespace OpenSim.Region.Framework.Scenes
2939 { 2957 {
2940 ScenePresence sp; 2958 ScenePresence sp;
2941 bool vialogin; 2959 bool vialogin;
2960 bool reallyNew = true;
2942 2961
2943 // Validation occurs in LLUDPServer 2962 // Validation occurs in LLUDPServer
2944 // 2963 //
@@ -2997,16 +3016,21 @@ namespace OpenSim.Region.Framework.Scenes
2997 m_log.WarnFormat( 3016 m_log.WarnFormat(
2998 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3017 "[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); 3018 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3019 reallyNew = false;
3000 } 3020 }
3001 3021
3002 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3022 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3003 // client is for a root or child agent. 3023 // client is for a root or child agent.
3004 client.SceneAgent = sp; 3024 client.SceneAgent = sp;
3005 3025
3006 // Cache the user's name 3026 // This is currently also being done earlier in NewUserConnection for real users to see if this
3027 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3028 // places. However, we still need to do it here for NPCs.
3007 CacheUserName(sp, aCircuit); 3029 CacheUserName(sp, aCircuit);
3008 3030
3009 EventManager.TriggerOnNewClient(client); 3031 if (reallyNew)
3032 EventManager.TriggerOnNewClient(client);
3033
3010 if (vialogin) 3034 if (vialogin)
3011 EventManager.TriggerOnClientLogin(client); 3035 EventManager.TriggerOnClientLogin(client);
3012 } 3036 }
@@ -3027,7 +3051,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3051 {
3028 string first = aCircuit.firstname, last = aCircuit.lastname; 3052 string first = aCircuit.firstname, last = aCircuit.lastname;
3029 3053
3030 if (sp.PresenceType == PresenceType.Npc) 3054 if (sp != null && sp.PresenceType == PresenceType.Npc)
3031 { 3055 {
3032 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3056 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
3033 } 3057 }
@@ -3105,7 +3129,8 @@ namespace OpenSim.Region.Framework.Scenes
3105 if (sp != null) 3129 if (sp != null)
3106 { 3130 {
3107 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3131 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3108 sp.ControllingClient.Close(); 3132
3133 IncomingCloseAgent(sp.UUID, false);
3109 } 3134 }
3110 3135
3111 // BANG! SLASH! 3136 // BANG! SLASH!
@@ -3244,8 +3269,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 { 3269 {
3245 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3270 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3246 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3271 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3247 client.OnSetStartLocationRequest += SetHomeRezPoint;
3248 client.OnRegionHandleRequest += RegionHandleRequest;
3249 } 3272 }
3250 3273
3251 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3274 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
@@ -3371,8 +3394,6 @@ namespace OpenSim.Region.Framework.Scenes
3371 { 3394 {
3372 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3395 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3373 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3396 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3374 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3375 client.OnRegionHandleRequest -= RegionHandleRequest;
3376 } 3397 }
3377 3398
3378 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3399 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3498,33 +3519,6 @@ namespace OpenSim.Region.Framework.Scenes
3498 } 3519 }
3499 3520
3500 /// <summary> 3521 /// <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. 3522 /// Get the avatar apperance for the given client.
3529 /// </summary> 3523 /// </summary>
3530 /// <param name="client"></param> 3524 /// <param name="client"></param>
@@ -3548,63 +3542,69 @@ namespace OpenSim.Region.Framework.Scenes
3548 } 3542 }
3549 } 3543 }
3550 3544
3545 /// <summary>
3546 /// Remove the given client from the scene.
3547 /// </summary>
3548 /// <remarks>
3549 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3550 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3551 /// from viewers).
3552 /// </remarks>
3553 /// <param name='agentID'>ID of agent to close</param>
3554 /// <param name='closeChildAgents'>
3555 /// Close the neighbour child agents associated with this client.
3556 /// </param>
3551 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3557 public override void RemoveClient(UUID agentID, bool closeChildAgents)
3552 { 3558 {
3553// CheckHeartbeat(); 3559 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3554 bool isChildAgent = false;
3555 AgentCircuitData acd;
3556 3560
3557 lock (m_removeClientLock) 3561 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3562 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3563 // However, will keep for now just in case.
3564 if (acd == null)
3558 { 3565 {
3559 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3566 m_log.ErrorFormat(
3567 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3560 3568
3561 if (acd == null) 3569 return;
3562 { 3570 }
3563 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); 3571 else
3564 return; 3572 {
3565 } 3573 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 } 3574 }
3574 3575
3576 // TODO: Can we now remove this lock?
3575 lock (acd) 3577 lock (acd)
3576 { 3578 {
3579 bool isChildAgent = false;
3580
3577 ScenePresence avatar = GetScenePresence(agentID); 3581 ScenePresence avatar = GetScenePresence(agentID);
3578 3582
3583 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3584 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3585 // However, will keep for now just in case.
3579 if (avatar == null) 3586 if (avatar == null)
3580 { 3587 {
3581 m_log.WarnFormat( 3588 m_log.ErrorFormat(
3582 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3589 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3583 3590
3584 return; 3591 return;
3585 } 3592 }
3586 3593
3587 try 3594 try
3588 { 3595 {
3589 isChildAgent = avatar.IsChildAgent; 3596 isChildAgent = avatar.IsChildAgent;
3590 3597
3591 m_log.DebugFormat( 3598 m_log.DebugFormat(
3592 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3599 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3593 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3600 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3594 3601
3595 // Don't do this to root agents, it's not nice for the viewer 3602 // Don't do this to root agents, it's not nice for the viewer
3596 if (closeChildAgents && isChildAgent) 3603 if (closeChildAgents && isChildAgent)
3597 { 3604 {
3598 // Tell a single agent to disconnect from the region. 3605 // Tell a single agent to disconnect from the region.
3599 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3606 // Let's do this via UDP
3600 if (eq != null) 3607 avatar.ControllingClient.SendShutdownConnectionNotice();
3601 {
3602 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3603 }
3604 else
3605 {
3606 avatar.ControllingClient.SendShutdownConnectionNotice();
3607 }
3608 } 3608 }
3609 3609
3610 // Only applies to root agents. 3610 // Only applies to root agents.
@@ -3620,16 +3620,13 @@ namespace OpenSim.Region.Framework.Scenes
3620 if (closeChildAgents && CapsModule != null) 3620 if (closeChildAgents && CapsModule != null)
3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); 3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3622 3622
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) 3623 if (closeChildAgents && !isChildAgent)
3629 { 3624 {
3630 List<ulong> regions = avatar.KnownRegionHandles; 3625 List<ulong> regions = avatar.KnownRegionHandles;
3631 regions.Remove(RegionInfo.RegionHandle); 3626 regions.Remove(RegionInfo.RegionHandle);
3632 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3627
3628 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3629 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3633 } 3630 }
3634 3631
3635 m_eventManager.TriggerClientClosed(agentID, this); 3632 m_eventManager.TriggerClientClosed(agentID, this);
@@ -3646,7 +3643,7 @@ namespace OpenSim.Region.Framework.Scenes
3646 delegate(IClientAPI client) 3643 delegate(IClientAPI client)
3647 { 3644 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3645 //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 }); } 3646 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3647 catch (NullReferenceException) { }
3651 }); 3648 });
3652 } 3649 }
@@ -3727,7 +3724,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3724 }
3728 deleteIDs.Add(localID); 3725 deleteIDs.Add(localID);
3729 } 3726 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3727
3728 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3729 }
3732 3730
3733 #endregion 3731 #endregion
@@ -3763,13 +3761,13 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3761 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3762 /// the LLUDP stack).
3765 /// </remarks> 3763 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3764 /// <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> 3765 /// <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 3766 /// <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> 3767 /// 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 3768 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3769 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3770 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3771 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3772 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3773 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,15 +3787,15 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3787 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})", 3788 "[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, 3789 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3790 (acd.child ? "child" : "root"),
3793 agent.firstname, 3791 acd.firstname,
3794 agent.lastname, 3792 acd.lastname,
3795 agent.AgentID, 3793 acd.AgentID,
3796 agent.circuitcode, 3794 acd.circuitcode,
3797 agent.IPAddress, 3795 acd.IPAddress,
3798 agent.Viewer, 3796 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3797 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3798 acd.startpos
3801 ); 3799 );
3802 3800
3803 if (!LoginsEnabled) 3801 if (!LoginsEnabled)
@@ -3815,7 +3813,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3813 {
3816 foreach (string viewer in m_AllowedViewers) 3814 foreach (string viewer in m_AllowedViewers)
3817 { 3815 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3816 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3817 {
3820 ViewerDenied = false; 3818 ViewerDenied = false;
3821 break; 3819 break;
@@ -3832,7 +3830,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3830 {
3833 foreach (string viewer in m_BannedViewers) 3831 foreach (string viewer in m_BannedViewers)
3834 { 3832 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3833 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3834 {
3837 ViewerDenied = true; 3835 ViewerDenied = true;
3838 break; 3836 break;
@@ -3844,54 +3842,129 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3842 {
3845 m_log.DebugFormat( 3843 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3844 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3845 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3846 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3847 return false;
3850 } 3848 }
3851 3849
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3850 ILandObject land;
3851 ScenePresence sp;
3853 3852
3854 // If we have noo presence here or if that presence is a zombie root 3853 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3854 {
3858 if (CapsModule != null) 3855 sp = GetScenePresence(acd.AgentID);
3856
3857 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3858 // closed.
3859 if (sp != null && sp.IsChildAgent
3860 && (sp.LifecycleState == ScenePresenceState.Running
3861 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3862 {
3860 lock (agent) 3863 m_log.DebugFormat(
3864 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3865 sp.Name, sp.LifecycleState, Name);
3866
3867 // In the case where, for example, an A B C D region layout, an avatar may
3868 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3869 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3870 //
3871 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3872 // teleport, since realistically, the close request should always be processed before any other
3873 // region tried to re-establish a child agent. This is much simpler since the logic below is
3874 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3875 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3876 // flag when no teleport had taken place (and hence no close was going to come).
3877// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3878// {
3879// m_log.DebugFormat(
3880// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3881// sp.Name, Name);
3882//
3883// sp.DoNotCloseAfterTeleport = true;
3884// }
3885// else if (EntityTransferModule.IsInTransit(sp.UUID))
3886
3887 sp.LifecycleState = ScenePresenceState.Running;
3888
3889 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3890 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3891 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3892
3893 m_log.DebugFormat(
3894 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3895 sp.Name, Name);
3864 } 3896 }
3865 } 3897 }
3866 } 3898 }
3867 3899
3900 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3901 // allow unpredictable things to happen.
3868 if (sp != null) 3902 if (sp != null)
3869 { 3903 {
3870 if (!sp.IsChildAgent) 3904 const int polls = 10;
3905 const int pollInterval = 1000;
3906 int pollsLeft = polls;
3907
3908 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3909 Thread.Sleep(pollInterval);
3910
3911 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3912 {
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( 3913 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3914 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3915 sp.Name, Name, polls * pollInterval / 1000);
3878 3916
3879 sp.ControllingClient.Close(true, true); 3917 return false;
3880 sp = null; 3918 }
3919 else if (polls != pollsLeft)
3920 {
3921 m_log.DebugFormat(
3922 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3923 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3924 }
3882 } 3925 }
3883 3926
3884 lock (agent) 3927 // TODO: can we remove this lock?
3928 lock (acd)
3885 { 3929 {
3886 //On login test land permisions 3930 if (sp != null && !sp.IsChildAgent)
3931 {
3932 // We have a root agent. Is it in transit?
3933 if (!EntityTransferModule.IsInTransit(sp.UUID))
3934 {
3935 // We have a zombie from a crashed session.
3936 // Or the same user is trying to be root twice here, won't work.
3937 // Kill it.
3938 m_log.WarnFormat(
3939 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3940 sp.Name, sp.UUID, RegionInfo.RegionName);
3941
3942 if (sp.ControllingClient != null)
3943 IncomingCloseAgent(sp.UUID, true);
3944
3945 sp = null;
3946 }
3947 //else
3948 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3949 }
3950
3951 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3952 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3953 // If the checks fail, we remove the circuit.
3954 acd.teleportFlags = teleportFlags;
3955 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3956
3957 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3958
3959 // On login test land permisions
3887 if (vialogin) 3960 if (vialogin)
3888 { 3961 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3962 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 3963 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 3964 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3965 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 3966 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3967 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 3968 return false;
3896 } 3969 }
3897 } 3970 }
@@ -3902,40 +3975,49 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 3975 {
3903 try 3976 try
3904 { 3977 {
3905 if (!VerifyUserPresence(agent, out reason)) 3978 if (!VerifyUserPresence(acd, out reason))
3979 {
3980 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 3981 return false;
3907 } catch (Exception e) 3982 }
3983 }
3984 catch (Exception e)
3908 { 3985 {
3909 m_log.ErrorFormat( 3986 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3987 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3988
3989 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 3990 return false;
3912 } 3991 }
3913 } 3992 }
3914 3993
3915 try 3994 try
3916 { 3995 {
3917 // Always check estate if this is a login. Always 3996 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 3997 {
3921 if (!AuthorizeUser(agent, out reason)) 3998 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 3999 return false;
3923 return false;
3924 }
3925 } 4000 }
3926 } 4001 }
3927 catch (Exception e) 4002 catch (Exception e)
3928 { 4003 {
3929 m_log.ErrorFormat( 4004 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4005 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4006
4007 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4008 return false;
3932 } 4009 }
3933 4010
3934 m_log.InfoFormat( 4011 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4012 "[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, 4013 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4014 acd.AgentID, acd.circuitcode);
3938 4015
4016 if (CapsModule != null)
4017 {
4018 CapsModule.SetAgentCapsSeeds(acd);
4019 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4020 }
3939 } 4021 }
3940 else 4022 else
3941 { 4023 {
@@ -3943,43 +4025,60 @@ namespace OpenSim.Region.Framework.Scenes
3943 // uses down the line. 4025 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4026 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4027
4028 // We must carry out a further authorization check if there's an
4029 // attempt to make a child agent into a root agent, since SeeIntoRegion may have allowed a child
4030 // agent to login to a region where a full avatar would not be allowed.
4031 //
4032 // We determine whether this is a CreateAgent for a future non-child agent by inspecting
4033 // TeleportFlags, which will be default for a child connection. This relies on input from the source
4034 // region.
4035 if (sp.TeleportFlags != TPFlags.Default)
4036 {
4037 if (!AuthorizeUser(acd, false, out reason))
4038 return false;
4039 }
4040
3946 if (sp.IsChildAgent) 4041 if (sp.IsChildAgent)
3947 { 4042 {
3948 m_log.DebugFormat( 4043 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4044 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4045 acd.AgentID, RegionInfo.RegionName);
3951 4046
3952 sp.AdjustKnownSeeds(); 4047 sp.AdjustKnownSeeds();
3953 4048
3954 if (CapsModule != null) 4049 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4050 {
4051 CapsModule.SetAgentCapsSeeds(acd);
4052 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4053 }
3956 } 4054 }
3957 } 4055 }
3958 }
3959 4056
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4057 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4058 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4059 // request for the HG avatar appears to trigger before the user name is cached.
4060 CacheUserName(null, acd);
4061 }
3963 4062
3964 if (CapsModule != null) 4063 if (CapsModule != null)
3965 { 4064 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4065 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4066 }
3968 4067
3969 if (vialogin) 4068 if (vialogin)
3970 { 4069 {
3971// CleanDroppedAttachments(); 4070// CleanDroppedAttachments();
3972 4071
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4072 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4073 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4074 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4075 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4076 }
3978 4077
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4078 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4079 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4080 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4081 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4082 }
3984 4083
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4084 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,39 +4088,39 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4088 {
3990 lock (EastBorders) 4089 lock (EastBorders)
3991 { 4090 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4091 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4092 {
3994 m_log.Warn("FIX AGENT POSITION"); 4093 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4094 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4095 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4096 acd.startpos.Z = 720;
3998 } 4097 }
3999 } 4098 }
4000 lock (NorthBorders) 4099 lock (NorthBorders)
4001 { 4100 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4101 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4102 {
4004 m_log.Warn("FIX Agent POSITION"); 4103 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4104 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4105 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4106 acd.startpos.Z = 720;
4008 } 4107 }
4009 } 4108 }
4010 } else 4109 } else
4011 { 4110 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4111 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4112 {
4014 m_log.Warn("FIX AGENT POSITION"); 4113 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4114 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4115 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4116 acd.startpos.Z = 720;
4018 } 4117 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4118 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4119 {
4021 m_log.Warn("FIX Agent POSITION"); 4120 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4121 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4122 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4123 acd.startpos.Z = 720;
4025 } 4124 }
4026 } 4125 }
4027 4126
@@ -4037,12 +4136,12 @@ namespace OpenSim.Region.Framework.Scenes
4037 { 4136 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4137 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4039 if (SpawnPointRouting == "random") 4138 if (SpawnPointRouting == "random")
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4139 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4041 telehub.AbsolutePosition, 4140 telehub.AbsolutePosition,
4042 telehub.GroupRotation 4141 telehub.GroupRotation
4043 ); 4142 );
4044 else 4143 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4144 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4046 telehub.AbsolutePosition, 4145 telehub.AbsolutePosition,
4047 telehub.GroupRotation 4146 telehub.GroupRotation
4048 ); 4147 );
@@ -4050,7 +4149,7 @@ namespace OpenSim.Region.Framework.Scenes
4050 else 4149 else
4051 { 4150 {
4052 // We have a single SpawnPoint and will route the agent to it 4151 // We have a single SpawnPoint and will route the agent to it
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4152 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4054 } 4153 }
4055 4154
4056 return true; 4155 return true;
@@ -4063,7 +4162,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4162 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4163 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4164 {
4066 agent.startpos = land.LandData.UserLocation; 4165 acd.startpos = land.LandData.UserLocation;
4067 } 4166 }
4068 } 4167 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4168 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4257,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4257 /// <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 4258 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4259 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4260 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4261 {
4163 reason = String.Empty; 4262 reason = String.Empty;
4164 4263
@@ -4177,67 +4276,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4276 }
4178 } 4277 }
4179 4278
4180 if (RegionInfo.EstateSettings != null) 4279 // We only test the things below when we want to cut off
4280 // child agents from being present in the scene for which their root
4281 // agent isn't allowed. Otherwise, we allow child agents. The test for
4282 // the root is done elsewhere (QueryAccess)
4283 if (!bypassAccessControl)
4181 { 4284 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4285 if (RegionInfo.EstateSettings != null)
4183 { 4286 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4287 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4288 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4289 {
4187 RegionInfo.RegionName); 4290 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4291 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4292 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4293 RegionInfo.RegionName);
4294 return false;
4295 }
4189 } 4296 }
4190 } 4297 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 { 4298 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4299 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4300 }
4207 else 4301
4302 List<UUID> agentGroups = new List<UUID>();
4303
4304 if (m_groupsModule != null)
4208 { 4305 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4306 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4307
4308 if (GroupMembership != null)
4309 {
4310 for (int i = 0; i < GroupMembership.Length; i++)
4311 agentGroups.Add(GroupMembership[i].GroupID);
4312 }
4313 else
4314 {
4315 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4316 }
4210 } 4317 }
4211 }
4212 4318
4213 bool groupAccess = false; 4319 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4320 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4321
4216 if (estateGroups != null) 4322 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4323 {
4220 if (agentGroups.Contains(group)) 4324 foreach (UUID group in estateGroups)
4221 { 4325 {
4222 groupAccess = true; 4326 if (agentGroups.Contains(group))
4223 break; 4327 {
4328 groupAccess = true;
4329 break;
4330 }
4224 } 4331 }
4225 } 4332 }
4226 } 4333 else
4227 else 4334 {
4228 { 4335 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4336 }
4230 }
4231 4337
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4338 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4339 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4340 !groupAccess)
4235 { 4341 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4342 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); 4343 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.", 4344 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4345 RegionInfo.RegionName);
4240 return false; 4346 return false;
4347 }
4241 } 4348 }
4242 4349
4243 // TODO: estate/region settings are not properly hooked up 4350 // TODO: estate/region settings are not properly hooked up
@@ -4367,8 +4474,6 @@ namespace OpenSim.Region.Framework.Scenes
4367 m_log.DebugFormat( 4474 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4475 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4476
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. 4477 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4478 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4479 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4390,13 +4495,39 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4495 }
4391 4496
4392 // We have to wait until the viewer contacts this region 4497 // 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 4498 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4499 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4394 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4500 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4501 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4502
4397 if (childAgentUpdate != null) 4503 if (sp != null)
4398 { 4504 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4505 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4506 {
4507 m_log.WarnFormat(
4508 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4509 sp.UUID, cAgentData.SessionID);
4510
4511 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4512 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4513 }
4514
4515 sp.ChildAgentDataUpdate(cAgentData);
4516
4517 int ntimes = 20;
4518 if (cAgentData.SenderWantsToWaitForRoot)
4519 {
4520 while (sp.IsChildAgent && ntimes-- > 0)
4521 Thread.Sleep(1000);
4522
4523 m_log.DebugFormat(
4524 "[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits",
4525 sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", Name, 20 - ntimes);
4526
4527 if (sp.IsChildAgent)
4528 return false;
4529 }
4530
4400 return true; 4531 return true;
4401 } 4532 }
4402 4533
@@ -4415,6 +4546,11 @@ namespace OpenSim.Region.Framework.Scenes
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4546 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4547 if (childAgentUpdate != null)
4417 { 4548 {
4549// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4550// // Only warn for now
4551// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4552// childAgentUpdate.UUID, cAgentData.SessionID);
4553
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4554 // 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.. 4555 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4556 if (childAgentUpdate.IsChildAgent)
@@ -4451,10 +4587,6 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4587 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4588 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4589 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 4590
4459 return sp; 4591 return sp;
4460 } 4592 }
@@ -4471,6 +4603,42 @@ namespace OpenSim.Region.Framework.Scenes
4471 4603
4472 return false; 4604 return false;
4473 } 4605 }
4606 /// <summary>
4607 /// Authenticated close (via network)
4608 /// </summary>
4609 /// <param name="agentID"></param>
4610 /// <param name="force"></param>
4611 /// <param name="auth_token"></param>
4612 /// <returns></returns>
4613 public bool IncomingCloseAgent(UUID agentID, bool force, string auth_token)
4614 {
4615 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4616
4617 // Check that the auth_token is valid
4618 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4619
4620 if (acd == null)
4621 {
4622 m_log.DebugFormat(
4623 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4624 agentID, Name);
4625
4626 return false;
4627 }
4628
4629 if (acd.SessionID.ToString() == auth_token)
4630 {
4631 return IncomingCloseAgent(agentID, force);
4632 }
4633 else
4634 {
4635 m_log.WarnFormat(
4636 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4637 agentID, auth_token, Name);
4638 }
4639
4640 return false;
4641 }
4474 4642
4475 public bool IncomingCloseAgent(UUID agentID) 4643 public bool IncomingCloseAgent(UUID agentID)
4476 { 4644 {
@@ -4483,6 +4651,50 @@ namespace OpenSim.Region.Framework.Scenes
4483 } 4651 }
4484 4652
4485 /// <summary> 4653 /// <summary>
4654 /// Tell a single agent to prepare to close.
4655 /// </summary>
4656 /// <remarks>
4657 /// This should only be called if we may close the agent but there will be some delay in so doing. Meant for
4658 /// internal use - other callers should almost certainly called IncomingCloseAgent().
4659 /// </remarks>
4660 /// <param name="sp"></param>
4661 /// <returns>true if pre-close state notification was successful. false if the agent
4662 /// was not in a state where it could transition to pre-close.</returns>
4663 public bool IncomingPreCloseAgent(ScenePresence sp)
4664 {
4665 lock (m_removeClientLock)
4666 {
4667 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4668 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4669 // want to obey this close since C may have renewed the child agent lease on B.
4670 if (sp.DoNotCloseAfterTeleport)
4671 {
4672 m_log.DebugFormat(
4673 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4674 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4675
4676 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4677 sp.DoNotCloseAfterTeleport = false;
4678
4679 return false;
4680 }
4681
4682 if (sp.LifecycleState != ScenePresenceState.Running)
4683 {
4684 m_log.DebugFormat(
4685 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4686 sp.Name, Name, sp.LifecycleState);
4687
4688 return false;
4689 }
4690
4691 sp.LifecycleState = ScenePresenceState.PreRemove;
4692
4693 return true;
4694 }
4695 }
4696
4697 /// <summary>
4486 /// Tell a single agent to disconnect from the region. 4698 /// Tell a single agent to disconnect from the region.
4487 /// </summary> 4699 /// </summary>
4488 /// <param name="agentID"></param> 4700 /// <param name="agentID"></param>
@@ -4492,16 +4704,55 @@ namespace OpenSim.Region.Framework.Scenes
4492 /// </param> 4704 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4705 public bool IncomingCloseAgent(UUID agentID, bool force)
4494 { 4706 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4707 ScenePresence sp;
4496 4708
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4709 lock (m_removeClientLock)
4498 if (presence != null) 4710 {
4711 sp = GetScenePresence(agentID);
4712
4713 if (sp == null)
4714 {
4715 m_log.DebugFormat(
4716 "[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}",
4717 agentID, Name);
4718
4719 return false;
4720 }
4721
4722 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4723 {
4724 m_log.DebugFormat(
4725 "[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}",
4726 sp.Name, Name, sp.LifecycleState);
4727
4728 return false;
4729 }
4730
4731 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4732 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4733 // want to obey this close since C may have renewed the child agent lease on B.
4734 if (sp.DoNotCloseAfterTeleport)
4735 {
4736 m_log.DebugFormat(
4737 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4738 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4739
4740 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4741 sp.DoNotCloseAfterTeleport = false;
4742
4743 return false;
4744 }
4745
4746 sp.LifecycleState = ScenePresenceState.Removing;
4747 }
4748
4749 if (sp != null)
4499 { 4750 {
4500 presence.ControllingClient.Close(force, force); 4751 sp.ControllingClient.Close(force, force);
4501 return true; 4752 return true;
4502 } 4753 }
4503 4754
4504 // Agent not here 4755 // Agent not here
4505 return false; 4756 return false;
4506 } 4757 }
4507 4758
@@ -5091,21 +5342,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5342
5092 #endregion 5343 #endregion
5093 5344
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 5345
5110// Commented pending deletion since this method no longer appears to do anything at all 5346// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5347// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5893,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5893 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5894 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5895 {
5660 minX = 256; 5896 minX = float.MaxValue;
5661 maxX = -256; 5897 maxX = float.MinValue;
5662 minY = 256; 5898 minY = float.MaxValue;
5663 maxY = -256; 5899 maxY = float.MinValue;
5664 minZ = 8192; 5900 minZ = float.MaxValue;
5665 maxZ = -256; 5901 maxZ = float.MinValue;
5666 5902
5667 List<Vector3> offsets = new List<Vector3>(); 5903 List<Vector3> offsets = new List<Vector3>();
5668 5904
@@ -5802,17 +6038,6 @@ Environment.Exit(1);
5802 { 6038 {
5803 reason = "You are banned from the region"; 6039 reason = "You are banned from the region";
5804 6040
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)) 6041 if (Permissions.IsGod(agentID))
5817 { 6042 {
5818 reason = String.Empty; 6043 reason = String.Empty;
@@ -5862,9 +6087,9 @@ Environment.Exit(1);
5862 6087
5863 try 6088 try
5864 { 6089 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6090 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6091 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6092 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6093 return false;
5869 } 6094 }
5870 } 6095 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 74c9582..1dac676 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -218,6 +218,19 @@ namespace OpenSim.Region.Framework.Scenes
218 #region Add/Remove Agent/Avatar 218 #region Add/Remove Agent/Avatar
219 219
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type);
221
222 /// <summary>
223 /// Remove the given client from the scene.
224 /// </summary>
225 /// <remarks>
226 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
227 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
228 /// from viewers).
229 /// </remarks>
230 /// <param name='agentID'>ID of agent to close</param>
231 /// <param name='closeChildAgents'>
232 /// Close the neighbour child agents associated with this client.
233 /// </param>
221 public abstract void RemoveClient(UUID agentID, bool closeChildAgents); 234 public abstract void RemoveClient(UUID agentID, bool closeChildAgents);
222 235
223 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 236 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
@@ -562,6 +575,10 @@ namespace OpenSim.Region.Framework.Scenes
562 get { return false; } 575 get { return false; }
563 } 576 }
564 577
578 public virtual void Start()
579 {
580 }
581
565 public void Restart() 582 public void Restart()
566 { 583 {
567 // This has to be here to fire the event 584 // This has to be here to fire the event
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 775a4c2..52f46f2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// This Closes child agents on neighboring regions 200 /// This Closes child agents on neighboring regions
201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
202 /// </summary> 202 /// </summary>
203 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 203 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
204 { 204 {
205 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 205 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
206 206
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes
209 Utils.LongToUInts(regionHandle, out x, out y); 209 Utils.LongToUInts(regionHandle, out x, out y);
210 210
211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
212 m_scene.SimulationService.CloseChildAgent(destination, agentID);
213 }
214 212
215 private void SendCloseChildAgentCompleted(IAsyncResult iar) 213 m_log.DebugFormat(
216 { 214 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
217 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; 215
218 icon.EndInvoke(iar); 216 m_scene.SimulationService.CloseAgent(destination, agentID, auth_token);
219 } 217 }
220 218
221 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 219 /// <summary>
220 /// Closes a child agents in a collection of regions. Does so asynchronously
221 /// so that the caller doesn't wait.
222 /// </summary>
223 /// <param name="agentID"></param>
224 /// <param name="regionslst"></param>
225 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
222 { 226 {
223 foreach (ulong handle in regionslst) 227 foreach (ulong handle in regionslst)
224 { 228 {
225 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; 229 ulong handleCopy = handle;
226 d.BeginInvoke(agentID, handle, 230 Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
227 SendCloseChildAgentCompleted,
228 d);
229 } 231 }
230 } 232 }
231 233
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..b0f8991 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
631 protected internal ScenePresence CreateAndAddChildScenePresence( 631 protected internal ScenePresence CreateAndAddChildScenePresence(
632 IClientAPI client, AvatarAppearance appearance, PresenceType type) 632 IClientAPI client, AvatarAppearance appearance, PresenceType type)
633 { 633 {
634 ScenePresence newAvatar = null;
635
636 // ScenePresence always defaults to child agent 634 // ScenePresence always defaults to child agent
637 newAvatar = new ScenePresence(client, m_parentScene, appearance, type); 635 ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
638
639 AddScenePresence(newAvatar);
640
641 return newAvatar;
642 }
643
644 /// <summary>
645 /// Add a presence to the scene
646 /// </summary>
647 /// <param name="presence"></param>
648 protected internal void AddScenePresence(ScenePresence presence)
649 {
650 // Always a child when added to the scene
651 bool child = presence.IsChildAgent;
652
653 if (child)
654 {
655 m_numChildAgents++;
656 }
657 else
658 {
659 m_numRootAgents++;
660 presence.AddToPhysicalScene(false);
661 }
662 636
663 Entities[presence.UUID] = presence; 637 Entities[presence.UUID] = presence;
664 638
665 m_scenePresencesLock.EnterWriteLock(); 639 m_scenePresencesLock.EnterWriteLock();
666 try 640 try
667 { 641 {
642 m_numChildAgents++;
643
668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
670 646
@@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
675 } 651 }
676 else 652 else
677 { 653 {
678 // Remember the old presene reference from the dictionary 654 // Remember the old presence reference from the dictionary
679 ScenePresence oldref = newmap[presence.UUID]; 655 ScenePresence oldref = newmap[presence.UUID];
680 // Replace the presence reference in the dictionary with the new value 656 // Replace the presence reference in the dictionary with the new value
681 newmap[presence.UUID] = presence; 657 newmap[presence.UUID] = presence;
@@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes
691 { 667 {
692 m_scenePresencesLock.ExitWriteLock(); 668 m_scenePresencesLock.ExitWriteLock();
693 } 669 }
670
671 return presence;
694 } 672 }
695 673
696 /// <summary> 674 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index c70342f..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes
420 return false; 420 return false;
421 } 421 }
422 422
423 /// <summary>
424 /// Set the debug packet level on each current scene. This level governs which packets are printed out to the
425 /// console.
426 /// </summary>
427 /// <param name="newDebug"></param>
428 /// <param name="name">Name of avatar to debug</param>
429 public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name)
430 {
431 ForEachSelectedScene(scene =>
432 scene.ForEachScenePresence(sp =>
433 {
434 if (name == null || sp.Name == name)
435 {
436 m_log.DebugFormat(
437 "Packet debug for {0} ({1}) set to {2}",
438 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug);
439
440 sp.ControllingClient.DebugPacketLevel = newDebug;
441 }
442 })
443 );
444 }
445
446 public List<ScenePresence> GetCurrentSceneAvatars() 423 public List<ScenePresence> GetCurrentSceneAvatars()
447 { 424 {
448 List<ScenePresence> avatars = new List<ScenePresence>(); 425 List<ScenePresence> avatars = new List<ScenePresence>();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f8624e7..8c50a81 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes
67 { 67 {
68 int scriptsStarted = 0; 68 int scriptsStarted = 0;
69 69
70 if (m_scene == null)
71 {
72 m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances");
73 return 0;
74 }
75
70 // Don't start scripts if they're turned off in the region! 76 // Don't start scripts if they're turned off in the region!
71 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 77 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
72 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 3e1dcaa..6deb870 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1868,11 +1868,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1868 /// <summary>
1869 /// Delete this group from its scene. 1869 /// Delete this group from its scene.
1870 /// </summary> 1870 /// </summary>
1871 /// 1871 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1872 /// 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 1873 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1874 /// must be handled by the caller.
1875 /// 1875 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1876 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1877 public void DeleteGroupFromScene(bool silent)
1878 { 1878 {
@@ -1886,10 +1886,10 @@ namespace OpenSim.Region.Framework.Scenes
1886 { 1886 {
1887 SceneObjectPart part = parts[i]; 1887 SceneObjectPart part = parts[i];
1888 1888
1889 Scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 1889 Scene.ForEachScenePresence(sp =>
1890 { 1890 {
1891 if (avatar.ParentID == LocalId) 1891 if (!sp.IsChildAgent && sp.ParentID == LocalId)
1892 avatar.StandUp(); 1892 sp.StandUp();
1893 1893
1894 if (!silent) 1894 if (!silent)
1895 { 1895 {
@@ -1897,9 +1897,9 @@ namespace OpenSim.Region.Framework.Scenes
1897 if (part == m_rootPart) 1897 if (part == m_rootPart)
1898 { 1898 {
1899 if (!IsAttachment 1899 if (!IsAttachment
1900 || AttachedAvatar == avatar.ControllingClient.AgentId 1900 || AttachedAvatar == sp.UUID
1901 || !HasPrivateAttachmentPoint) 1901 || !HasPrivateAttachmentPoint)
1902 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1902 sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1903 } 1903 }
1904 } 1904 }
1905 }); 1905 });
@@ -2208,7 +2208,7 @@ namespace OpenSim.Region.Framework.Scenes
2208 if (!userExposed) 2208 if (!userExposed)
2209 dupe.IsAttachment = true; 2209 dupe.IsAttachment = true;
2210 2210
2211 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 2211 dupe.m_sittingAvatars = new List<UUID>();
2212 2212
2213 if (!userExposed) 2213 if (!userExposed)
2214 { 2214 {
@@ -3811,20 +3811,23 @@ namespace OpenSim.Region.Framework.Scenes
3811 /// <summary> 3811 /// <summary>
3812 /// Update just the root prim position in a linkset 3812 /// Update just the root prim position in a linkset
3813 /// </summary> 3813 /// </summary>
3814 /// <param name="pos"></param> 3814 /// <param name="newPos"></param>
3815 public void UpdateRootPosition(Vector3 pos) 3815 public void UpdateRootPosition(Vector3 newPos)
3816 { 3816 {
3817 // needs to be called with phys building true 3817 // needs to be called with phys building true
3818 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3818 Vector3 oldPos;
3819 Vector3 oldPos = 3819
3820 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3820 // FIXME: This improves the situation where editing just the root prim of an attached object would send
3821 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3821 // all the other parts to oblivion after detach/reattach. However, a problem remains since the root prim
3822 AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); 3822 // still ends up in the wrong position on reattach.
3823 if (IsAttachment)
3824 oldPos = RootPart.OffsetPosition;
3825 else
3826 oldPos = AbsolutePosition + RootPart.OffsetPosition;
3827
3823 Vector3 diff = oldPos - newPos; 3828 Vector3 diff = oldPos - newPos;
3824 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3825 Quaternion partRotation = m_rootPart.RotationOffset; 3829 Quaternion partRotation = m_rootPart.RotationOffset;
3826 axDiff *= Quaternion.Inverse(partRotation); 3830 diff *= Quaternion.Inverse(partRotation);
3827 diff = axDiff;
3828 3831
3829 SceneObjectPart[] parts = m_parts.GetArray(); 3832 SceneObjectPart[] parts = m_parts.GetArray();
3830 for (int i = 0; i < parts.Length; i++) 3833 for (int i = 0; i < parts.Length; i++)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 261e958..cf03d7c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
231 231
232 public double SoundRadius; 232 public double SoundRadius;
233 233
234 /// <summary>
235 /// Should sounds played from this prim be queued?
236 /// </summary>
237 /// <remarks>
238 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
239 /// </remarks>
240 public bool SoundQueueing { get; set; }
234 241
235 public uint TimeStampFull; 242 public uint TimeStampFull;
236 243
@@ -383,8 +390,6 @@ namespace OpenSim.Region.Framework.Scenes
383 390
384 private SOPVehicle m_vehicleParams = null; 391 private SOPVehicle m_vehicleParams = null;
385 392
386 private KeyframeMotion m_keyframeMotion = null;
387
388 public KeyframeMotion KeyframeMotion 393 public KeyframeMotion KeyframeMotion
389 { 394 {
390 get; set; 395 get; set;
@@ -536,7 +541,11 @@ namespace OpenSim.Region.Framework.Scenes
536 CreatorID = uuid; 541 CreatorID = uuid;
537 } 542 }
538 if (parts.Length >= 2) 543 if (parts.Length >= 2)
544 {
539 CreatorData = parts[1]; 545 CreatorData = parts[1];
546 if (!CreatorData.EndsWith("/"))
547 CreatorData += "/";
548 }
540 if (parts.Length >= 3) 549 if (parts.Length >= 3)
541 name = parts[2]; 550 name = parts[2];
542 551
@@ -815,7 +824,8 @@ namespace OpenSim.Region.Framework.Scenes
815 } 824 }
816 825
817 // Tell the physics engines that this prim changed. 826 // Tell the physics engines that this prim changed.
818 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 827 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
828 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
819 } 829 }
820 catch (Exception e) 830 catch (Exception e)
821 { 831 {
@@ -933,7 +943,7 @@ namespace OpenSim.Region.Framework.Scenes
933 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 943 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
934 } 944 }
935 945
936 if (ParentGroup != null) 946 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
937 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 947 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
938 //} 948 //}
939 } 949 }
@@ -1218,23 +1228,14 @@ namespace OpenSim.Region.Framework.Scenes
1218 // the mappings more consistant. 1228 // the mappings more consistant.
1219 public Vector3 SitTargetPositionLL 1229 public Vector3 SitTargetPositionLL
1220 { 1230 {
1221 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1231 get { return m_sitTargetPosition; }
1222 set { m_sitTargetPosition = value; } 1232 set { m_sitTargetPosition = value; }
1223 } 1233 }
1224 1234
1225 public Quaternion SitTargetOrientationLL 1235 public Quaternion SitTargetOrientationLL
1226 { 1236 {
1227 get 1237 get { return m_sitTargetOrientation; }
1228 { 1238 set { m_sitTargetOrientation = value; }
1229 return new Quaternion(
1230 m_sitTargetOrientation.X,
1231 m_sitTargetOrientation.Y,
1232 m_sitTargetOrientation.Z,
1233 m_sitTargetOrientation.W
1234 );
1235 }
1236
1237 set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); }
1238 } 1239 }
1239 1240
1240 public bool Stopped 1241 public bool Stopped
@@ -4350,30 +4351,31 @@ namespace OpenSim.Region.Framework.Scenes
4350 } 4351 }
4351 } 4352 }
4352 4353
4353 public void UpdateGroupPosition(Vector3 pos) 4354 public void UpdateGroupPosition(Vector3 newPos)
4354 { 4355 {
4355 if ((pos.X != GroupPosition.X) || 4356 Vector3 oldPos = GroupPosition;
4356 (pos.Y != GroupPosition.Y) || 4357
4357 (pos.Z != GroupPosition.Z)) 4358 if ((newPos.X != oldPos.X) ||
4359 (newPos.Y != oldPos.Y) ||
4360 (newPos.Z != oldPos.Z))
4358 { 4361 {
4359 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4360 GroupPosition = newPos; 4362 GroupPosition = newPos;
4361 ScheduleTerseUpdate(); 4363 ScheduleTerseUpdate();
4362 } 4364 }
4363 } 4365 }
4364 4366
4365 /// <summary> 4367 /// <summary>
4366 /// 4368 /// Update this part's offset position.
4367 /// </summary> 4369 /// </summary>
4368 /// <param name="pos"></param> 4370 /// <param name="pos"></param>
4369 public void UpdateOffSet(Vector3 pos) 4371 public void UpdateOffSet(Vector3 newPos)
4370 { 4372 {
4371 if ((pos.X != OffsetPosition.X) || 4373 Vector3 oldPos = OffsetPosition;
4372 (pos.Y != OffsetPosition.Y) ||
4373 (pos.Z != OffsetPosition.Z))
4374 {
4375 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4376 4374
4375 if ((newPos.X != oldPos.X) ||
4376 (newPos.Y != oldPos.Y) ||
4377 (newPos.Z != oldPos.Z))
4378 {
4377 if (ParentGroup.RootPart.GetStatusSandbox()) 4379 if (ParentGroup.RootPart.GetStatusSandbox())
4378 { 4380 {
4379 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4381 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -4520,7 +4522,7 @@ namespace OpenSim.Region.Framework.Scenes
4520 // For now, we use the NINJA naming scheme for identifying joints. 4522 // For now, we use the NINJA naming scheme for identifying joints.
4521 // In the future, we can support other joint specification schemes such as a 4523 // In the future, we can support other joint specification schemes such as a
4522 // custom checkbox in the viewer GUI. 4524 // custom checkbox in the viewer GUI.
4523 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4525 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4524 { 4526 {
4525 return IsHingeJoint() || IsBallJoint(); 4527 return IsHingeJoint() || IsBallJoint();
4526 } 4528 }
@@ -4642,6 +4644,11 @@ namespace OpenSim.Region.Framework.Scenes
4642 } 4644 }
4643 } 4645 }
4644*/ 4646*/
4647 if (pa != null)
4648 {
4649 pa.SetMaterial(Material);
4650 DoPhysicsPropertyUpdate(UsePhysics, true);
4651 }
4645 } 4652 }
4646 else // it already has a physical representation 4653 else // it already has a physical representation
4647 { 4654 {
@@ -5014,6 +5021,14 @@ namespace OpenSim.Region.Framework.Scenes
5014 oldTex.DefaultTexture = fallbackOldFace; 5021 oldTex.DefaultTexture = fallbackOldFace;
5015 } 5022 }
5016 5023
5024 // Materials capable viewers can send a ObjectImage packet
5025 // when nothing in TE has changed. MaterialID should be updated
5026 // by the RenderMaterials CAP handler, so updating it here may cause a
5027 // race condtion. Therefore, if no non-materials TE fields have changed,
5028 // we should ignore any changes and not update Shape.TextureEntry
5029
5030 bool otherFieldsChanged = false;
5031
5017 for (int i = 0 ; i < GetNumberOfSides(); i++) 5032 for (int i = 0 ; i < GetNumberOfSides(); i++)
5018 { 5033 {
5019 5034
@@ -5040,18 +5055,36 @@ namespace OpenSim.Region.Framework.Scenes
5040 // Max change, skip the rest of testing 5055 // Max change, skip the rest of testing
5041 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5056 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
5042 break; 5057 break;
5058
5059 if (!otherFieldsChanged)
5060 {
5061 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
5062 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
5063 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
5064 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
5065 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
5066 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
5067 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
5068 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
5069 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
5070 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
5071 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5072 }
5043 } 5073 }
5044 5074
5045 m_shape.TextureEntry = newTex.GetBytes(); 5075 if (changeFlags != 0 || otherFieldsChanged)
5046 if (changeFlags != 0) 5076 {
5047 TriggerScriptChangedEvent(changeFlags); 5077 m_shape.TextureEntry = newTex.GetBytes();
5048 UpdateFlag = UpdateRequired.FULL; 5078 if (changeFlags != 0)
5049 ParentGroup.HasGroupChanged = true; 5079 TriggerScriptChangedEvent(changeFlags);
5080 UpdateFlag = UpdateRequired.FULL;
5081 ParentGroup.HasGroupChanged = true;
5050 5082
5051 //This is madness.. 5083 //This is madness..
5052 //ParentGroup.ScheduleGroupForFullUpdate(); 5084 //ParentGroup.ScheduleGroupForFullUpdate();
5053 //This is sparta 5085 //This is sparta
5054 ScheduleFullUpdate(); 5086 ScheduleFullUpdate();
5087 }
5055 } 5088 }
5056 5089
5057 5090
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d04d87b..3be0623 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);
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7004d23..183d8d1 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,7 +29,9 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using Nini.Config;
@@ -73,21 +75,40 @@ namespace OpenSim.Region.Framework.Scenes
73 75
74 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
75 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
76// ~ScenePresence() 80// ~ScenePresence()
77// { 81// {
78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 83// }
80 84
81 private void TriggerScenePresenceUpdated() 85 public void TriggerScenePresenceUpdated()
82 { 86 {
83 if (m_scene != null) 87 if (m_scene != null)
84 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
85 } 89 }
86 90
87 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
88
89 public PresenceType PresenceType { get; private set; } 91 public PresenceType PresenceType { get; private set; }
90 92
93 private ScenePresenceStateMachine m_stateMachine;
94
95 /// <summary>
96 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
97 /// for more details.
98 /// </summary>
99 public ScenePresenceState LifecycleState
100 {
101 get
102 {
103 return m_stateMachine.GetState();
104 }
105
106 set
107 {
108 m_stateMachine.SetState(value);
109 }
110 }
111
91// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 112// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
92 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 113 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
93 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 114 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -142,6 +163,8 @@ namespace OpenSim.Region.Framework.Scenes
142 private Vector3 m_lastVelocity; 163 private Vector3 m_lastVelocity;
143 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 164 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
144 165
166 private bool m_followCamAuto = false;
167
145 168
146 private Vector3? m_forceToApply; 169 private Vector3? m_forceToApply;
147 private int m_userFlags; 170 private int m_userFlags;
@@ -200,7 +223,7 @@ namespace OpenSim.Region.Framework.Scenes
200 private float m_sitAvatarHeight = 2.0f; 223 private float m_sitAvatarHeight = 2.0f;
201 224
202 private Vector3 m_lastChildAgentUpdatePosition; 225 private Vector3 m_lastChildAgentUpdatePosition;
203 private Vector3 m_lastChildAgentUpdateCamPosition; 226// private Vector3 m_lastChildAgentUpdateCamPosition;
204 227
205 private const int LAND_VELOCITYMAG_MAX = 12; 228 private const int LAND_VELOCITYMAG_MAX = 12;
206 229
@@ -290,9 +313,23 @@ namespace OpenSim.Region.Framework.Scenes
290 /// </summary> 313 /// </summary>
291 private Vector3 posLastSignificantMove; 314 private Vector3 posLastSignificantMove;
292 315
293 // For teleports and crossings callbacks 316 #region For teleports and crossings callbacks
294 string m_callbackURI; 317
295 UUID m_originRegionID; 318 /// <summary>
319 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
320 /// </summary>
321 private string m_callbackURI;
322
323 public UUID m_originRegionID;
324
325 /// <summary>
326 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
327 /// teleport is reusing the connection.
328 /// </summary>
329 /// <remarks>May be refactored or move somewhere else soon.</remarks>
330 public bool DoNotCloseAfterTeleport { get; set; }
331
332 #endregion
296 333
297 /// <value> 334 /// <value>
298 /// Script engines present in the scene 335 /// Script engines present in the scene
@@ -795,7 +832,7 @@ namespace OpenSim.Region.Framework.Scenes
795 832
796 public ScenePresence( 833 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 834 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 835 {
799 AttachmentsSyncLock = new Object(); 836 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 837 AllowMovement = true;
801 IsChildAgent = true; 838 IsChildAgent = true;
@@ -841,6 +878,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 878 SetDirectionVectors();
842 879
843 Appearance = appearance; 880 Appearance = appearance;
881
882 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 883 }
845 884
846 private void RegionHeartbeatEnd(Scene scene) 885 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +913,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 913 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 914 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 915 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
916 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 917 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 918 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 919 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -937,7 +977,7 @@ namespace OpenSim.Region.Framework.Scenes
937 /// </summary> 977 /// </summary>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 978 public void MakeRootAgent(Vector3 pos, bool isFlying)
939 { 979 {
940 m_log.DebugFormat( 980 m_log.InfoFormat(
941 "[SCENE]: Upgrading child to root agent for {0} in {1}", 981 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName); 982 Name, m_scene.RegionInfo.RegionName);
943 983
@@ -977,6 +1017,11 @@ namespace OpenSim.Region.Framework.Scenes
977 1017
978 IsChildAgent = false; 1018 IsChildAgent = false;
979 1019
1020 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1021 // set and prevent the close of the connection on a subsequent re-teleport.
1022 // Should not be needed if we are not trying to tell this region to close
1023// DoNotCloseAfterTeleport = false;
1024
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1025 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1026 if (gm != null)
982 Grouptitle = gm.GetGroupTitle(m_uuid); 1027 Grouptitle = gm.GetGroupTitle(m_uuid);
@@ -1153,7 +1198,6 @@ namespace OpenSim.Region.Framework.Scenes
1153 1198
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1199 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1155 1200
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1157 } 1201 }
1158 1202
1159 public int GetStateSource() 1203 public int GetStateSource()
@@ -1306,7 +1350,26 @@ namespace OpenSim.Region.Framework.Scenes
1306 1350
1307 public void StopFlying() 1351 public void StopFlying()
1308 { 1352 {
1309 ControllingClient.StopFlying(this); 1353 Vector3 pos = AbsolutePosition;
1354 if (Appearance.AvatarHeight != 127.0f)
1355 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1356 else
1357 pos += new Vector3(0f, 0f, (1.56f / 6f));
1358
1359 AbsolutePosition = pos;
1360
1361 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1362 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1363 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1364 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1365
1366 // why are we still testing for this really old height value default???
1367 if (Appearance.AvatarHeight != 127.0f)
1368 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1369 else
1370 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1371
1372 ControllingClient.SendAgentTerseUpdate(this);
1310 } 1373 }
1311 1374
1312 /// <summary> 1375 /// <summary>
@@ -1480,6 +1543,26 @@ namespace OpenSim.Region.Framework.Scenes
1480 1543
1481 } 1544 }
1482 1545
1546 private bool WaitForUpdateAgent(IClientAPI client)
1547 {
1548 // Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero
1549 int count = 50;
1550 while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
1551 {
1552 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1553 Thread.Sleep(200);
1554 }
1555
1556 if (m_originRegionID.Equals(UUID.Zero))
1557 {
1558 // Movement into region will fail
1559 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1560 return false;
1561 }
1562
1563 return true;
1564 }
1565
1483 /// <summary> 1566 /// <summary>
1484 /// Complete Avatar's movement into the region. 1567 /// Complete Avatar's movement into the region.
1485 /// </summary> 1568 /// </summary>
@@ -1497,6 +1580,15 @@ namespace OpenSim.Region.Framework.Scenes
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1580 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1581 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition);
1499 1582
1583 // Make sure it's not a login agent. We don't want to wait for updates during login
1584 if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1585 {
1586 // Let's wait until UpdateAgent (called by departing region) is done
1587 if (!WaitForUpdateAgent(client))
1588 // The sending region never sent the UpdateAgent data, we have to refuse
1589 return;
1590 }
1591
1500 Vector3 look = Velocity; 1592 Vector3 look = Velocity;
1501 1593
1502 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1594 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
@@ -1518,11 +1610,17 @@ namespace OpenSim.Region.Framework.Scenes
1518 1610
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1611 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1520 MakeRootAgent(AbsolutePosition, flying); 1612 MakeRootAgent(AbsolutePosition, flying);
1613
1614 // Tell the client that we're totally ready
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1615 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1522 1616
1617 // Remember in HandleUseCircuitCode, we delayed this to here
1618 if (m_teleportFlags > 0)
1619 SendInitialDataToMe();
1620
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1621// m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1524 1622
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1623 if (!string.IsNullOrEmpty(m_callbackURI))
1526 { 1624 {
1527 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1625 // 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 1626 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
@@ -1550,7 +1648,6 @@ namespace OpenSim.Region.Framework.Scenes
1550 // Create child agents in neighbouring regions 1648 // Create child agents in neighbouring regions
1551 if (openChildAgents && !IsChildAgent) 1649 if (openChildAgents && !IsChildAgent)
1552 { 1650 {
1553
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1651 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1555 if (m_agentTransfer != null) 1652 if (m_agentTransfer != null)
1556 m_agentTransfer.EnableChildAgents(this); 1653 m_agentTransfer.EnableChildAgents(this);
@@ -1573,6 +1670,7 @@ namespace OpenSim.Region.Framework.Scenes
1573// m_log.DebugFormat( 1670// m_log.DebugFormat(
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1671// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1672// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1673
1576 } 1674 }
1577 1675
1578 /// <summary> 1676 /// <summary>
@@ -1653,9 +1751,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 1751 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1752 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 1753 {
1656// m_log.DebugFormat( 1754 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 1755 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 1756 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 1757
1660 if (IsChildAgent) 1758 if (IsChildAgent)
1661 { 1759 {
@@ -1663,10 +1761,6 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 1761 return;
1664 } 1762 }
1665 1763
1666 ++m_movementUpdateCount;
1667 if (m_movementUpdateCount < 1)
1668 m_movementUpdateCount = 1;
1669
1670 #region Sanity Checking 1764 #region Sanity Checking
1671 1765
1672 // This is irritating. Really. 1766 // This is irritating. Really.
@@ -1697,21 +1791,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 1791
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 1792 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 1793
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 1794 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 1795 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 1796 // changes, then start using the agent's drawdistance rather than the
@@ -1783,8 +1862,14 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 1862 // Here's where you get them.
1784 m_AgentControlFlags = flags; 1863 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 1864 m_headrotation = agentData.HeadRotation;
1865 byte oldState = State;
1786 State = agentData.State; 1866 State = agentData.State;
1787 1867
1868 // We need to send this back to the client in order to stop the edit beams
1869 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
1870 ControllingClient.SendAgentTerseUpdate(this);
1871
1872
1788 PhysicsActor actor = PhysicsActor; 1873 PhysicsActor actor = PhysicsActor;
1789 if (actor == null) 1874 if (actor == null)
1790 { 1875 {
@@ -1996,10 +2081,78 @@ namespace OpenSim.Region.Framework.Scenes
1996 SendControlsToScripts(flagsForScripts); 2081 SendControlsToScripts(flagsForScripts);
1997 } 2082 }
1998 2083
2084 // We need to send this back to the client in order to see the edit beams
2085 if ((State & (uint)AgentState.Editing) != 0)
2086 ControllingClient.SendAgentTerseUpdate(this);
2087
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2088 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2089 }
2002 2090
2091
2092 /// <summary>
2093 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2094 /// </summary>
2095 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2096 {
2097 //m_log.DebugFormat(
2098 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2099 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2100
2101 if (IsChildAgent)
2102 {
2103 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2104 return;
2105 }
2106
2107 ++m_movementUpdateCount;
2108 if (m_movementUpdateCount < 1)
2109 m_movementUpdateCount = 1;
2110
2111// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2112
2113 // Camera location in world. We'll need to raytrace
2114 // from this location from time to time.
2115 CameraPosition = agentData.CameraCenter;
2116 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2117 {
2118 ReprioritizeUpdates();
2119 m_lastCameraPosition = CameraPosition;
2120 }
2121
2122 // Use these three vectors to figure out what the agent is looking at
2123 // Convert it to a Matrix and/or Quaternion
2124 CameraAtAxis = agentData.CameraAtAxis;
2125 CameraLeftAxis = agentData.CameraLeftAxis;
2126 CameraUpAxis = agentData.CameraUpAxis;
2127
2128 // The Agent's Draw distance setting
2129 // When we get to the point of re-computing neighbors everytime this
2130 // changes, then start using the agent's drawdistance rather than the
2131 // region's draw distance.
2132 // DrawDistance = agentData.Far;
2133 DrawDistance = Scene.DefaultDrawDistance;
2134
2135 // Check if Client has camera in 'follow cam' or 'build' mode.
2136 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2137
2138 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2139 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2140
2141
2142 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2143 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2144 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2145 {
2146 if (m_followCamAuto)
2147 {
2148 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2149 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2150 }
2151 }
2152
2153 TriggerScenePresenceUpdated();
2154 }
2155
2003 /// <summary> 2156 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2157 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2158 /// </summary>
@@ -2309,6 +2462,7 @@ namespace OpenSim.Region.Framework.Scenes
2309 AddToPhysicalScene(false); 2462 AddToPhysicalScene(false);
2310 2463
2311 Animator.TrySetMovementAnimation("STAND"); 2464 Animator.TrySetMovementAnimation("STAND");
2465 TriggerScenePresenceUpdated();
2312 } 2466 }
2313 2467
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2468 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2407,7 +2561,7 @@ namespace OpenSim.Region.Framework.Scenes
2407 ControllingClient.SendSitResponse( 2561 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2562 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2563
2410 m_requestedSitTargetUUID = targetID; 2564 m_requestedSitTargetUUID = part.UUID;
2411 2565
2412 HandleAgentSit(ControllingClient, UUID); 2566 HandleAgentSit(ControllingClient, UUID);
2413 2567
@@ -2435,7 +2589,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2589 if (part != null)
2436 { 2590 {
2437 m_requestedSitTargetID = part.LocalId; 2591 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2592 m_requestedSitTargetUUID = part.UUID;
2439 2593
2440 } 2594 }
2441 else 2595 else
@@ -2554,6 +2708,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 2708
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2709 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 2710 {
2711 if (IsChildAgent)
2712 return;
2713
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2714 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 2715
2559 if (part != null) 2716 if (part != null)
@@ -2634,14 +2791,19 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 2791 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 2792 Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 2793 SendAvatarDataToAllAgents();
2794 TriggerScenePresenceUpdated();
2637 } 2795 }
2638 } 2796 }
2639 2797
2640 public void HandleAgentSitOnGround() 2798 public void HandleAgentSitOnGround()
2641 { 2799 {
2800 if (IsChildAgent)
2801 return;
2802
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 2803// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 2804 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 2805 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
2806 TriggerScenePresenceUpdated();
2645 SitGround = true; 2807 SitGround = true;
2646 RemoveFromPhysicalScene(); 2808 RemoveFromPhysicalScene();
2647 } 2809 }
@@ -2658,11 +2820,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 2820 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 2821 {
2660 Animator.AddAnimation(animID, UUID.Zero); 2822 Animator.AddAnimation(animID, UUID.Zero);
2823 TriggerScenePresenceUpdated();
2661 } 2824 }
2662 2825
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 2826 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 2827 {
2665 Animator.RemoveAnimation(animID, false); 2828 Animator.RemoveAnimation(animID, false);
2829 TriggerScenePresenceUpdated();
2666 } 2830 }
2667 2831
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 2832 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2880,11 +3044,12 @@ namespace OpenSim.Region.Framework.Scenes
2880 SendOtherAgentsAppearanceToMe(); 3044 SendOtherAgentsAppearanceToMe();
2881 3045
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3046 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3047 foreach (EntityBase e in entities)
2884 { 3048 {
2885 if (e != null && e is SceneObjectGroup) 3049 if (e != null && e is SceneObjectGroup)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3050 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3051 }
3052
2888 }); 3053 });
2889 } 3054 }
2890 3055
@@ -3079,11 +3244,10 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3244 }
3080 3245
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3246 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3247 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3248 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3249 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3250// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3251
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3252 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3253 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3110,7 +3274,7 @@ namespace OpenSim.Region.Framework.Scenes
3110 cadu.Velocity = Velocity; 3274 cadu.Velocity = Velocity;
3111 3275
3112 AgentPosition agentpos = new AgentPosition(); 3276 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3277 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3114 3278
3115 // Let's get this out of the update loop 3279 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3280 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3294,11 +3458,6 @@ namespace OpenSim.Region.Framework.Scenes
3294 } 3458 }
3295 } 3459 }
3296 3460
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 }
3301
3302 public void Reset() 3461 public void Reset()
3303 { 3462 {
3304// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3463// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3348,10 +3507,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 3507 if (byebyeRegions.Count > 0)
3349 { 3508 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 3509 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 3510
3352 { 3511 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 3512 string auth = string.Empty;
3354 }); 3513 if (acd != null)
3514 auth = acd.SessionID.ToString();
3515 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 3516 }
3356 3517
3357 foreach (ulong handle in byebyeRegions) 3518 foreach (ulong handle in byebyeRegions)
@@ -3452,6 +3613,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 3613
3453 cAgent.AgentID = UUID; 3614 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 3615 cAgent.RegionID = Scene.RegionInfo.RegionID;
3616 cAgent.SessionID = ControllingClient.SessionId;
3455 3617
3456 cAgent.Position = AbsolutePosition; 3618 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 3619 cAgent.Velocity = m_velocity;
@@ -3694,7 +3856,8 @@ namespace OpenSim.Region.Framework.Scenes
3694 3856
3695// if (m_updateCount > 0) 3857// if (m_updateCount > 0)
3696// { 3858// {
3697 Animator.UpdateMovementAnimations(); 3859 if (Animator.UpdateMovementAnimations())
3860 TriggerScenePresenceUpdated();
3698// m_updateCount--; 3861// m_updateCount--;
3699// } 3862// }
3700 3863
@@ -3858,6 +4021,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4021// Animator.Close();
3859 Animator = null; 4022 Animator = null;
3860 4023
4024 LifecycleState = ScenePresenceState.Removed;
3861 } 4025 }
3862 4026
3863 public void AddAttachment(SceneObjectGroup gobj) 4027 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
new file mode 100644
index 0000000..cae7fe5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Region.Framework.Scenes
31{
32 /// <summary>
33 /// The possible states that a scene presence can be in. This is currently orthagonal to whether a scene presence
34 /// is root or child.
35 /// </summary>
36 /// <remarks>
37 /// This is a state machine.
38 ///
39 /// [Entry] => Running
40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
42 /// Removing => Removed
43 ///
44 /// All other methods should only see the scene presence in running state - this is the normal operational state
45 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
46 /// </remarks>
47 public enum ScenePresenceState
48 {
49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
52 Removed, // The presence has been removed from the scene and is effectively dead.
53 // There is no exit from this state.
54 }
55
56 internal class ScenePresenceStateMachine
57 {
58 private ScenePresence m_sp;
59 private ScenePresenceState m_state;
60
61 internal ScenePresenceStateMachine(ScenePresence sp)
62 {
63 m_sp = sp;
64 m_state = ScenePresenceState.Running;
65 }
66
67 internal ScenePresenceState GetState()
68 {
69 return m_state;
70 }
71
72 /// <summary>
73 /// Updates the state of an agent that is already in transit.
74 /// </summary>
75 /// <param name='id'></param>
76 /// <param name='newState'></param>
77 /// <returns></returns>
78 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
79 internal void SetState(ScenePresenceState newState)
80 {
81 bool transitionOkay = false;
82
83 lock (this)
84 {
85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
97 transitionOkay = true;
98 }
99
100 if (!transitionOkay)
101 {
102 throw new Exception(
103 string.Format(
104 "Scene presence {0} is not allowed to move from state {1} to new state {2} in {3}",
105 m_sp.Name, m_state, newState, m_sp.Scene.Name));
106 }
107 else
108 {
109 m_state = newState;
110 }
111 }
112 }
113} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index ce4fb40..68918d3 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -1346,7 +1346,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1346 if (sop.MediaUrl != null) 1346 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1348 1348
1349 if (sop.DynAttrs.Count > 0) 1349 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1350 {
1351 writer.WriteStartElement("DynAttrs"); 1351 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer); 1352 sop.DynAttrs.WriteXml(writer);
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..bbe34d2 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -119,7 +119,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
119 119
120 UUID spUuid = TestHelpers.ParseTail(0x1); 120 UUID spUuid = TestHelpers.ParseTail(0x1);
121 121
122 // The etm is only invoked by this test to check whether an agent is still in transit if there is a dupe
123 EntityTransferModule etm = new EntityTransferModule();
124
125 IConfigSource config = new IniConfigSource();
126 IConfig modulesConfig = config.AddConfig("Modules");
127 modulesConfig.Set("EntityTransferModule", etm.Name);
128 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
129
130 // In order to run a single threaded regression test we do not want the entity transfer module waiting
131 // for a callback from the destination scene before removing its avatar data.
132 entityTransferConfig.Set("wait_for_callback", false);
133
122 TestScene scene = new SceneHelpers().SetupScene(); 134 TestScene scene = new SceneHelpers().SetupScene();
135 SceneHelpers.SetupSceneModules(scene, config, etm);
123 SceneHelpers.AddScenePresence(scene, spUuid); 136 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid); 137 SceneHelpers.AddScenePresence(scene, spUuid);
125 138
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
new file mode 100644
index 0000000..4ae7a8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -0,0 +1,88 @@
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
85 // TODO: Need to add tests for other ICapabiltiesModule methods.
86 }
87 }
88}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 8775949..12a778b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -95,11 +95,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
95 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 95 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
96 96
97 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 97 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
98 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 98 TestClient tc = new TestClient(acd, sceneA);
99 List<TestClient> destinationTestClients = new List<TestClient>(); 99 List<TestClient> destinationTestClients = new List<TestClient>();
100 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 100 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
101 101
102 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 102 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
103 originalSp.AbsolutePosition = new Vector3(128, 32, 10); 103 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
104 104
105// originalSp.Flying = true; 105// originalSp.Flying = true;
@@ -112,6 +112,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
112 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); 112 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
113 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); 113 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
114 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 114 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
115 moveArgs.SessionID = acd.SessionID;
115 116
116 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); 117 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
117 118
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/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index b09ae39..e60a025 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -34,6 +34,7 @@ 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;
@@ -180,6 +181,14 @@ namespace OpenSim.Region.Framework.Scenes
180 if (!assetUuids.ContainsKey(tii.AssetID)) 181 if (!assetUuids.ContainsKey(tii.AssetID))
181 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 182 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids);
182 } 183 }
184
185 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
186 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
187 // inventory transfer. There needs to be a way for a module to register a method without assuming a
188 // Scene.EventManager is present.
189// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
190
191 GatherMaterialsUuids(part, assetUuids);
183 } 192 }
184 catch (Exception e) 193 catch (Exception e)
185 { 194 {
@@ -205,6 +214,73 @@ namespace OpenSim.Region.Framework.Scenes
205// } 214// }
206 215
207 /// <summary> 216 /// <summary>
217 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
218 /// </summary>
219 /// <param name="part"></param>
220 /// <param name="assetUuids"></param>
221 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
222 {
223 // scan thru the dynAttrs map of this part for any textures used as materials
224 OSD osdMaterials = null;
225
226 lock (part.DynAttrs)
227 {
228 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
229 {
230 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
231
232 if (materialsStore == null)
233 return;
234
235 materialsStore.TryGetValue("Materials", out osdMaterials);
236 }
237
238 if (osdMaterials != null)
239 {
240 //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
241
242 if (osdMaterials is OSDArray)
243 {
244 OSDArray matsArr = osdMaterials as OSDArray;
245 foreach (OSDMap matMap in matsArr)
246 {
247 try
248 {
249 if (matMap.ContainsKey("Material"))
250 {
251 OSDMap mat = matMap["Material"] as OSDMap;
252 if (mat.ContainsKey("NormMap"))
253 {
254 UUID normalMapId = mat["NormMap"].AsUUID();
255 if (normalMapId != UUID.Zero)
256 {
257 assetUuids[normalMapId] = AssetType.Texture;
258 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
259 }
260 }
261 if (mat.ContainsKey("SpecMap"))
262 {
263 UUID specularMapId = mat["SpecMap"].AsUUID();
264 if (specularMapId != UUID.Zero)
265 {
266 assetUuids[specularMapId] = AssetType.Texture;
267 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
268 }
269 }
270 }
271
272 }
273 catch (Exception e)
274 {
275 m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message);
276 }
277 }
278 }
279 }
280 }
281 }
282
283 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 284 /// Get an asset synchronously, potentially using an asynchronous callback. If the
209 /// asynchronous callback is used, we will wait for it to complete. 285 /// asynchronous callback is used, we will wait for it to complete.
210 /// </summary> 286 /// </summary>