aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs11
-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/IInterregionComms.cs119
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs19
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs10
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs2
-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/MovementAnimationOverrides.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs390
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs226
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs200
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs43
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs915
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs1168
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs187
-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.cs673
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs328
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs374
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2659
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs62
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs90
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs175
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs167
46 files changed, 6239 insertions, 2798 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index 21ed44f..b536a49 100644
--- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -1,9 +1,30 @@
1//////////////////////////////////////////////////////////////// 1/*
2// 2 * Copyright (c) Contributors, http://opensimulator.org/
3// (c) 2009, 2010 Careminster Limited and Melanie Thielker 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4// 4 *
5// All rights reserved 5 * Redistribution and use in source and binary forms, with or without
6// 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
7using System; 28using System;
8using Nini.Config; 29using Nini.Config;
9using OpenSim.Framework; 30using OpenSim.Framework;
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 8028d87..eba881f 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -236,15 +236,17 @@ namespace OpenSim.Region.Framework.Interfaces
236 List<TaskInventoryItem> GetInventoryItems(InventoryType type); 236 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
237 237
238 /// <summary> 238 /// <summary>
239 /// Get the scene object referenced by an inventory item. 239 /// Get the scene object(s) referenced by an inventory item.
240 /// </summary> 240 /// </summary>
241 /// 241 ///
242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
243 /// been adjusted to reflect the part and item from which it originates. 243 /// been adjusted to reflect the part and item from which it originates.
244 /// 244 ///
245 /// <param name="item"></param> 245 /// <param name="item">Inventory item</param>
246 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns> 246 /// <param name="objlist">The scene objects</param>
247 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); 247 /// <param name="veclist">Relative offsets for each object</param>
248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1949a90..84cdc15 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Scenes;
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); 38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
39 public delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying);
39 40
40 public interface IEntityTransferModule 41 public interface IEntityTransferModule
41 { 42 {
@@ -47,13 +48,33 @@ namespace OpenSim.Region.Framework.Interfaces
47 /// The handle of the destination region. If it's the same as the region currently 48 /// The handle of the destination region. If it's the same as the region currently
48 /// occupied by the agent then the teleport will be within that region. 49 /// occupied by the agent then the teleport will be within that region.
49 /// </param> 50 /// </param>
51 /// <param name='agent'></param>
52 /// <param name='regionHandle'></param>
50 /// <param name='position'></param> 53 /// <param name='position'></param>
51 /// <param name='lookAt'></param> 54 /// <param name='lookAt'></param>
52 /// <param name='teleportFlags'></param> 55 /// <param name='teleportFlags'></param>
53 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); 56 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
54 57
58 /// <summary>
59 /// Teleports the agent for the given client to their home destination.
60 /// </summary>
61 /// <param name='id'></param>
62 /// <param name='client'></param>
55 bool TeleportHome(UUID id, IClientAPI client); 63 bool TeleportHome(UUID id, IClientAPI client);
56 64
65 /// <summary>
66 /// Teleport an agent directly to a given region without checking whether the region should be substituted.
67 /// </summary>
68 /// <remarks>
69 /// Please use Teleport() instead unless you know exactly what you're doing.
70 /// Do not use for same region teleports.
71 /// </remarks>
72 /// <param name='sp'></param>
73 /// <param name='reg'></param>
74 /// <param name='finalDestination'>/param>
75 /// <param name='position'></param>
76 /// <param name='lookAt'></param>
77 /// <param name='teleportFlags'></param>
57 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 78 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
58 Vector3 position, Vector3 lookAt, uint teleportFlags); 79 Vector3 position, Vector3 lookAt, uint teleportFlags);
59 80
@@ -72,9 +93,11 @@ namespace OpenSim.Region.Framework.Interfaces
72 93
73 void EnableChildAgent(ScenePresence agent, GridRegion region); 94 void EnableChildAgent(ScenePresence agent, GridRegion region);
74 95
75 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos); 96 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
76 97 GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos);
98 bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason);
77 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 99 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
100 bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent);
78 101
79 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); 102 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
80 103
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 292efa4..944c66b 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>
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 54
55 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); 56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
57
58 /// <summary>
59 /// Returns whether the transfer ID is being used for a terrain transfer.
60 /// </summary>
61 bool IsTerrainXfer(ulong xferID);
57 } 62 }
58} 63}
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index 5512642..dfc269e 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -39,21 +39,22 @@ namespace OpenSim.Region.Framework.Interfaces
39 39
40 // These are required to decouple Scenes from EventQueueHelper 40 // These are required to decouple Scenes from EventQueueHelper
41 void DisableSimulator(ulong handle, UUID avatarID); 41 void DisableSimulator(ulong handle, UUID avatarID);
42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID); 42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY);
43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, 43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint,
44 string capsPath); 44 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY);
45 void TeleportFinishEvent(ulong regionHandle, byte simAccess, 45 void TeleportFinishEvent(ulong regionHandle, byte simAccess,
46 IPEndPoint regionExternalEndPoint, 46 IPEndPoint regionExternalEndPoint,
47 uint locationID, uint flags, string capsURL, 47 uint locationID, uint flags, string capsURL,
48 UUID agentID); 48 UUID agentID, int regionSizeX, int regionSizeY);
49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
50 IPEndPoint newRegionExternalEndPoint, 50 IPEndPoint newRegionExternalEndPoint,
51 string capsURL, UUID avatarID, UUID sessionID); 51 string capsURL, UUID avatarID, UUID sessionID,
52 int regionSizeX, int regionSizeY);
52 void ChatterboxInvitation(UUID sessionID, string sessionName, 53 void ChatterboxInvitation(UUID sessionID, string sessionName,
53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 54 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
54 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 55 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
55 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); 56 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket);
56 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 57 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
57 bool isModerator, bool textMute); 58 bool isModerator, bool textMute);
58 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); 59 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 60 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/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
deleted file mode 100644
index 67a500f..0000000
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ /dev/null
@@ -1,119 +0,0 @@
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 OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 public delegate bool ChildAgentUpdateReceived(AgentData data);
35
36 public interface IInterregionCommsOut
37 {
38 #region Agents
39
40 bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit, uint teleportFlags, out string reason);
41
42 /// <summary>
43 /// Full child agent update.
44 /// </summary>
45 /// <param name="regionHandle"></param>
46 /// <param name="data"></param>
47 /// <returns></returns>
48 bool SendChildAgentUpdate(ulong regionHandle, AgentData data);
49
50 /// <summary>
51 /// Short child agent update, mostly for position.
52 /// </summary>
53 /// <param name="regionHandle"></param>
54 /// <param name="data"></param>
55 /// <returns></returns>
56 bool SendChildAgentUpdate(ulong regionHandle, AgentPosition data);
57
58 bool SendRetrieveRootAgent(ulong regionHandle, UUID id, out IAgentData agent);
59
60 /// <summary>
61 /// Message from receiving region to departing region, telling it got contacted by the client.
62 /// When sent over REST, it invokes the opaque uri.
63 /// </summary>
64 /// <param name="regionHandle"></param>
65 /// <param name="id"></param>
66 /// <param name="uri"></param>
67 /// <returns></returns>
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69
70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
79 /// Close agent.
80 /// </summary>
81 /// <param name="regionHandle"></param>
82 /// <param name="id"></param>
83 /// <returns></returns>
84 bool SendCloseAgent(ulong regionHandle, UUID id);
85
86 #endregion Agents
87
88 #region Objects
89
90 /// <summary>
91 /// Create an object in the destination region. This message is used primarily for prim crossing.
92 /// </summary>
93 /// <param name="regionHandle"></param>
94 /// <param name="sog"></param>
95 /// <param name="isLocalCall"></param>
96 /// <returns></returns>
97 bool SendCreateObject(ulong regionHandle, SceneObjectGroup sog, bool isLocalCall);
98
99 /// <summary>
100 /// Create an object from the user's inventory in the destination region.
101 /// This message is used primarily by clients.
102 /// </summary>
103 /// <param name="regionHandle"></param>
104 /// <param name="userID"></param>
105 /// <param name="itemID"></param>
106 /// <returns></returns>
107 bool SendCreateObject(ulong regionHandle, UUID userID, UUID itemID);
108
109 #endregion Objects
110
111 }
112
113 // This may not be needed, but having it here for now.
114 public interface IInterregionCommsIn
115 {
116 event ChildAgentUpdateReceived OnChildAgentUpdate;
117 }
118
119}
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index b67312e..1a89721 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -51,10 +51,17 @@ namespace OpenSim.Region.Framework.Interfaces
51 UUID = 5 51 UUID = 5
52 } 52 }
53 53
54 public struct JsonStoreStats
55 {
56 public int StoreCount;
57 }
58
54 public delegate void TakeValueCallback(string s); 59 public delegate void TakeValueCallback(string s);
55 60
56 public interface IJsonStoreModule 61 public interface IJsonStoreModule
57 { 62 {
63 JsonStoreStats GetStoreStats();
64
58 bool AttachObjectStore(UUID objectID); 65 bool AttachObjectStore(UUID objectID);
59 bool CreateStore(string value, ref UUID result); 66 bool CreateStore(string value, ref UUID result);
60 bool DestroyStore(UUID storeID); 67 bool DestroyStore(UUID storeID);
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..f7c6513 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Interfaces
95 /// <param name="radius">Sound radius</param> 95 /// <param name="radius">Sound radius</param>
96 /// <param name="isMaster">Set object to sync master if true</param> 96 /// <param name="isMaster">Set object to sync master if true</param>
97 void LoopSound(UUID objectID, UUID soundID, double gain, 97 void LoopSound(UUID objectID, UUID soundID, double gain,
98 double radius, bool isMaster); 98 double radius, bool isMaster, bool isSlave);
99 99
100 /// <summary> 100 /// <summary>
101 /// Trigger or play an attached sound in this part's inventory. 101 /// Trigger or play an attached sound in this part's inventory.
@@ -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/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index 167c248..a2a99d4 100644
--- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
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/MovementAnimationOverrides.cs b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
new file mode 100644
index 0000000..31fdb2c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
@@ -0,0 +1,101 @@
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.Xml;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Framework.Client;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes.Animation;
42using OpenSim.Region.Framework.Scenes.Types;
43using OpenSim.Region.Physics.Manager;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenSim.Services.Interfaces;
46using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
47
48namespace OpenSim.Region.Framework.Scenes
49{
50 public class MovementAnimationOverrides
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private Dictionary<string, UUID> m_overrides = new Dictionary<string, UUID>();
56 public void SetOverride(string state, UUID animID)
57 {
58 if (animID == UUID.Zero)
59 {
60 if (state == "ALL")
61 m_overrides.Clear();
62 else
63 m_overrides.Remove(state);
64 return;
65 }
66
67 m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
68
69 lock (m_overrides)
70 m_overrides[state] = animID;
71 }
72
73 public UUID GetOverriddenAnimation(string state)
74 {
75 lock (m_overrides)
76 {
77 if (m_overrides.ContainsKey(state))
78 return m_overrides[state];
79 }
80
81 return UUID.Zero;
82 }
83
84 public Dictionary<string, UUID> CloneAOPairs()
85 {
86 lock (m_overrides)
87 {
88 return new Dictionary<string, UUID>(m_overrides);
89 }
90 }
91
92 public void CopyAOPairsFrom(Dictionary<string, UUID> src)
93 {
94 lock (m_overrides)
95 {
96 m_overrides.Clear();
97 m_overrides = new Dictionary<string, UUID>(src);
98 }
99 }
100 }
101}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 65c279e..ade908d 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
48 48
49 public AnimationSet Animations 49 public AnimationSet Animations
50 { 50 {
51 get { return m_animations; } 51 get { return m_animations; }
52 } 52 }
53 protected AnimationSet m_animations = new AnimationSet(); 53 protected AnimationSet m_animations = new AnimationSet();
54 54
@@ -56,25 +56,27 @@ namespace OpenSim.Region.Framework.Scenes.Animation
56 /// The current movement animation 56 /// The current movement animation
57 /// </value> 57 /// </value>
58 public string CurrentMovementAnimation { get; private set; } 58 public string CurrentMovementAnimation { get; private set; }
59 59
60 private int m_animTickFall; 60 private int m_animTickFall;
61 public int m_animTickJump; // ScenePresence has to see this to control +Z force 61 private int m_animTickLand;
62 public bool m_jumping = false; 62 private int m_animTickJump;
63 public float m_jumpVelocity = 0f; 63
64// private int m_landing = 0; 64 public bool m_jumping = false;
65
66 // private int m_landing = 0;
65 67
66 /// <summary> 68 /// <summary>
67 /// Is the avatar falling? 69 /// Is the avatar falling?
68 /// </summary> 70 /// </summary>
69 public bool Falling { get; private set; } 71 public bool Falling { get; private set; }
70 72
71 private float m_fallHeight; 73 private float m_lastFallVelocity;
72 74
73 /// <value> 75 /// <value>
74 /// The scene presence that this animator applies to 76 /// The scene presence that this animator applies to
75 /// </value> 77 /// </value>
76 protected ScenePresence m_scenePresence; 78 protected ScenePresence m_scenePresence;
77 79
78 public ScenePresenceAnimator(ScenePresence sp) 80 public ScenePresenceAnimator(ScenePresence sp)
79 { 81 {
80 m_scenePresence = sp; 82 m_scenePresence = sp;
@@ -89,11 +91,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
89 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name); 91 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
90 if (m_scenePresence.Scene.DebugAnimations) 92 if (m_scenePresence.Scene.DebugAnimations)
91 m_log.DebugFormat( 93 m_log.DebugFormat(
92 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", 94 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}",
93 GetAnimName(animID), animID, m_scenePresence.Name); 95 GetAnimName(animID), animID, m_scenePresence.Name);
94 96
95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 97 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
98 {
96 SendAnimPack(); 99 SendAnimPack();
100 m_scenePresence.TriggerScenePresenceUpdated();
101 }
97 } 102 }
98 103
99 // Called from scripts 104 // Called from scripts
@@ -108,7 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
108 if (animID == UUID.Zero) 113 if (animID == UUID.Zero)
109 return; 114 return;
110 115
111// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name); 116 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name);
112 117
113 AddAnimation(animID, objectID); 118 AddAnimation(animID, objectID);
114 } 119 }
@@ -128,11 +133,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
128 133
129 if (m_scenePresence.Scene.DebugAnimations) 134 if (m_scenePresence.Scene.DebugAnimations)
130 m_log.DebugFormat( 135 m_log.DebugFormat(
131 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}", 136 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}",
132 GetAnimName(animID), animID, m_scenePresence.Name); 137 GetAnimName(animID), animID, m_scenePresence.Name);
133 138
134 if (m_animations.Remove(animID, allowNoDefault)) 139 if (m_animations.Remove(animID, allowNoDefault))
140 {
135 SendAnimPack(); 141 SendAnimPack();
142 m_scenePresence.TriggerScenePresenceUpdated();
143 }
136 } 144 }
137 145
138 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) 146 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
@@ -145,9 +153,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
145 if (addRemove) 153 if (addRemove)
146 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero); 154 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
147 else 155 else
148 m_animations.Remove(animID, true); 156 m_animations.Remove(animID, false);
149 } 157 }
150 if(sendPack) 158 if (sendPack)
151 SendAnimPack(); 159 SendAnimPack();
152 } 160 }
153 161
@@ -175,29 +183,72 @@ namespace OpenSim.Region.Framework.Scenes.Animation
175 183
176 m_animations.Clear(); 184 m_animations.Clear();
177 } 185 }
178 186
187
188 UUID aoSitGndAnim = UUID.Zero;
189
179 /// <summary> 190 /// <summary>
180 /// The movement animation is reserved for "main" animations 191 /// The movement animation is reserved for "main" animations
181 /// that are mutually exclusive, e.g. flying and sitting. 192 /// that are mutually exclusive, e.g. flying and sitting.
182 /// </summary> 193 /// </summary>
183 public void TrySetMovementAnimation(string anim) 194 /// <returns>'true' if the animation was updated</returns>
195 ///
196
197
198
199 public bool TrySetMovementAnimation(string anim)
184 { 200 {
201 bool ret = false;
185 if (!m_scenePresence.IsChildAgent) 202 if (!m_scenePresence.IsChildAgent)
186 { 203 {
187// m_log.DebugFormat( 204// m_log.DebugFormat(
188// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", 205// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}",
189// anim, m_scenePresence.Name); 206// anim, m_scenePresence.Name);
190 207
191 if (m_animations.TrySetDefaultAnimation( 208 if (aoSitGndAnim != UUID.Zero)
192 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) 209 {
210 avnChangeAnim(aoSitGndAnim, false, true);
211 aoSitGndAnim = UUID.Zero;
212 }
213
214 UUID overridenAnim = m_scenePresence.Overrides.GetOverriddenAnimation(anim);
215 if (overridenAnim != UUID.Zero)
216 {
217 if (anim == "SITGROUND")
218 {
219 UUID defsit = DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"];
220 if (defsit == UUID.Zero)
221 return false;
222 m_animations.SetDefaultAnimation(defsit, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID);
223 aoSitGndAnim = overridenAnim;
224 avnChangeAnim(overridenAnim, true, false);
225 }
226 else
227 {
228 m_animations.SetDefaultAnimation(overridenAnim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID);
229 }
230 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
231 SendAnimPack();
232 ret = true;
233 }
234 else
193 { 235 {
236 // translate sit and sitground state animations
237 if (anim == "SIT" || anim == "SITGROUND")
238 anim = m_scenePresence.sitAnimation;
239
240 if (m_animations.TrySetDefaultAnimation(
241 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
242 {
194// m_log.DebugFormat( 243// m_log.DebugFormat(
195// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}", 244// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}",
196// anim, m_scenePresence.Name); 245// anim, m_scenePresence.Name);
197 246
198 // 16384 is CHANGED_ANIMATION 247 // 16384 is CHANGED_ANIMATION
199 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 248 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
200 SendAnimPack(); 249 SendAnimPack();
250 ret = true;
251 }
201 } 252 }
202 } 253 }
203 else 254 else
@@ -206,80 +257,122 @@ namespace OpenSim.Region.Framework.Scenes.Animation
206 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", 257 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
207 anim, m_scenePresence.Name); 258 anim, m_scenePresence.Name);
208 } 259 }
260 return ret;
261 }
262
263 public enum motionControlStates : byte
264 {
265 sitted = 0,
266 flying,
267 falling,
268 jumping,
269 landing,
270 onsurface
209 } 271 }
210 272
273 public motionControlStates currentControlState = motionControlStates.onsurface;
274
211 /// <summary> 275 /// <summary>
212 /// This method determines the proper movement related animation 276 /// This method determines the proper movement related animation
213 /// </summary> 277 /// </summary>
214 private string DetermineMovementAnimation() 278 private string DetermineMovementAnimation()
215 { 279 {
216 const float FALL_DELAY = 800f; 280 const int FALL_DELAY = 800;
217 const float PREJUMP_DELAY = 200f; 281 const int PREJUMP_DELAY = 200;
218 const float JUMP_PERIOD = 800f; 282 const int JUMP_PERIOD = 800;
219 #region Inputs 283 #region Inputs
220 284
285 if (m_scenePresence.IsInTransit)
286 return CurrentMovementAnimation;
287
288 if (m_scenePresence.SitGround)
289 {
290 currentControlState = motionControlStates.sitted;
291 return "SITGROUND";
292 }
293 if (m_scenePresence.ParentID != 0 || m_scenePresence.ParentUUID != UUID.Zero)
294 {
295 currentControlState = motionControlStates.sitted;
296 return "SIT";
297 }
298
221 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 299 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
222 PhysicsActor actor = m_scenePresence.PhysicsActor; 300 PhysicsActor actor = m_scenePresence.PhysicsActor;
223 301
224 // Create forward and left vectors from the current avatar rotation 302 const AgentManager.ControlFlags ANYXYMASK = (
225 Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation); 303 AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS |
226 Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix); 304 AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG |
227 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 305 AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS |
306 AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG
307 );
228 308
229 // Check control flags 309 // Check control flags
230 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); 310 /* not in use
231 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); 311 bool heldForward = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)) != 0);
232 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); 312 bool heldBack = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG)) != 0);
233 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); 313 bool heldLeft = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS)) != 0);
314 bool heldRight = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG)) != 0);
315 */
234 bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 316 bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
235 bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 317 bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
236 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 318 // bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS)) != 0);
237 bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; 319 // excluded nudge up so it doesn't trigger jump state
320 bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS)) != 0);
321 bool heldDown = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG)) != 0);
238 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY; 322 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
239 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK; 323 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
240 if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown) 324
325 bool heldOnXY = ((controlFlags & ANYXYMASK) != 0);
326 if (heldOnXY || heldUp || heldDown)
241 { 327 {
242 heldTurnLeft = false; 328 heldTurnLeft = false;
243 heldTurnRight = false; 329 heldTurnRight = false;
244 } 330 }
245 331
246 // Direction in which the avatar is trying to move
247 Vector3 move = Vector3.Zero;
248 if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
249 if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
250 if (heldLeft) { move.X += left.X; move.Y += left.Y; }
251 if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
252 if (heldUp) { move.Z += 1; }
253 if (heldDown) { move.Z -= 1; }
254
255 // Is the avatar trying to move?
256// bool moving = (move != Vector3.Zero);
257 #endregion Inputs 332 #endregion Inputs
258 333
334 // no physics actor case
335 if (actor == null)
336 {
337 // well what to do?
338
339 currentControlState = motionControlStates.onsurface;
340 if (heldOnXY)
341 return "WALK";
342
343 return "STAND";
344 }
345
259 #region Flying 346 #region Flying
260 347
261 if (actor != null && actor.Flying) 348 bool isColliding = actor.IsColliding;
349
350 if (actor.Flying)
262 { 351 {
263 m_animTickFall = 0; 352 m_animTickFall = 0;
264 m_animTickJump = 0; 353 m_animTickJump = 0;
265 m_jumping = false; 354 m_jumping = false;
266 Falling = false; 355 Falling = false;
267 m_jumpVelocity = 0f;
268 actor.Selected = false;
269 m_fallHeight = actor.Position.Z; // save latest flying height
270 356
271 if (move.X != 0f || move.Y != 0f) 357 currentControlState = motionControlStates.flying;
358
359 if (heldOnXY)
272 { 360 {
273 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); 361 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
274 } 362 }
275 else if (move.Z > 0f) 363 else if (heldUp)
276 { 364 {
277 return "HOVER_UP"; 365 return "HOVER_UP";
278 } 366 }
279 else if (move.Z < 0f) 367 else if (heldDown)
280 { 368 {
281 if (actor != null && actor.IsColliding) 369 if (isColliding)
370 {
371 actor.Flying = false;
372 currentControlState = motionControlStates.landing;
373 m_animTickLand = Environment.TickCount;
282 return "LAND"; 374 return "LAND";
375 }
283 else 376 else
284 return "HOVER_DOWN"; 377 return "HOVER_DOWN";
285 } 378 }
@@ -288,139 +381,161 @@ namespace OpenSim.Region.Framework.Scenes.Animation
288 return "HOVER"; 381 return "HOVER";
289 } 382 }
290 } 383 }
384 else
385 {
386 if (isColliding && currentControlState == motionControlStates.flying)
387 {
388 currentControlState = motionControlStates.landing;
389 m_animTickLand = Environment.TickCount;
390 return "LAND";
391 }
392 }
291 393
292 #endregion Flying 394 #endregion Flying
293 395
294 #region Falling/Floating/Landing 396 #region Falling/Floating/Landing
295 397
296 if ((actor == null || !actor.IsColliding) && !m_jumping) 398 if (!isColliding && currentControlState != motionControlStates.jumping)
297 { 399 {
298 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); 400 float fallVelocity = actor.Velocity.Z;
299 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
300 401
301 if (!m_jumping && (fallVelocity < -3.0f)) 402 if (fallVelocity < -2.5f)
302 Falling = true; 403 Falling = true;
303 404
304 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) 405 if (m_animTickFall == 0 || (fallVelocity >= -0.5f))
305 { 406 {
306 // not falling yet, or going up
307 // reset start of fall time
308 m_animTickFall = Environment.TickCount; 407 m_animTickFall = Environment.TickCount;
309 } 408 }
310 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) 409 else
311 { 410 {
312 // Falling long enough to trigger the animation 411 int fallElapsed = (Environment.TickCount - m_animTickFall);
313 return "FALLDOWN"; 412 if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f))
413 {
414 currentControlState = motionControlStates.falling;
415 m_lastFallVelocity = fallVelocity;
416 // Falling long enough to trigger the animation
417 return "FALLDOWN";
418 }
314 } 419 }
315 420
316 // Check if the user has stopped walking just now 421 // Check if the user has stopped walking just now
317 if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) 422 if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp)
318 return "STAND"; 423 return "STAND";
319 424
320 return CurrentMovementAnimation; 425 return CurrentMovementAnimation;
321 } 426 }
322 427
323 #endregion Falling/Floating/Landing 428 m_animTickFall = 0;
324 429
430 #endregion Falling/Floating/Landing
325 431
326 #region Jumping // section added for jumping... 432 #region Jumping // section added for jumping...
327 433
328 int jumptime; 434 if (isColliding && heldUp && currentControlState != motionControlStates.jumping)
329 jumptime = Environment.TickCount - m_animTickJump;
330
331 if ((move.Z > 0f) && (!m_jumping))
332 { 435 {
333 // Start jumping, prejump 436 // Start jumping, prejump
334 m_animTickFall = 0; 437 currentControlState = motionControlStates.jumping;
335 m_jumping = true; 438 m_jumping = true;
336 Falling = false; 439 Falling = false;
337 actor.Selected = true; // borrowed for jumping flag
338 m_animTickJump = Environment.TickCount; 440 m_animTickJump = Environment.TickCount;
339 m_jumpVelocity = 0.35f;
340 return "PREJUMP"; 441 return "PREJUMP";
341 } 442 }
342 443
343 if (m_jumping) 444 if (currentControlState == motionControlStates.jumping)
344 { 445 {
446 int jumptime = Environment.TickCount - m_animTickJump;
345 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) 447 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
346 { 448 {
347 // end jumping 449 // end jumping
348 m_jumping = false; 450 m_jumping = false;
349 Falling = false; 451 Falling = false;
350 actor.Selected = false; // borrowed for jumping flag 452 actor.Selected = false; // borrowed for jumping flag
351 m_jumpVelocity = 0f; 453 m_animTickLand = Environment.TickCount;
352 m_animTickFall = Environment.TickCount; 454 currentControlState = motionControlStates.landing;
353 return "LAND"; 455 return "LAND";
354 } 456 }
355 else if (jumptime > JUMP_PERIOD) 457 else if (jumptime > JUMP_PERIOD)
356 { 458 {
357 // jump down 459 // jump down
358 m_jumpVelocity = 0f;
359 return "JUMP"; 460 return "JUMP";
360 } 461 }
361 else if (jumptime > PREJUMP_DELAY) 462 else if (jumptime > PREJUMP_DELAY)
362 { 463 {
363 // jump up 464 // jump up
364 m_jumping = true; 465 m_jumping = true;
365 m_jumpVelocity = 10f;
366 return "JUMP"; 466 return "JUMP";
367 } 467 }
468 return CurrentMovementAnimation;
368 } 469 }
369 470
370 #endregion Jumping 471 #endregion Jumping
371 472
372 #region Ground Movement 473 #region Ground Movement
373 474
374 if (CurrentMovementAnimation == "FALLDOWN") 475 if (currentControlState == motionControlStates.falling)
375 { 476 {
376 Falling = false; 477 Falling = false;
377 m_animTickFall = Environment.TickCount; 478 currentControlState = motionControlStates.landing;
479 m_animTickLand = Environment.TickCount;
378 // TODO: SOFT_LAND support 480 // TODO: SOFT_LAND support
379 float fallHeight = m_fallHeight - actor.Position.Z; 481 float fallVsq = m_lastFallVelocity * m_lastFallVelocity;
380 if (fallHeight > 15.0f) 482 if (fallVsq > 300f) // aprox 20*h
381 return "STANDUP"; 483 return "STANDUP";
382 else if (fallHeight > 8.0f) 484 else if (fallVsq > 160f)
383 return "SOFT_LAND"; 485 return "SOFT_LAND";
384 else 486 else
385 return "LAND"; 487 return "LAND";
386 } 488 }
387 else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) 489
490
491 if (currentControlState == motionControlStates.landing)
388 { 492 {
389 int landElapsed = Environment.TickCount - m_animTickFall; 493 Falling = false;
494 int landElapsed = Environment.TickCount - m_animTickLand;
390 int limit = 1000; 495 int limit = 1000;
391 if (CurrentMovementAnimation == "LAND") 496 if (CurrentMovementAnimation == "LAND")
392 limit = 350; 497 limit = 350;
393 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client 498 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
394 499
395 if ((m_animTickFall != 0) && (landElapsed <= limit)) 500 if ((m_animTickLand != 0) && (landElapsed <= limit))
396 { 501 {
397 return CurrentMovementAnimation; 502 return CurrentMovementAnimation;
398 } 503 }
399 else 504 else
400 { 505 {
401 m_fallHeight = actor.Position.Z; // save latest flying height 506 currentControlState = motionControlStates.onsurface;
507 m_animTickLand = 0;
402 return "STAND"; 508 return "STAND";
403 } 509 }
404 } 510 }
405 511
406 // next section moved outside paren. and realigned for jumping 512 // next section moved outside paren. and realigned for jumping
407 if (move.X != 0f || move.Y != 0f) 513
514 if (heldOnXY)
408 { 515 {
409 m_fallHeight = actor.Position.Z; // save latest flying height 516 currentControlState = motionControlStates.onsurface;
410 Falling = false; 517 Falling = false;
411 // Walking / crouchwalking / running 518 // Walking / crouchwalking / running
412 if (move.Z < 0f) 519 if (heldDown)
520 {
413 return "CROUCHWALK"; 521 return "CROUCHWALK";
414 else if (m_scenePresence.SetAlwaysRun) 522 }
415 return "RUN"; 523 // We need to prevent these animations if the user tries to make their avatar walk or run whilst
416 else 524 // specifying AGENT_CONTROL_STOP (pressing down space on viewers).
417 return "WALK"; 525 else if (!m_scenePresence.AgentControlStopActive)
526 {
527 if (m_scenePresence.SetAlwaysRun)
528 return "RUN";
529 else
530 return "WALK";
531 }
418 } 532 }
419 else if (!m_jumping) 533 else
420 { 534 {
535 currentControlState = motionControlStates.onsurface;
421 Falling = false; 536 Falling = false;
422 // Not walking 537 // Not walking
423 if (move.Z < 0) 538 if (heldDown)
424 return "CROUCH"; 539 return "CROUCH";
425 else if (heldTurnLeft) 540 else if (heldTurnLeft)
426 return "TURNLEFT"; 541 return "TURNLEFT";
@@ -431,22 +546,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation
431 } 546 }
432 #endregion Ground Movement 547 #endregion Ground Movement
433 548
434 Falling = false;
435
436 return CurrentMovementAnimation; 549 return CurrentMovementAnimation;
437 } 550 }
438 551
439 /// <summary> 552 /// <summary>
440 /// Update the movement animation of this avatar according to its current state 553 /// Update the movement animation of this avatar according to its current state
441 /// </summary> 554 /// </summary>
442 public void UpdateMovementAnimations() 555 /// <returns>'true' if the animation was changed</returns>
556 public bool UpdateMovementAnimations()
443 { 557 {
558 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
559
560 bool ret = false;
444 lock (m_animations) 561 lock (m_animations)
445 { 562 {
446 string newMovementAnimation = DetermineMovementAnimation(); 563 string newMovementAnimation = DetermineMovementAnimation();
447 if (CurrentMovementAnimation != newMovementAnimation) 564 if (CurrentMovementAnimation != newMovementAnimation)
448 { 565 {
449 CurrentMovementAnimation = DetermineMovementAnimation(); 566 CurrentMovementAnimation = newMovementAnimation;
450 567
451// m_log.DebugFormat( 568// m_log.DebugFormat(
452// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", 569// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
@@ -454,9 +571,28 @@ namespace OpenSim.Region.Framework.Scenes.Animation
454 571
455 // Only set it if it's actually changed, give a script 572 // Only set it if it's actually changed, give a script
456 // a chance to stop a default animation 573 // a chance to stop a default animation
457 TrySetMovementAnimation(CurrentMovementAnimation); 574 ret = TrySetMovementAnimation(CurrentMovementAnimation);
458 } 575 }
459 } 576 }
577 return ret;
578 }
579
580 public bool ForceUpdateMovementAnimations()
581 {
582 lock (m_animations)
583 {
584 CurrentMovementAnimation = DetermineMovementAnimation();
585 return TrySetMovementAnimation(CurrentMovementAnimation);
586 }
587 }
588
589 public bool SetMovementAnimations(string motionState)
590 {
591 lock (m_animations)
592 {
593 CurrentMovementAnimation = motionState;
594 return TrySetMovementAnimation(CurrentMovementAnimation);
595 }
460 } 596 }
461 597
462 public UUID[] GetAnimationArray() 598 public UUID[] GetAnimationArray()
@@ -467,19 +603,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
467 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 603 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
468 return animIDs; 604 return animIDs;
469 } 605 }
470 606
471 public BinBVHAnimation GenerateRandomAnimation() 607 public BinBVHAnimation GenerateRandomAnimation()
472 { 608 {
473 int rnditerations = 3; 609 int rnditerations = 3;
474 BinBVHAnimation anim = new BinBVHAnimation(); 610 BinBVHAnimation anim = new BinBVHAnimation();
475 List<string> parts = new List<string>(); 611 List<string> parts = new List<string>();
476 parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); 612 parts.Add("mPelvis"); parts.Add("mHead"); parts.Add("mTorso");
477 parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft"); 613 parts.Add("mHipLeft"); parts.Add("mHipRight"); parts.Add("mHipLeft"); parts.Add("mKneeLeft");
478 parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck"); 614 parts.Add("mKneeRight"); parts.Add("mCollarLeft"); parts.Add("mCollarRight"); parts.Add("mNeck");
479 parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight"); 615 parts.Add("mElbowLeft"); parts.Add("mElbowRight"); parts.Add("mWristLeft"); parts.Add("mWristRight");
480 parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight"); 616 parts.Add("mShoulderLeft"); parts.Add("mShoulderRight"); parts.Add("mAnkleLeft"); parts.Add("mAnkleRight");
481 parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight"); 617 parts.Add("mEyeRight"); parts.Add("mChest"); parts.Add("mToeLeft"); parts.Add("mToeRight");
482 parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); 618 parts.Add("mFootLeft"); parts.Add("mFootRight"); parts.Add("mEyeLeft");
483 anim.HandPose = 1; 619 anim.HandPose = 1;
484 anim.InPoint = 0; 620 anim.InPoint = 0;
485 anim.OutPoint = (rnditerations * .10f); 621 anim.OutPoint = (rnditerations * .10f);
@@ -503,12 +639,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
503 for (int i = 0; i < rnditerations; i++) 639 for (int i = 0; i < rnditerations; i++)
504 { 640 {
505 anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); 641 anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
506 anim.Joints[j].rotationkeys[i].time = (i*.10f); 642 anim.Joints[j].rotationkeys[i].time = (i * .10f);
507 anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1); 643 anim.Joints[j].rotationkeys[i].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
508 anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1); 644 anim.Joints[j].rotationkeys[i].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
509 anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1); 645 anim.Joints[j].rotationkeys[i].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
510 anim.Joints[j].positionkeys[i] = new binBVHJointKey(); 646 anim.Joints[j].positionkeys[i] = new binBVHJointKey();
511 anim.Joints[j].positionkeys[i].time = (i*.10f); 647 anim.Joints[j].positionkeys[i].time = (i * .10f);
512 anim.Joints[j].positionkeys[i].key_element.X = 0; 648 anim.Joints[j].positionkeys[i].key_element.X = 0;
513 anim.Joints[j].positionkeys[i].key_element.Y = 0; 649 anim.Joints[j].positionkeys[i].key_element.Y = 0;
514 anim.Joints[j].positionkeys[i].key_element.Z = 0; 650 anim.Joints[j].positionkeys[i].key_element.Z = 0;
@@ -535,20 +671,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
535 /// <param name="objectIDs"></param> 671 /// <param name="objectIDs"></param>
536 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) 672 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
537 { 673 {
538 if (m_scenePresence.IsChildAgent) 674 m_scenePresence.SendAnimPack(animations, seqs, objectIDs);
539 return; 675 }
540 676
541// m_log.DebugFormat( 677 public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs)
542// "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'", 678 {
543// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), 679 animIDs = null;
544// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), 680 sequenceNums = null;
545// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); 681 objectIDs = null;
546 682
547 m_scenePresence.Scene.ForEachClient( 683 if (m_animations != null)
548 delegate(IClientAPI client) 684 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
549 {
550 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
551 });
552 } 685 }
553 686
554 public void SendAnimPackToClient(IClientAPI client) 687 public void SendAnimPackToClient(IClientAPI client)
@@ -570,7 +703,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
570 public void SendAnimPack() 703 public void SendAnimPack()
571 { 704 {
572 //m_log.Debug("Sending animation pack to all"); 705 //m_log.Debug("Sending animation pack to all");
573 706
574 if (m_scenePresence.IsChildAgent) 707 if (m_scenePresence.IsChildAgent)
575 return; 708 return;
576 709
@@ -580,7 +713,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
580 713
581 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 714 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
582 715
583 SendAnimPack(animIDs, sequenceNums, objectIDs); 716 // SendAnimPack(animIDs, sequenceNums, objectIDs);
717 m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs);
584 } 718 }
585 719
586 public string GetAnimName(UUID animId) 720 public string GetAnimName(UUID animId)
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index f555b49..11a0146 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
109 foreach (SceneObjectGroup g in objectGroups) 107 foreach (SceneObjectGroup g in objectGroups)
110 { killIDs.Add(g.LocalId); 108 g.DeleteGroupFromScene(false);
111 g.DeleteGroupFromScene(true);
112 }
113
114 m_scene.SendKillObject(killIDs);
115 } 109 }
116 } 110 }
117 111
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
160 if (x.permissionToDelete) 154 if (x.permissionToDelete)
161 { 155 {
162 foreach (SceneObjectGroup g in x.objectGroups) 156 foreach (SceneObjectGroup g in x.objectGroups)
163 m_scene.DeleteSceneObject(g, false); 157 m_scene.DeleteSceneObject(g, true);
164 } 158 }
165 } 159 }
166 catch (Exception e) 160 catch (Exception e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 4733547..692e0c9 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes
148 /// Triggered when a new presence is added to the scene 148 /// Triggered when a new presence is added to the scene
149 /// </summary> 149 /// </summary>
150 /// <remarks> 150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks> 153 /// </remarks>
154 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
@@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes
159 /// Triggered when a presence is removed from the scene 159 /// Triggered when a presence is removed from the scene
160 /// </summary> 160 /// </summary>
161 /// <remarks> 161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 /// 164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please 165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
@@ -743,7 +743,7 @@ namespace OpenSim.Region.Framework.Scenes
743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; 743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject;
744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); 744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so);
745 745
746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel);
747 747
748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; 748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
749 749
@@ -974,6 +974,8 @@ namespace OpenSim.Region.Framework.Scenes
974 public delegate void RegionStarted(Scene scene); 974 public delegate void RegionStarted(Scene scene);
975 public event RegionStarted OnRegionStarted; 975 public event RegionStarted OnRegionStarted;
976 976
977 public delegate void RegionHeartbeatStart(Scene scene);
978 public event RegionHeartbeatStart OnRegionHeartbeatStart;
977 public delegate void RegionHeartbeatEnd(Scene scene); 979 public delegate void RegionHeartbeatEnd(Scene scene);
978 public event RegionHeartbeatEnd OnRegionHeartbeatEnd; 980 public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
979 981
@@ -1024,6 +1026,16 @@ namespace OpenSim.Region.Framework.Scenes
1024 /// </remarks> 1026 /// </remarks>
1025 public event TeleportFail OnTeleportFail; 1027 public event TeleportFail OnTeleportFail;
1026 1028
1029// public delegate void GatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids);
1030//
1031// /// <summary>
1032// /// Triggered when UUIDs referenced by a scene object are being gathered for archiving, hg transfer, etc.
1033// /// </summary>
1034// /// <remarks>
1035// /// The listener should add references to the IDictionary<UUID, AssetType> as appropriate.
1036// /// </remarks>
1037// public event GatherUuids OnGatherUuids;
1038
1027 public class MoneyTransferArgs : EventArgs 1039 public class MoneyTransferArgs : EventArgs
1028 { 1040 {
1029 public UUID sender; 1041 public UUID sender;
@@ -1095,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
1095 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> 1107 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1096 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> 1108 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1097 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> 1109 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1098 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> 1110 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/>
1099 /// </remarks> 1111 /// </remarks>
1100 public event MoneyTransferEvent OnMoneyTransfer; 1112 public event MoneyTransferEvent OnMoneyTransfer;
1101 1113
@@ -1354,7 +1366,9 @@ namespace OpenSim.Region.Framework.Scenes
1354 { 1366 {
1355 try 1367 try
1356 { 1368 {
1369// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate: {0}",d.Target.ToString());
1357 d(agentId); 1370 d(agentId);
1371// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate done ");
1358 } 1372 }
1359 catch (Exception e) 1373 catch (Exception e)
1360 { 1374 {
@@ -2025,7 +2039,10 @@ namespace OpenSim.Region.Framework.Scenes
2025 { 2039 {
2026 try 2040 try
2027 { 2041 {
2042// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed: {0}", d.Target.ToString());
2028 d(ClientID, scene); 2043 d(ClientID, scene);
2044// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed done ");
2045
2029 } 2046 }
2030 catch (Exception e) 2047 catch (Exception e)
2031 { 2048 {
@@ -2160,7 +2177,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 } 2177 }
2161 } 2178 }
2162 2179
2163 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) 2180 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel)
2164 { 2181 {
2165 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2182 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2166 if (handlerNewInventoryItemUpdateComplete != null) 2183 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2169,7 +2186,7 @@ namespace OpenSim.Region.Framework.Scenes
2169 { 2186 {
2170 try 2187 try
2171 { 2188 {
2172 d(agentID, AssetID, AssetName, userlevel); 2189 d(agentID, type, AssetID, AssetName, userlevel);
2173 } 2190 }
2174 catch (Exception e) 2191 catch (Exception e)
2175 { 2192 {
@@ -3096,6 +3113,27 @@ namespace OpenSim.Region.Framework.Scenes
3096 } 3113 }
3097 } 3114 }
3098 3115
3116 public void TriggerRegionHeartbeatStart(Scene scene)
3117 {
3118 RegionHeartbeatStart handler = OnRegionHeartbeatStart;
3119
3120 if (handler != null)
3121 {
3122 foreach (RegionHeartbeatStart d in handler.GetInvocationList())
3123 {
3124 try
3125 {
3126 d(scene);
3127 }
3128 catch (Exception e)
3129 {
3130 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}",
3131 e.Message, e.StackTrace);
3132 }
3133 }
3134 }
3135 }
3136
3099 public void TriggerRegionHeartbeatEnd(Scene scene) 3137 public void TriggerRegionHeartbeatEnd(Scene scene)
3100 { 3138 {
3101 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; 3139 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd;
@@ -3251,5 +3289,26 @@ namespace OpenSim.Region.Framework.Scenes
3251 handler(scenePresence); 3289 handler(scenePresence);
3252 } 3290 }
3253 } 3291 }
3292
3293// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3294// {
3295// GatherUuids handler = OnGatherUuids;
3296//
3297// if (handler != null)
3298// {
3299// foreach (GatherUuids d in handler.GetInvocationList())
3300// {
3301// try
3302// {
3303// d(sop, assetUuids);
3304// }
3305// catch (Exception e)
3306// {
3307// m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}",
3308// e.Message, e.StackTrace);
3309// }
3310// }
3311// }
3312// }
3254 } 3313 }
3255} 3314}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index f0e639d..e3f979f 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -1,6 +1,29 @@
1// Proprietary code of Avination Virtual Limited 1/*
2// (c) 2012 Melanie Thielker 2 * Copyright (c) Contributors, http://opensimulator.org/
3// 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
4 27
5using System; 28using System;
6using System.Timers; 29using System.Timers;
@@ -32,7 +55,6 @@ namespace OpenSim.Region.Framework.Scenes
32 private object m_lockObject = new object(); 55 private object m_lockObject = new object();
33 private object m_timerLock = new object(); 56 private object m_timerLock = new object();
34 private const double m_tickDuration = 50.0; 57 private const double m_tickDuration = 50.0;
35 private Scene m_scene;
36 58
37 public double TickDuration 59 public double TickDuration
38 { 60 {
@@ -46,8 +68,6 @@ namespace OpenSim.Region.Framework.Scenes
46 m_timer.AutoReset = true; 68 m_timer.AutoReset = true;
47 m_timer.Elapsed += OnTimer; 69 m_timer.Elapsed += OnTimer;
48 70
49 m_scene = scene;
50
51 m_timer.Start(); 71 m_timer.Start();
52 } 72 }
53 73
@@ -71,13 +91,13 @@ namespace OpenSim.Region.Framework.Scenes
71 { 91 {
72 m.OnTimer(TickDuration); 92 m.OnTimer(TickDuration);
73 } 93 }
74 catch (Exception inner) 94 catch (Exception)
75 { 95 {
76 // Don't stop processing 96 // Don't stop processing
77 } 97 }
78 } 98 }
79 } 99 }
80 catch (Exception e) 100 catch (Exception)
81 { 101 {
82 // Keep running no matter what 102 // Keep running no matter what
83 } 103 }
@@ -134,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
134 [Serializable] 154 [Serializable]
135 public class KeyframeMotion 155 public class KeyframeMotion
136 { 156 {
137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 157// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
138 158
139 public enum PlayMode : int 159 public enum PlayMode : int
140 { 160 {
@@ -303,22 +323,25 @@ namespace OpenSim.Region.Framework.Scenes
303 m_group = grp; 323 m_group = grp;
304 m_scene = grp.Scene; 324 m_scene = grp.Scene;
305 325
306 Vector3 grppos = grp.AbsolutePosition; 326 lock (m_frames)
307 Vector3 offset = grppos - m_serializedPosition; 327 {
308 // avoid doing it more than once 328 Vector3 grppos = grp.AbsolutePosition;
309 // current this will happen draging a prim to other region 329 Vector3 offset = grppos - m_serializedPosition;
310 m_serializedPosition = grppos; 330 // avoid doing it more than once
331 // current this will happen draging a prim to other region
332 m_serializedPosition = grppos;
311 333
312 m_basePosition += offset; 334 m_basePosition += offset;
313 m_currentFrame.Position += offset; 335 m_currentFrame.Position += offset;
314 336
315 m_nextPosition += offset; 337 m_nextPosition += offset;
316 338
317 for (int i = 0; i < m_frames.Count; i++) 339 for (int i = 0; i < m_frames.Count; i++)
318 { 340 {
319 Keyframe k = m_frames[i]; 341 Keyframe k = m_frames[i];
320 k.Position += offset; 342 k.Position += offset;
321 m_frames[i]=k; 343 m_frames[i] = k;
344 }
322 } 345 }
323 346
324 if (m_running) 347 if (m_running)
@@ -363,25 +386,28 @@ namespace OpenSim.Region.Framework.Scenes
363 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 386 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
364 } 387 }
365 388
366 newmotion.m_frames = new List<Keyframe>(m_frames); 389 lock (m_frames)
390 {
391 newmotion.m_frames = new List<Keyframe>(m_frames);
367 392
368 newmotion.m_basePosition = m_basePosition; 393 newmotion.m_basePosition = m_basePosition;
369 newmotion.m_baseRotation = m_baseRotation; 394 newmotion.m_baseRotation = m_baseRotation;
370 395
371 if (m_selected) 396 if (m_selected)
372 newmotion.m_serializedPosition = m_serializedPosition;
373 else
374 {
375 if (m_group != null)
376 newmotion.m_serializedPosition = m_group.AbsolutePosition;
377 else
378 newmotion.m_serializedPosition = m_serializedPosition; 397 newmotion.m_serializedPosition = m_serializedPosition;
379 } 398 else
399 {
400 if (m_group != null)
401 newmotion.m_serializedPosition = m_group.AbsolutePosition;
402 else
403 newmotion.m_serializedPosition = m_serializedPosition;
404 }
380 405
381 newmotion.m_currentFrame = m_currentFrame; 406 newmotion.m_currentFrame = m_currentFrame;
382 407
383 newmotion.m_iterations = m_iterations; 408 newmotion.m_iterations = m_iterations;
384 newmotion.m_running = m_running; 409 newmotion.m_running = m_running;
410 }
385 411
386 if (m_running && !m_waitingCrossing) 412 if (m_running && !m_waitingCrossing)
387 StartTimer(); 413 StartTimer();
@@ -598,7 +624,6 @@ namespace OpenSim.Region.Framework.Scenes
598 return; 624 return;
599 } 625 }
600 626
601
602 if (m_group == null) 627 if (m_group == null)
603 return; 628 return;
604 629
@@ -610,7 +635,6 @@ namespace OpenSim.Region.Framework.Scenes
610 { 635 {
611 m_group.RootPart.Velocity = Vector3.Zero; 636 m_group.RootPart.Velocity = Vector3.Zero;
612 m_group.SendGroupRootTerseUpdate(); 637 m_group.SendGroupRootTerseUpdate();
613
614 } 638 }
615 return; 639 return;
616 } 640 }
@@ -633,28 +657,31 @@ namespace OpenSim.Region.Framework.Scenes
633 657
634 if (m_frames.Count == 0) 658 if (m_frames.Count == 0)
635 { 659 {
636 GetNextList(); 660 lock (m_frames)
637
638 if (m_frames.Count == 0)
639 { 661 {
640 Done(); 662 GetNextList();
641 Scene scene = m_group.Scene;
642 663
643 IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>(); 664 if (m_frames.Count == 0)
644 foreach (IScriptModule m in scriptModules)
645 { 665 {
646 if (m == null) 666 Done();
647 continue; 667 Scene scene = m_group.Scene;
648 m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
649 }
650 668
651 return; 669 IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
652 } 670 foreach (IScriptModule m in scriptModules)
671 {
672 if (m == null)
673 continue;
674 m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
675 }
653 676
654 m_currentFrame = m_frames[0]; 677 return;
655 m_currentFrame.TimeMS += (int)tickDuration; 678 }
656 679
680 m_currentFrame = m_frames[0];
681 m_currentFrame.TimeMS += (int)tickDuration;
682 }
657 //force a update on a keyframe transition 683 //force a update on a keyframe transition
684 m_nextPosition = m_group.AbsolutePosition;
658 update = true; 685 update = true;
659 } 686 }
660 687
@@ -662,7 +689,7 @@ namespace OpenSim.Region.Framework.Scenes
662 689
663 // Do the frame processing 690 // Do the frame processing
664 double steps = (double)m_currentFrame.TimeMS / tickDuration; 691 double steps = (double)m_currentFrame.TimeMS / tickDuration;
665 692
666 if (steps <= 0.0) 693 if (steps <= 0.0)
667 { 694 {
668 m_group.RootPart.Velocity = Vector3.Zero; 695 m_group.RootPart.Velocity = Vector3.Zero;
@@ -675,9 +702,13 @@ namespace OpenSim.Region.Framework.Scenes
675 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); 702 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
676 703
677 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 704 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
678 m_frames.RemoveAt(0); 705
679 if (m_frames.Count > 0) 706 lock (m_frames)
680 m_currentFrame = m_frames[0]; 707 {
708 m_frames.RemoveAt(0);
709 if (m_frames.Count > 0)
710 m_currentFrame = m_frames[0];
711 }
681 712
682 update = true; 713 update = true;
683 } 714 }
@@ -689,15 +720,10 @@ namespace OpenSim.Region.Framework.Scenes
689 Vector3 motionThisFrame = v / (float)steps; 720 Vector3 motionThisFrame = v / (float)steps;
690 v = v * 1000 / m_currentFrame.TimeMS; 721 v = v * 1000 / m_currentFrame.TimeMS;
691 722
692 if (Vector3.Mag(motionThisFrame) >= 0.05f) 723 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
693 {
694 // m_group.AbsolutePosition += motionThisFrame;
695 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
696 m_group.AbsolutePosition = m_nextPosition;
697 724
698 //m_group.RootPart.Velocity = v; 725 if (Vector3.Mag(motionThisFrame) >= 0.05f)
699 update = true; 726 update = true;
700 }
701 727
702 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) 728 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
703 { 729 {
@@ -705,43 +731,43 @@ namespace OpenSim.Region.Framework.Scenes
705 731
706 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); 732 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
707 step.Normalize(); 733 step.Normalize();
708/* use simpler change detection 734 /* use simpler change detection
709* float angle = 0; 735 * float angle = 0;
710 736
711 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 737 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
712 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 738 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
713 float aa_bb = aa * bb; 739 float aa_bb = aa * bb;
714 740
715 if (aa_bb == 0) 741 if (aa_bb == 0)
716 { 742 {
717 angle = 0; 743 angle = 0;
718 } 744 }
719 else 745 else
720 { 746 {
721 float ab = current.X * step.X + 747 float ab = current.X * step.X +
722 current.Y * step.Y + 748 current.Y * step.Y +
723 current.Z * step.Z + 749 current.Z * step.Z +
724 current.W * step.W; 750 current.W * step.W;
725 float q = (ab * ab) / aa_bb; 751 float q = (ab * ab) / aa_bb;
726 752
727 if (q > 1.0f) 753 if (q > 1.0f)
728 { 754 {
729 angle = 0; 755 angle = 0;
730 } 756 }
731 else 757 else
732 { 758 {
733 angle = (float)Math.Acos(2 * q - 1); 759 angle = (float)Math.Acos(2 * q - 1);
734 } 760 }
735 } 761 }
736 762
737 if (angle > 0.01f) 763 if (angle > 0.01f)
738*/ 764 */
739 if (Math.Abs(step.X - current.X) > 0.001f 765 if (Math.Abs(step.X - current.X) > 0.001f
740 || Math.Abs(step.Y - current.Y) > 0.001f 766 || Math.Abs(step.Y - current.Y) > 0.001f
741 || Math.Abs(step.Z - current.Z) > 0.001f) 767 || Math.Abs(step.Z - current.Z) > 0.001f)
742 // assuming w is a dependente var 768 // assuming w is a dependente var
743 { 769 {
744// m_group.UpdateGroupRotationR(step); 770 // m_group.UpdateGroupRotationR(step);
745 m_group.RootPart.RotationOffset = step; 771 m_group.RootPart.RotationOffset = step;
746 772
747 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); 773 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
@@ -752,12 +778,18 @@ namespace OpenSim.Region.Framework.Scenes
752 778
753 if (update) 779 if (update)
754 { 780 {
781 m_group.AbsolutePosition = m_nextPosition;
755 m_group.SendGroupRootTerseUpdate(); 782 m_group.SendGroupRootTerseUpdate();
756 } 783 }
757 } 784 }
758 785
759 public Byte[] Serialize() 786 public Byte[] Serialize()
760 { 787 {
788 bool timerWasStopped;
789 lock (m_frames)
790 {
791 timerWasStopped = m_timerStopped;
792 }
761 StopTimer(); 793 StopTimer();
762 MemoryStream ms = new MemoryStream(); 794 MemoryStream ms = new MemoryStream();
763 795
@@ -768,7 +800,7 @@ namespace OpenSim.Region.Framework.Scenes
768 m_serializedPosition = tmp.AbsolutePosition; 800 m_serializedPosition = tmp.AbsolutePosition;
769 fmt.Serialize(ms, this); 801 fmt.Serialize(ms, this);
770 m_group = tmp; 802 m_group = tmp;
771 if (m_running && !m_waitingCrossing) 803 if (!timerWasStopped && m_running && !m_waitingCrossing)
772 StartTimer(); 804 StartTimer();
773 805
774 return ms.ToArray(); 806 return ms.ToArray();
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index ddae073..c0405ad 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -91,6 +91,11 @@ namespace OpenSim.Region.Framework.Scenes
91 return 0; 91 return 0;
92 92
93 uint priority; 93 uint priority;
94
95
96 // HACK
97 return GetPriorityByBestAvatarResponsiveness(client, entity);
98
94 99
95 switch (m_scene.UpdatePrioritizationScheme) 100 switch (m_scene.UpdatePrioritizationScheme)
96 { 101 {
@@ -157,30 +162,31 @@ namespace OpenSim.Region.Framework.Scenes
157 162
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 163 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 164 {
160 uint pqueue = ComputeDistancePriority(client,entity,false); 165 uint pqueue = 2; // keep compiler happy
161 166
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 167 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 168 if (presence != null)
164 { 169 {
165 if (!presence.IsChildAgent) 170 // All avatars other than our own go into pqueue 1
171 if (entity is ScenePresence)
172 return 1;
173
174 if (entity is SceneObjectPart)
166 { 175 {
167 // All avatars other than our own go into pqueue 1 176 // Attachments are high priority,
168 if (entity is ScenePresence) 177 if (((SceneObjectPart)entity).ParentGroup.IsAttachment)
169 return 1; 178 return 2;
170 179
171 if (entity is SceneObjectPart) 180 pqueue = ComputeDistancePriority(client, entity, false);
172 { 181
173 // Attachments are high priority, 182 // Non physical prims are lower priority than physical prims
174 if (((SceneObjectPart)entity).ParentGroup.IsAttachment) 183 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
175 return 1; 184 if (physActor == null || !physActor.IsPhysical)
176 185 pqueue++;
177 // Non physical prims are lower priority than physical prims
178 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
179 if (physActor == null || !physActor.IsPhysical)
180 pqueue++;
181 }
182 } 186 }
183 } 187 }
188 else
189 pqueue = ComputeDistancePriority(client, entity, false);
184 190
185 return pqueue; 191 return pqueue;
186 } 192 }
@@ -227,16 +233,28 @@ namespace OpenSim.Region.Framework.Scenes
227 233
228 // And convert the distance to a priority queue, this computation gives queues 234 // And convert the distance to a priority queue, this computation gives queues
229 // at 10, 20, 40, 80, 160, 320, 640, and 1280m 235 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
230 uint pqueue = PriorityQueue.NumberOfImmediateQueues; 236 uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue
231 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; 237 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
232 238/*
233 for (int i = 0; i < queues - 1; i++) 239 for (int i = 0; i < queues - 1; i++)
234 { 240 {
235 if (distance < 30 * Math.Pow(2.0,i)) 241 if (distance < 30 * Math.Pow(2.0,i))
236 break; 242 break;
237 pqueue++; 243 pqueue++;
238 } 244 }
239 245*/
246 if (distance > 10f)
247 {
248 float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f;
249 // for a map identical to original:
250 // now
251 // 1st constant is 1/(log(2)) (natural log) so we get log2(distance)
252 // 2st constant makes it be log2(distance/10)
253 pqueue += (uint)tmp;
254 if (pqueue > queues - 1)
255 pqueue = queues - 1;
256 }
257
240 // If this is a root agent, then determine front & back 258 // If this is a root agent, then determine front & back
241 // Bump up the priority queue (drop the priority) for any objects behind the avatar 259 // Bump up the priority queue (drop the priority) for any objects behind the avatar
242 if (useFrontBack && ! presence.IsChildAgent) 260 if (useFrontBack && ! presence.IsChildAgent)
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index c11174d..f208afb 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -46,47 +46,33 @@ using OpenSim.Region.Framework.Scenes;
46 46
47namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
48{ 48{
49 public class RegionStatsHandler : IStreamedRequestHandler 49 public class RegionStatsHandler : BaseStreamHandler
50 { 50 {
51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private string osRXStatsURI = String.Empty;
54 private string osXStatsURI = String.Empty; 53 private string osXStatsURI = String.Empty;
55 //private string osSecret = String.Empty; 54 //private string osSecret = String.Empty;
56 private OpenSim.Framework.RegionInfo regionInfo; 55 private OpenSim.Framework.RegionInfo regionInfo;
57 public string localZone = TimeZone.CurrentTimeZone.StandardName; 56 public string localZone = TimeZone.CurrentTimeZone.StandardName;
58 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 57 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
59 58
60 public string Name { get { return "RegionStats"; } } 59 public RegionStatsHandler(RegionInfo region_info)
61 public string Description { get { return "Region Statistics"; } } 60 : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics")
62
63 public RegionStatsHandler(RegionInfo region_info)
64 { 61 {
65 regionInfo = region_info; 62 regionInfo = region_info;
66 osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret);
67 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); 63 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret);
68 } 64 }
69 65
70 public byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 protected override byte[] ProcessRequest(
67 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
71 { 68 {
72 return Util.UTF8.GetBytes(Report()); 69 return Util.UTF8.GetBytes(Report());
73 } 70 }
74 71
75 public string ContentType 72 public override string ContentType
76 { 73 {
77 get { return "text/plain"; } 74 get { return "text/plain"; }
78 } 75 }
79
80 public string HttpMethod
81 {
82 get { return "GET"; }
83 }
84
85 public string Path
86 {
87 // This is for the region and is the regionSecret hashed
88 get { return "/" + osRXStatsURI; }
89 }
90 76
91 private string Report() 77 private string Report()
92 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index d70aa45..cd8c9a5 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -139,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
139 { 140 {
140 userlevel = 1; 141 userlevel = 1;
141 } 142 }
142 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 143 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
143 144
144 return true; 145 return true;
145 } 146 }
@@ -178,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
178 { 179 {
179 userlevel = 1; 180 userlevel = 1;
180 } 181 }
181 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 182 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
182 183
183 if (originalFolder != UUID.Zero) 184 if (originalFolder != UUID.Zero)
184 { 185 {
@@ -411,19 +412,21 @@ namespace OpenSim.Region.Framework.Scenes
411// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, 412// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
412// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); 413// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
413 414
415 bool sendUpdate = false;
416
414 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid 417 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
415 { 418 {
416 // Create a set of base permissions that will not include export if the user 419 // Create a set of base permissions that will not include export if the user
417 // is not allowed to change the export flag. 420 // is not allowed to change the export flag.
418 bool denyExportChange = false; 421 bool denyExportChange = false;
419 422
420 m_log.InfoFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); 423// m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions);
421 424
422 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export 425 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export
423 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) 426 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner)
424 denyExportChange = true; 427 denyExportChange = true;
425 428
426 m_log.InfoFormat("[XXX]: Deny Export Update {0}", denyExportChange); 429// m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange);
427 430
428 // If it is already set, force it set and also force full perm 431 // If it is already set, force it set and also force full perm
429 // else prevent setting it. It can and should never be set unless 432 // else prevent setting it. It can and should never be set unless
@@ -447,7 +450,7 @@ namespace OpenSim.Region.Framework.Scenes
447 // If the new state is exportable, force full perm 450 // If the new state is exportable, force full perm
448 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) 451 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
449 { 452 {
450 m_log.InfoFormat("[XXX]: Force full perm"); 453// m_log.DebugFormat("[XXX]: Force full perm");
451 itemUpd.NextPermissions = (uint)(PermissionMask.All); 454 itemUpd.NextPermissions = (uint)(PermissionMask.All);
452 } 455 }
453 } 456 }
@@ -484,8 +487,13 @@ namespace OpenSim.Region.Framework.Scenes
484 item.SalePrice = itemUpd.SalePrice; 487 item.SalePrice = itemUpd.SalePrice;
485 item.SaleType = itemUpd.SaleType; 488 item.SaleType = itemUpd.SaleType;
486 489
490 if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0)
491 {
492 item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf);
493 sendUpdate = true;
494 }
495
487 InventoryService.UpdateItem(item); 496 InventoryService.UpdateItem(item);
488 remoteClient.SendBulkUpdateInventory(item);
489 } 497 }
490 498
491 if (UUID.Zero != transactionID) 499 if (UUID.Zero != transactionID)
@@ -495,6 +503,17 @@ namespace OpenSim.Region.Framework.Scenes
495 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); 503 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
496 } 504 }
497 } 505 }
506 else
507 {
508 // This MAY be problematic, if it is, another solution
509 // needs to be found. If inventory item flags are updated
510 // the viewer's notion of the item needs to be refreshed.
511 //
512 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
513 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
514 if (sendUpdate)
515 remoteClient.SendBulkUpdateInventory(item);
516 }
498 } 517 }
499 else 518 else
500 { 519 {
@@ -548,6 +567,9 @@ namespace OpenSim.Region.Framework.Scenes
548 { 567 {
549 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); 568 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
550 569
570 if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
571 return null;
572
551 InventoryItemBase item = new InventoryItemBase(itemId, senderId); 573 InventoryItemBase item = new InventoryItemBase(itemId, senderId);
552 item = InventoryService.GetItem(item); 574 item = InventoryService.GetItem(item);
553 575
@@ -642,17 +664,13 @@ namespace OpenSim.Region.Framework.Scenes
642 // a mask 664 // a mask
643 if (item.InvType == (int)InventoryType.Object) 665 if (item.InvType == (int)InventoryType.Object)
644 { 666 {
645 // Create a safe mask for the current perms
646 uint foldedPerms = (item.CurrentPermissions & 7) << 13;
647 foldedPerms |= permsMask;
648
649 bool isRootMod = (item.CurrentPermissions & 667 bool isRootMod = (item.CurrentPermissions &
650 (uint)PermissionMask.Modify) != 0 ? 668 (uint)PermissionMask.Modify) != 0 ?
651 true : false; 669 true : false;
652 670
653 // Mask the owner perms to the folded perms 671 // Mask the owner perms to the folded perms
654 ownerPerms &= foldedPerms; 672 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms);
655 basePerms &= foldedPerms; 673 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms);
656 674
657 // If the root was mod, let the mask reflect that 675 // If the root was mod, let the mask reflect that
658 // We also need to adjust the base here, because 676 // We also need to adjust the base here, because
@@ -1005,6 +1023,10 @@ namespace OpenSim.Region.Framework.Scenes
1005 item.BasePermissions = baseMask; 1023 item.BasePermissions = baseMask;
1006 item.CreationDate = creationDate; 1024 item.CreationDate = creationDate;
1007 1025
1026 // special AnimationSet case
1027 if (item.InvType == (int)CustomInventoryType.AnimationSet)
1028 AnimationSet.enforceItemPermitions(item,true);
1029
1008 if (AddInventoryItem(item)) 1030 if (AddInventoryItem(item))
1009 { 1031 {
1010 remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID); 1032 remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID);
@@ -1213,9 +1235,15 @@ namespace OpenSim.Region.Framework.Scenes
1213 { 1235 {
1214 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); 1236 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1215 if (taskItem.InvType == (int)InventoryType.Object) 1237 if (taskItem.InvType == (int)InventoryType.Object)
1216 agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); 1238 {
1217 else 1239 uint perms = taskItem.BasePermissions & taskItem.NextPermissions;
1218 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; 1240 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
1241// agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1242// agentItem.CurrentPermissions = agentItem.BasePermissions;
1243 agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1244 }
1245
1246 agentItem.CurrentPermissions = agentItem.BasePermissions;
1219 1247
1220 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 1248 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1221 agentItem.NextPermissions = taskItem.NextPermissions; 1249 agentItem.NextPermissions = taskItem.NextPermissions;
@@ -2124,7 +2152,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2152 {
2125 // If we don't have permission, stop right here 2153 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2154 if (!permissionToTakeCopy)
2155 {
2156 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2157 return;
2158 }
2128 2159
2129 permissionToTake = true; 2160 permissionToTake = true;
2130 // Don't delete 2161 // Don't delete
@@ -2277,6 +2308,88 @@ namespace OpenSim.Region.Framework.Scenes
2277 } 2308 }
2278 2309
2279 /// <summary> 2310 /// <summary>
2311 /// Returns the list of Scene Objects in an asset.
2312 /// </summary>
2313 /// <remarks>
2314 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2315 /// </remarks>
2316 /// <param name="assetData">Asset data</param>
2317 /// <param name="attachment">Whether the item is an attachment</param>
2318 /// <param name="objlist">The objects included in the asset</param>
2319 /// <param name="veclist">Relative positions of the objects</param>
2320 /// <param name="bbox">Bounding box of all the objects</param>
2321 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2322 /// to the centre of the root prim (relevant only when returning a single object)</param>
2323 /// <returns>true = returning a single object; false = multiple objects</returns>
2324 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2325 out Vector3 bbox, out float offsetHeight)
2326 {
2327 objlist = new List<SceneObjectGroup>();
2328 veclist = new List<Vector3>();
2329
2330 XmlDocument doc = new XmlDocument();
2331 string xmlData = Utils.BytesToString(assetData);
2332 doc.LoadXml(xmlData);
2333 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2334
2335 if (e == null || attachment) // Single
2336 {
2337 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2338/*
2339 if (!attachment)
2340 {
2341 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2342 g.RootPart.AttachedPos = g.AbsolutePosition;
2343 g.RootPart.AttachRotation = g.GroupRotation;
2344 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2345 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2346 g.RootPart.Shape.State = 0;
2347 }
2348*/
2349 objlist.Add(g);
2350 veclist.Add(new Vector3(0, 0, 0));
2351 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2352 return true;
2353 }
2354 else
2355 {
2356 XmlElement coll = (XmlElement)e;
2357 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2358 float by = Convert.ToSingle(coll.GetAttribute("y"));
2359 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2360 bbox = new Vector3(bx, by, bz);
2361 offsetHeight = 0;
2362
2363 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2364 foreach (XmlNode n in groups)
2365 {
2366 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2367/*
2368 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2369 g.RootPart.AttachedPos = g.AbsolutePosition;
2370 g.RootPart.AttachRotation = g.GroupRotation;
2371 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2372 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2373 g.RootPart.Shape.State = 0;
2374*/
2375 objlist.Add(g);
2376
2377 XmlElement el = (XmlElement)n;
2378 string rawX = el.GetAttribute("offsetx");
2379 string rawY = el.GetAttribute("offsety");
2380 string rawZ = el.GetAttribute("offsetz");
2381
2382 float x = Convert.ToSingle(rawX);
2383 float y = Convert.ToSingle(rawY);
2384 float z = Convert.ToSingle(rawZ);
2385 veclist.Add(new Vector3(x, y, z));
2386 }
2387 }
2388
2389 return false;
2390 }
2391
2392 /// <summary>
2280 /// Event Handler Rez an object into a scene 2393 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler 2394 /// Calls the non-void event handler
2282 /// </summary> 2395 /// </summary>
@@ -2351,19 +2464,25 @@ namespace OpenSim.Region.Framework.Scenes
2351 /// will be used if it exists.</param> 2464 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param> 2465 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param> 2466 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2467 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual SceneObjectGroup RezObject( 2468 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2469 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 { 2470 {
2358 if (null == item) 2471 if (null == item)
2359 return null; 2472 return null;
2473
2474 List<SceneObjectGroup> objlist;
2475 List<Vector3> veclist;
2360 2476
2361 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2477 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2362 2478 if (!success)
2363 if (null == group)
2364 return null; 2479 return null;
2365 2480
2366 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2481 int totalPrims = 0;
2482 foreach (SceneObjectGroup group in objlist)
2483 totalPrims += group.PrimCount;
2484
2485 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2367 return null; 2486 return null;
2368 2487
2369 if (!Permissions.BypassPermissions()) 2488 if (!Permissions.BypassPermissions())
@@ -2372,16 +2491,28 @@ namespace OpenSim.Region.Framework.Scenes
2372 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2491 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2373 } 2492 }
2374 2493
2375 group.FromPartID = sourcePart.UUID; 2494 for (int i = 0; i < objlist.Count; i++)
2376 AddNewSceneObject(group, true, pos, rot, vel); 2495 {
2377 2496 SceneObjectGroup group = objlist[i];
2378 // We can only call this after adding the scene object, since the scene object references the scene 2497 Vector3 curpos = pos + veclist[i];
2379 // to find out if scripts should be activated at all. 2498
2380 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2499 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2381 2500 {
2382 group.ScheduleGroupForFullUpdate(); 2501 group.RootPart.AttachedPos = group.AbsolutePosition;
2383 2502 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2384 return group; 2503 }
2504
2505 group.FromPartID = sourcePart.UUID;
2506 AddNewSceneObject(group, true, curpos, rot, vel);
2507
2508 // We can only call this after adding the scene object, since the scene object references the scene
2509 // to find out if scripts should be activated at all.
2510 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2511
2512 group.ScheduleGroupForFullUpdate();
2513 }
2514
2515 return objlist;
2385 } 2516 }
2386 2517
2387 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2518 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
@@ -2576,12 +2707,17 @@ namespace OpenSim.Region.Framework.Scenes
2576 return; 2707 return;
2577 } 2708 }
2578 2709
2710 bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0;
2579 m_sceneGraph.LinkObjects(root, children); 2711 m_sceneGraph.LinkObjects(root, children);
2580 2712
2581 ScenePresence sp; 2713 ScenePresence sp;
2582 if (TryGetScenePresence(agentId, out sp)) 2714 if (TryGetScenePresence(agentId, out sp))
2583 { 2715 {
2584 root.SendPropertiesToClient(sp.ControllingClient); 2716 root.SendPropertiesToClient(sp.ControllingClient);
2717 if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0)
2718 {
2719 sp.ControllingClient.SendAlertMessage("Object physics canceled");
2720 }
2585 } 2721 }
2586 } 2722 }
2587 2723
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index ce6415a..931093a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 if (part.ParentGroup.RootPart.LocalId != part.LocalId) 252 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
253 return; 253 return;
254 254
255 bool isAttachment = false;
256
257 // This is wrong, wrong, wrong. Selection should not be 255 // This is wrong, wrong, wrong. Selection should not be
258 // handled by group, but by prim. Legacy cruft. 256 // handled by group, but by prim. Legacy cruft.
259 // TODO: Make selection flagging per prim! 257 // TODO: Make selection flagging per prim!
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes
262 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) 260 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
263 part.ParentGroup.IsSelected = false; 261 part.ParentGroup.IsSelected = false;
264 262
265 if (part.ParentGroup.IsAttachment) 263 part.ParentGroup.ScheduleGroupForFullUpdate();
266 isAttachment = true;
267 else
268 part.ParentGroup.ScheduleGroupForFullUpdate();
269 264
270 // If it's not an attachment, and we are allowed to move it, 265 // If it's not an attachment, and we are allowed to move it,
271 // then we might have done so. If we moved across a parcel 266 // then we might have done so. If we moved across a parcel
272 // boundary, we will need to recount prims on the parcels. 267 // boundary, we will need to recount prims on the parcels.
273 // For attachments, that makes no sense. 268 // For attachments, that makes no sense.
274 // 269 //
275 if (!isAttachment) 270 if (!part.ParentGroup.IsAttachment)
276 { 271 {
277 if (Permissions.CanEditObject( 272 if (Permissions.CanEditObject(
278 part.UUID, remoteClient.AgentId) 273 part.UUID, remoteClient.AgentId)
@@ -296,6 +291,10 @@ namespace OpenSim.Region.Framework.Scenes
296 EventManager.TriggerParcelPrimCountTainted(); 291 EventManager.TriggerParcelPrimCountTainted();
297 } 292 }
298 293
294 // restore targetOmega
295 if (part.AngularVelocity != Vector3.Zero)
296 part.ScheduleTerseUpdate();
297
299 } 298 }
300 299
301 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 300 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
@@ -416,6 +415,7 @@ namespace OpenSim.Region.Framework.Scenes
416 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) 415 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args)
417 { 416 {
418 // TODO: don't create new blocks if recycling an old packet 417 // TODO: don't create new blocks if recycling an old packet
418 bool discardableEffects = true;
419 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; 419 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count];
420 for (int i = 0; i < args.Count; i++) 420 for (int i = 0; i < args.Count; i++)
421 { 421 {
@@ -427,17 +427,34 @@ namespace OpenSim.Region.Framework.Scenes
427 effect.Type = args[i].Type; 427 effect.Type = args[i].Type;
428 effect.TypeData = args[i].TypeData; 428 effect.TypeData = args[i].TypeData;
429 effectBlockArray[i] = effect; 429 effectBlockArray[i] = effect;
430
431 if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam)
432 discardableEffects = false;
433
434 //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type);
430 } 435 }
431 436
432 ForEachClient( 437 ForEachScenePresence(sp =>
433 delegate(IClientAPI client)
434 { 438 {
435 if (client.AgentId != remoteClient.AgentId) 439 if (sp.ControllingClient.AgentId != remoteClient.AgentId)
436 client.SendViewerEffect(effectBlockArray); 440 {
437 } 441 if (!discardableEffects ||
438 ); 442 (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp)))
443 {
444 //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID);
445 sp.ControllingClient.SendViewerEffect(effectBlockArray);
446 }
447 //else
448 // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID);
449 }
450 });
439 } 451 }
440 452
453 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
454 {
455 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
456 }
457
441 private class DescendentsRequestData 458 private class DescendentsRequestData
442 { 459 {
443 public IClientAPI RemoteClient; 460 public IClientAPI RemoteClient;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b189599..9e2f52c 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
@@ -204,6 +204,12 @@ namespace OpenSim.Region.Framework.Scenes
204 /// </summary> 204 /// </summary>
205 public int m_linksetCapacity = 0; 205 public int m_linksetCapacity = 0;
206 206
207 /// <summary>
208 /// Max prims an Physical object will hold
209 /// </summary>
210 ///
211 public int m_linksetPhysCapacity = 0;
212
207 public bool m_clampPrimSize; 213 public bool m_clampPrimSize;
208 public bool m_trustBinaries; 214 public bool m_trustBinaries;
209 public bool m_allowScriptCrossings; 215 public bool m_allowScriptCrossings;
@@ -230,6 +236,8 @@ namespace OpenSim.Region.Framework.Scenes
230 public bool m_seeIntoBannedRegion = false; 236 public bool m_seeIntoBannedRegion = false;
231 public int MaxUndoCount = 5; 237 public int MaxUndoCount = 5;
232 238
239 public bool SeeIntoRegion { get; set; }
240
233 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 241 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
234 public bool LoginLock = false; 242 public bool LoginLock = false;
235 243
@@ -396,10 +404,12 @@ namespace OpenSim.Region.Framework.Scenes
396 if (value) 404 if (value)
397 { 405 {
398 if (!m_active) 406 if (!m_active)
399 Start(); 407 Start(false);
400 } 408 }
401 else 409 else
402 { 410 {
411 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
412 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
403 m_active = false; 413 m_active = false;
404 } 414 }
405 } 415 }
@@ -747,6 +757,7 @@ namespace OpenSim.Region.Framework.Scenes
747 m_config = config; 757 m_config = config;
748 MinFrameTime = 0.089f; 758 MinFrameTime = 0.089f;
749 MinMaintenanceTime = 1; 759 MinMaintenanceTime = 1;
760 SeeIntoRegion = true;
750 761
751 Random random = new Random(); 762 Random random = new Random();
752 763
@@ -859,9 +870,12 @@ namespace OpenSim.Region.Framework.Scenes
859 //Animation states 870 //Animation states
860 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 871 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
861 872
873 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
874
875 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
876
862 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 877 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
863 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 878 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
864
865 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 879 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
866 if (RegionInfo.NonphysPrimMin > 0) 880 if (RegionInfo.NonphysPrimMin > 0)
867 { 881 {
@@ -893,6 +907,9 @@ namespace OpenSim.Region.Framework.Scenes
893 m_linksetCapacity = RegionInfo.LinksetCapacity; 907 m_linksetCapacity = RegionInfo.LinksetCapacity;
894 } 908 }
895 909
910 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
911
912
896 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 913 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
897 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 914 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
898 915
@@ -1332,7 +1349,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 Thread.Sleep(500); 1349 Thread.Sleep(500);
1333 1350
1334 // Stop all client threads. 1351 // Stop all client threads.
1335 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1352 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1336 1353
1337 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1354 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1338 EventManager.TriggerSceneShuttingDown(this); 1355 EventManager.TriggerSceneShuttingDown(this);
@@ -1361,10 +1378,18 @@ namespace OpenSim.Region.Framework.Scenes
1361 } 1378 }
1362 } 1379 }
1363 1380
1381 public override void Start()
1382 {
1383 Start(true);
1384 }
1385
1364 /// <summary> 1386 /// <summary>
1365 /// Start the scene 1387 /// Start the scene
1366 /// </summary> 1388 /// </summary>
1367 public void Start() 1389 /// <param name='startScripts'>
1390 /// Start the scripts within the scene.
1391 /// </param>
1392 public void Start(bool startScripts)
1368 { 1393 {
1369 m_active = true; 1394 m_active = true;
1370 1395
@@ -1401,6 +1426,8 @@ namespace OpenSim.Region.Framework.Scenes
1401 m_heartbeatThread 1426 m_heartbeatThread
1402 = Watchdog.StartThread( 1427 = Watchdog.StartThread(
1403 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1428 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1429
1430 StartScripts();
1404 } 1431 }
1405 1432
1406 /// <summary> 1433 /// <summary>
@@ -1557,6 +1584,8 @@ namespace OpenSim.Region.Framework.Scenes
1557 1584
1558 try 1585 try
1559 { 1586 {
1587 EventManager.TriggerRegionHeartbeatStart(this);
1588
1560 // Apply taints in terrain module to terrain in physics scene 1589 // Apply taints in terrain module to terrain in physics scene
1561 if (Frame % m_update_terrain == 0) 1590 if (Frame % m_update_terrain == 0)
1562 { 1591 {
@@ -1996,6 +2025,11 @@ namespace OpenSim.Region.Framework.Scenes
1996 2025
1997 GridRegion region = new GridRegion(RegionInfo); 2026 GridRegion region = new GridRegion(RegionInfo);
1998 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2027 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2028 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
2029 LogHeader, m_regionName,
2030 RegionInfo.RegionID,
2031 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2032 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1999 if (error != String.Empty) 2033 if (error != String.Empty)
2000 throw new Exception(error); 2034 throw new Exception(error);
2001 } 2035 }
@@ -2444,7 +2478,7 @@ namespace OpenSim.Region.Framework.Scenes
2444 foreach (UUID av in avatars) 2478 foreach (UUID av in avatars)
2445 { 2479 {
2446 ScenePresence p = GetScenePresence(av); 2480 ScenePresence p = GetScenePresence(av);
2447 if (p != null) 2481 if (p != null && p.ParentUUID == UUID.Zero)
2448 p.StandUp(); 2482 p.StandUp();
2449 } 2483 }
2450 2484
@@ -2514,6 +2548,11 @@ namespace OpenSim.Region.Framework.Scenes
2514 return false; 2548 return false;
2515 } 2549 }
2516 2550
2551
2552 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2553 {
2554 m_sceneGraph.updateScenePartGroup(part, grp);
2555 }
2517 /// <summary> 2556 /// <summary>
2518 /// Move the given scene object into a new region depending on which region its absolute position has moved 2557 /// Move the given scene object into a new region depending on which region its absolute position has moved
2519 /// into. 2558 /// into.
@@ -2935,14 +2974,15 @@ namespace OpenSim.Region.Framework.Scenes
2935 2974
2936 #region Add/Remove Avatar Methods 2975 #region Add/Remove Avatar Methods
2937 2976
2938 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2977 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2939 { 2978 {
2940 ScenePresence sp; 2979 ScenePresence sp;
2941 bool vialogin; 2980 bool vialogin;
2981 bool reallyNew = true;
2942 2982
2943 // Validation occurs in LLUDPServer 2983 // Validation occurs in LLUDPServer
2944 // 2984 //
2945 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2985 // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
2946 // each other. In practice, this does not currently occur in the code. 2986 // each other. In practice, this does not currently occur in the code.
2947 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2987 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2948 2988
@@ -2950,9 +2990,9 @@ namespace OpenSim.Region.Framework.Scenes
2950 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2990 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2951 // whilst connecting). 2991 // whilst connecting).
2952 // 2992 //
2953 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 2993 // It would be easier to lock across all NewUserConnection(), AddNewAgent() and
2954 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service 2994 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2955 // response in some module listening to AddNewClient()) from holding up unrelated agent calls. 2995 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2956 // 2996 //
2957 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 2997 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2958 // AddNewClient() operations (though not other ops). 2998 // AddNewClient() operations (though not other ops).
@@ -2969,18 +3009,23 @@ namespace OpenSim.Region.Framework.Scenes
2969 3009
2970 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 3010 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2971 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 3011 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2972 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 3012 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2973 // connected. 3013 // connected.
2974 if (sp == null) 3014 if (sp == null)
2975 { 3015 {
2976 m_log.DebugFormat( 3016 m_log.DebugFormat(
2977 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3017 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}",
2978 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 3018 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
3019 ((TPFlags)aCircuit.teleportFlags).ToString());
2979 3020
2980 m_clientManager.Add(client); 3021 m_clientManager.Add(client);
2981 SubscribeToClientEvents(client); 3022 SubscribeToClientEvents(client);
2982 3023
2983 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 3024 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3025
3026 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3027
3028/* done in completMovement
2984 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46); 3029 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
2985 if (cof == null) 3030 if (cof == null)
2986 sp.COF = UUID.Zero; 3031 sp.COF = UUID.Zero;
@@ -2988,25 +3033,33 @@ namespace OpenSim.Region.Framework.Scenes
2988 sp.COF = cof.ID; 3033 sp.COF = cof.ID;
2989 3034
2990 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF); 3035 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
3036 */
2991 m_eventManager.TriggerOnNewPresence(sp); 3037 m_eventManager.TriggerOnNewPresence(sp);
2992 3038
2993 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2994 } 3039 }
2995 else 3040 else
2996 { 3041 {
2997 m_log.WarnFormat( 3042 m_log.WarnFormat(
2998 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3043 "[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); 3044 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3045 reallyNew = false;
3000 } 3046 }
3001 3047
3002 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3048 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3003 // client is for a root or child agent. 3049 // client is for a root or child agent.
3050 // XXX: This may be better set for a new client before that client is added to the client manager.
3051 // But need to know what happens in the case where a ScenePresence is already present (and if this
3052 // actually occurs).
3004 client.SceneAgent = sp; 3053 client.SceneAgent = sp;
3005 3054
3006 // Cache the user's name 3055 // This is currently also being done earlier in NewUserConnection for real users to see if this
3056 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3057 // places. However, we still need to do it here for NPCs.
3007 CacheUserName(sp, aCircuit); 3058 CacheUserName(sp, aCircuit);
3008 3059
3009 EventManager.TriggerOnNewClient(client); 3060 if (reallyNew)
3061 EventManager.TriggerOnNewClient(client);
3062
3010 if (vialogin) 3063 if (vialogin)
3011 EventManager.TriggerOnClientLogin(client); 3064 EventManager.TriggerOnClientLogin(client);
3012 } 3065 }
@@ -3027,7 +3080,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3080 {
3028 string first = aCircuit.firstname, last = aCircuit.lastname; 3081 string first = aCircuit.firstname, last = aCircuit.lastname;
3029 3082
3030 if (sp.PresenceType == PresenceType.Npc) 3083 if (sp != null && sp.PresenceType == PresenceType.Npc)
3031 { 3084 {
3032 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3085 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
3033 } 3086 }
@@ -3100,12 +3153,13 @@ namespace OpenSim.Region.Framework.Scenes
3100 // and the scene presence and the client, if they exist 3153 // and the scene presence and the client, if they exist
3101 try 3154 try
3102 { 3155 {
3103 ScenePresence sp = GetScenePresence(agentID); 3156 ScenePresence sp = WaitGetScenePresence(agentID);
3104 3157
3105 if (sp != null) 3158 if (sp != null)
3106 { 3159 {
3107 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3160 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3108 sp.ControllingClient.Close(); 3161
3162 CloseAgent(sp.UUID, false);
3109 } 3163 }
3110 3164
3111 // BANG! SLASH! 3165 // BANG! SLASH!
@@ -3244,8 +3298,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 { 3298 {
3245 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3299 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3246 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3300 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3247 client.OnSetStartLocationRequest += SetHomeRezPoint;
3248 client.OnRegionHandleRequest += RegionHandleRequest;
3249 } 3301 }
3250 3302
3251 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3303 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
@@ -3371,8 +3423,6 @@ namespace OpenSim.Region.Framework.Scenes
3371 { 3423 {
3372 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3424 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3373 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3425 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3374 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3375 client.OnRegionHandleRequest -= RegionHandleRequest;
3376 } 3426 }
3377 3427
3378 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3428 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3498,33 +3548,6 @@ namespace OpenSim.Region.Framework.Scenes
3498 } 3548 }
3499 3549
3500 /// <summary> 3550 /// <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. 3551 /// Get the avatar apperance for the given client.
3529 /// </summary> 3552 /// </summary>
3530 /// <param name="client"></param> 3553 /// <param name="client"></param>
@@ -3548,63 +3571,73 @@ namespace OpenSim.Region.Framework.Scenes
3548 } 3571 }
3549 } 3572 }
3550 3573
3551 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3574 /// <summary>
3575 /// Remove the given client from the scene.
3576 /// </summary>
3577 /// <remarks>
3578 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3579 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3580 /// from viewers).
3581 /// </remarks>
3582 /// <param name='agentID'>ID of agent to close</param>
3583 /// <param name='closeChildAgents'>
3584 /// Close the neighbour child agents associated with this client.
3585 /// </param>
3586 ///
3587
3588 private object m_removeClientPrivLock = new Object();
3589
3590 public void RemoveClient(UUID agentID, bool closeChildAgents)
3552 { 3591 {
3553// CheckHeartbeat(); 3592 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3554 bool isChildAgent = false;
3555 AgentCircuitData acd;
3556 3593
3557 lock (m_removeClientLock) 3594 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3595 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3596 // However, will keep for now just in case.
3597 if (acd == null)
3558 { 3598 {
3559 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3599 m_log.ErrorFormat(
3600 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3560 3601
3561 if (acd == null) 3602 return;
3562 {
3563 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3564 return;
3565 }
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 } 3603 }
3574 3604 else
3575 lock (acd)
3576 { 3605 {
3606 m_authenticateHandler.RemoveCircuit(agentID);
3607 }
3608
3609 // TODO: Can we now remove this lock?
3610 lock (m_removeClientPrivLock)
3611 {
3612 bool isChildAgent = false;
3613
3577 ScenePresence avatar = GetScenePresence(agentID); 3614 ScenePresence avatar = GetScenePresence(agentID);
3578 3615
3616 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3617 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3618 // However, will keep for now just in case.
3579 if (avatar == null) 3619 if (avatar == null)
3580 { 3620 {
3581 m_log.WarnFormat( 3621 m_log.ErrorFormat(
3582 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3622 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3583 3623
3584 return; 3624 return;
3585 } 3625 }
3586 3626
3587 try 3627 try
3588 { 3628 {
3589 isChildAgent = avatar.IsChildAgent; 3629 isChildAgent = avatar.IsChildAgent;
3590 3630
3591 m_log.DebugFormat( 3631 m_log.DebugFormat(
3592 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3632 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3593 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3633 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3594 3634
3595 // Don't do this to root agents, it's not nice for the viewer 3635 // Don't do this to root agents, it's not nice for the viewer
3596 if (closeChildAgents && isChildAgent) 3636 if (closeChildAgents && isChildAgent)
3597 { 3637 {
3598 // Tell a single agent to disconnect from the region. 3638 // Tell a single agent to disconnect from the region.
3599 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3639 // Let's do this via UDP
3600 if (eq != null) 3640 avatar.ControllingClient.SendShutdownConnectionNotice();
3601 {
3602 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3603 }
3604 else
3605 {
3606 avatar.ControllingClient.SendShutdownConnectionNotice();
3607 }
3608 } 3641 }
3609 3642
3610 // Only applies to root agents. 3643 // Only applies to root agents.
@@ -3620,40 +3653,44 @@ namespace OpenSim.Region.Framework.Scenes
3620 if (closeChildAgents && CapsModule != null) 3653 if (closeChildAgents && CapsModule != null)
3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); 3654 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3622 3655
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) 3656 if (closeChildAgents && !isChildAgent)
3629 { 3657 {
3630 List<ulong> regions = avatar.KnownRegionHandles; 3658 List<ulong> regions = avatar.KnownRegionHandles;
3631 regions.Remove(RegionInfo.RegionHandle); 3659 regions.Remove(RegionInfo.RegionHandle);
3632 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3660
3661 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3662 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3633 } 3663 }
3634 3664
3635 m_eventManager.TriggerClientClosed(agentID, this); 3665 m_eventManager.TriggerClientClosed(agentID, this);
3666// m_log.Debug("[Scene]TriggerClientClosed done");
3636 m_eventManager.TriggerOnRemovePresence(agentID); 3667 m_eventManager.TriggerOnRemovePresence(agentID);
3668// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3637 3669
3638 if (!isChildAgent) 3670 if (!isChildAgent)
3639 { 3671 {
3640 if (AttachmentsModule != null) 3672 if (AttachmentsModule != null)
3641 { 3673 {
3674// m_log.Debug("[Scene]DeRezAttachments");
3642 AttachmentsModule.DeRezAttachments(avatar); 3675 AttachmentsModule.DeRezAttachments(avatar);
3676// m_log.Debug("[Scene]DeRezAttachments done");
3643 } 3677 }
3644 3678
3645 ForEachClient( 3679 ForEachClient(
3646 delegate(IClientAPI client) 3680 delegate(IClientAPI client)
3647 { 3681 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3682 //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 }); } 3683 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3684 catch (NullReferenceException) { }
3651 }); 3685 });
3652 } 3686 }
3653 3687
3654 // It's possible for child agents to have transactions if changes are being made cross-border. 3688 // It's possible for child agents to have transactions if changes are being made cross-border.
3655 if (AgentTransactionsModule != null) 3689 if (AgentTransactionsModule != null)
3690 {
3691// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3656 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3692 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3693 }
3657 m_log.Debug("[Scene] The avatar has left the building"); 3694 m_log.Debug("[Scene] The avatar has left the building");
3658 } 3695 }
3659 catch (Exception e) 3696 catch (Exception e)
@@ -3727,7 +3764,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3764 }
3728 deleteIDs.Add(localID); 3765 deleteIDs.Add(localID);
3729 } 3766 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3767
3768 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3769 }
3732 3770
3733 #endregion 3771 #endregion
@@ -3763,13 +3801,16 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3801 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3802 /// the LLUDP stack).
3765 /// </remarks> 3803 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3804 /// <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> 3805 /// <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 3806 /// <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> 3807 /// 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 3808 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3809 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3810 ///
3811 private object m_newUserConnLock = new object();
3812
3813 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3814 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3815 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3816 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,17 +3830,19 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3830 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})", 3831 "[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, 3832 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3833 (acd.child ? "child" : "root"),
3793 agent.firstname, 3834 acd.firstname,
3794 agent.lastname, 3835 acd.lastname,
3795 agent.AgentID, 3836 acd.AgentID,
3796 agent.circuitcode, 3837 acd.circuitcode,
3797 agent.IPAddress, 3838 acd.IPAddress,
3798 agent.Viewer, 3839 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3840 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3841 acd.startpos
3801 ); 3842 );
3802 3843
3844// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3845
3803 if (!LoginsEnabled) 3846 if (!LoginsEnabled)
3804 { 3847 {
3805 reason = "Logins Disabled"; 3848 reason = "Logins Disabled";
@@ -3815,7 +3858,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3858 {
3816 foreach (string viewer in m_AllowedViewers) 3859 foreach (string viewer in m_AllowedViewers)
3817 { 3860 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3861 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3862 {
3820 ViewerDenied = false; 3863 ViewerDenied = false;
3821 break; 3864 break;
@@ -3832,7 +3875,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3875 {
3833 foreach (string viewer in m_BannedViewers) 3876 foreach (string viewer in m_BannedViewers)
3834 { 3877 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3878 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3879 {
3837 ViewerDenied = true; 3880 ViewerDenied = true;
3838 break; 3881 break;
@@ -3844,54 +3887,135 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3887 {
3845 m_log.DebugFormat( 3888 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3889 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3890 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3891 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3892 return false;
3850 } 3893 }
3851 3894
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3895 ILandObject land;
3896 ScenePresence sp;
3853 3897
3854 // If we have noo presence here or if that presence is a zombie root 3898 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3899 {
3858 if (CapsModule != null) 3900 sp = GetScenePresence(acd.AgentID);
3901
3902 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3903 // closed.
3904 if (sp != null && sp.IsChildAgent
3905 && (sp.LifecycleState == ScenePresenceState.Running
3906 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3907 {
3860 lock (agent) 3908 m_log.DebugFormat(
3909 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3910 sp.Name, sp.LifecycleState, Name);
3911
3912 // In the case where, for example, an A B C D region layout, an avatar may
3913 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3914 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3915 //
3916 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3917 // teleport, since realistically, the close request should always be processed before any other
3918 // region tried to re-establish a child agent. This is much simpler since the logic below is
3919 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3920 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3921 // flag when no teleport had taken place (and hence no close was going to come).
3922// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3923// {
3924// m_log.DebugFormat(
3925// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3926// sp.Name, Name);
3927//
3928// sp.DoNotCloseAfterTeleport = true;
3929// }
3930// else if (EntityTransferModule.IsInTransit(sp.UUID))
3931
3932 sp.LifecycleState = ScenePresenceState.Running;
3933
3934 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3935 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3936 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3937
3938 m_log.DebugFormat(
3939 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3940 sp.Name, Name);
3864 } 3941 }
3865 } 3942 }
3866 } 3943 }
3867 3944
3945 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3946 // allow unpredictable things to happen.
3868 if (sp != null) 3947 if (sp != null)
3869 { 3948 {
3870 if (!sp.IsChildAgent) 3949 const int polls = 10;
3950 const int pollInterval = 1000;
3951 int pollsLeft = polls;
3952
3953 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3954 Thread.Sleep(pollInterval);
3955
3956 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3957 {
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( 3958 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3959 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3960 sp.Name, Name, polls * pollInterval / 1000);
3878 3961
3879 sp.ControllingClient.Close(true, true); 3962 return false;
3880 sp = null; 3963 }
3964 else if (polls != pollsLeft)
3965 {
3966 m_log.DebugFormat(
3967 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3968 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3969 }
3882 } 3970 }
3883 3971
3884 lock (agent) 3972 // TODO: can we remove this lock?
3973 lock (m_newUserConnLock)
3885 { 3974 {
3886 //On login test land permisions 3975 if (sp != null && !sp.IsChildAgent)
3976 {
3977 // We have a root agent. Is it in transit?
3978 if (!EntityTransferModule.IsInTransit(sp.UUID))
3979 {
3980 // We have a zombie from a crashed session.
3981 // Or the same user is trying to be root twice here, won't work.
3982 // Kill it.
3983 m_log.WarnFormat(
3984 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3985 sp.Name, sp.UUID, RegionInfo.RegionName);
3986
3987 if (sp.ControllingClient != null)
3988 CloseAgent(sp.UUID, true);
3989
3990 sp = null;
3991 }
3992 //else
3993 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3994 }
3995
3996 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3997 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3998 // If the checks fail, we remove the circuit.
3999 acd.teleportFlags = teleportFlags;
4000
4001 // Remove any preexisting circuit - we don't want duplicates
4002 // This is a stab at preventing avatar "ghosting"
4003 if (vialogin)
4004 m_authenticateHandler.RemoveCircuit(acd.AgentID);
4005
4006 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
4007
4008 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
4009
4010 // On login test land permisions
3887 if (vialogin) 4011 if (vialogin)
3888 { 4012 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 4013 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 4014 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 4015 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 4016 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 4017 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 4018 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 4019 return false;
3896 } 4020 }
3897 } 4021 }
@@ -3902,84 +4026,97 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 4026 {
3903 try 4027 try
3904 { 4028 {
3905 if (!VerifyUserPresence(agent, out reason)) 4029 if (!VerifyUserPresence(acd, out reason))
4030 {
4031 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 4032 return false;
3907 } catch (Exception e) 4033 }
4034 }
4035 catch (Exception e)
3908 { 4036 {
3909 m_log.ErrorFormat( 4037 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 4038 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
4039
4040 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 4041 return false;
3912 } 4042 }
3913 } 4043 }
3914 4044
3915 try 4045 try
3916 { 4046 {
3917 // Always check estate if this is a login. Always 4047 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 4048 {
3921 if (!AuthorizeUser(agent, out reason)) 4049 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 4050 return false;
3923 return false;
3924 }
3925 } 4051 }
3926 } 4052 }
3927 catch (Exception e) 4053 catch (Exception e)
3928 { 4054 {
3929 m_log.ErrorFormat( 4055 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4056 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4057
4058 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4059 return false;
3932 } 4060 }
3933 4061
3934 m_log.InfoFormat( 4062 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4063 "[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, 4064 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4065 acd.AgentID, acd.circuitcode);
3938 4066
4067 if (CapsModule != null)
4068 {
4069 CapsModule.SetAgentCapsSeeds(acd);
4070 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4071 }
3939 } 4072 }
3940 else 4073 else
3941 { 4074 {
3942 // Let the SP know how we got here. This has a lot of interesting 4075 // Let the SP know how we got here. This has a lot of interesting
3943 // uses down the line. 4076 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4077 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4078
3946 if (sp.IsChildAgent) 4079 if (sp.IsChildAgent)
3947 { 4080 {
3948 m_log.DebugFormat( 4081 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4082 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4083 acd.AgentID, RegionInfo.RegionName);
3951
3952 sp.AdjustKnownSeeds();
3953 4084
3954 if (CapsModule != null) 4085 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4086 {
4087 CapsModule.SetAgentCapsSeeds(acd);
4088 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4089 }
4090
4091 sp.AdjustKnownSeeds();
3956 } 4092 }
3957 } 4093 }
3958 }
3959 4094
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4095 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4096 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4097 // request for the HG avatar appears to trigger before the user name is cached.
4098 CacheUserName(null, acd);
4099 }
3963 4100
3964 if (CapsModule != null) 4101 if (CapsModule != null)
3965 { 4102 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4103 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4104 }
3968 4105
3969 if (vialogin) 4106 if (vialogin)
3970 { 4107 {
3971// CleanDroppedAttachments(); 4108// CleanDroppedAttachments();
3972 4109
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4110 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4111 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4112 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4113 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4114 }
3978 4115
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4116 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4117 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4118 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4119 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4120 }
3984 4121
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4122 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,68 +4126,88 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4126 {
3990 lock (EastBorders) 4127 lock (EastBorders)
3991 { 4128 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4129 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4130 {
3994 m_log.Warn("FIX AGENT POSITION"); 4131 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4132 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4133 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4134 acd.startpos.Z = 720;
3998 } 4135 }
3999 } 4136 }
4000 lock (NorthBorders) 4137 lock (NorthBorders)
4001 { 4138 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4139 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4140 {
4004 m_log.Warn("FIX Agent POSITION"); 4141 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4142 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4143 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4144 acd.startpos.Z = 720;
4008 } 4145 }
4009 } 4146 }
4010 } else 4147 } else
4011 { 4148 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4149 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4150 {
4014 m_log.Warn("FIX AGENT POSITION"); 4151 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4152 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4153 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4154 acd.startpos.Z = 720;
4018 } 4155 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4156 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4157 {
4021 m_log.Warn("FIX Agent POSITION"); 4158 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4159 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4160 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4161 acd.startpos.Z = 720;
4025 } 4162 }
4026 } 4163 }
4027 4164
4165// m_log.DebugFormat(
4166// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4167// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4168
4028 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4169 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4029 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4170 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4030 RegionInfo.EstateSettings.AllowDirectTeleport == false && 4171 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4031 !viahome && !godlike) 4172 !viahome && !godlike)
4032 { 4173 {
4033 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4174 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4034 // Can have multiple SpawnPoints 4175
4035 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4176 if (telehub != null)
4036 if (spawnpoints.Count > 1)
4037 { 4177 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4178 // Can have multiple SpawnPoints
4039 if (SpawnPointRouting == "random") 4179 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4180 if (spawnpoints.Count > 1)
4041 telehub.AbsolutePosition, 4181 {
4042 telehub.GroupRotation 4182 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4043 ); 4183 if (SpawnPointRouting == "random")
4184 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4185 telehub.AbsolutePosition,
4186 telehub.GroupRotation
4187 );
4188 else
4189 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4190 telehub.AbsolutePosition,
4191 telehub.GroupRotation
4192 );
4193 }
4194 else if (spawnpoints.Count == 1)
4195 {
4196 // We have a single SpawnPoint and will route the agent to it
4197 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4198 }
4044 else 4199 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4200 {
4046 telehub.AbsolutePosition, 4201 m_log.DebugFormat(
4047 telehub.GroupRotation 4202 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4048 ); 4203 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4204 }
4049 } 4205 }
4050 else 4206 else
4051 { 4207 {
4052 // We have a single SpawnPoint and will route the agent to it 4208 m_log.DebugFormat(
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4209 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4210 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4054 } 4211 }
4055 4212
4056 return true; 4213 return true;
@@ -4063,7 +4220,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4220 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4221 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4222 {
4066 agent.startpos = land.LandData.UserLocation; 4223 acd.startpos = land.LandData.UserLocation;
4067 } 4224 }
4068 } 4225 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4226 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4315,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4315 /// <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 4316 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4317 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4318 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4319 {
4163 reason = String.Empty; 4320 reason = String.Empty;
4164 4321
@@ -4177,67 +4334,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4334 }
4178 } 4335 }
4179 4336
4180 if (RegionInfo.EstateSettings != null) 4337 // We only test the things below when we want to cut off
4338 // child agents from being present in the scene for which their root
4339 // agent isn't allowed. Otherwise, we allow child agents. The test for
4340 // the root is done elsewhere (QueryAccess)
4341 if (!bypassAccessControl)
4181 { 4342 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4343 if (RegionInfo.EstateSettings != null)
4183 { 4344 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4345 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4346 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4347 {
4187 RegionInfo.RegionName); 4348 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4349 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4350 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4351 RegionInfo.RegionName);
4352 return false;
4353 }
4189 } 4354 }
4190 } 4355 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 { 4356 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4357 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4358 }
4207 else 4359
4360 List<UUID> agentGroups = new List<UUID>();
4361
4362 if (m_groupsModule != null)
4208 { 4363 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4364 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4365
4366 if (GroupMembership != null)
4367 {
4368 for (int i = 0; i < GroupMembership.Length; i++)
4369 agentGroups.Add(GroupMembership[i].GroupID);
4370 }
4371 else
4372 {
4373 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4374 }
4210 } 4375 }
4211 }
4212 4376
4213 bool groupAccess = false; 4377 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4378 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4379
4216 if (estateGroups != null) 4380 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4381 {
4220 if (agentGroups.Contains(group)) 4382 foreach (UUID group in estateGroups)
4221 { 4383 {
4222 groupAccess = true; 4384 if (agentGroups.Contains(group))
4223 break; 4385 {
4386 groupAccess = true;
4387 break;
4388 }
4224 } 4389 }
4225 } 4390 }
4226 } 4391 else
4227 else 4392 {
4228 { 4393 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4394 }
4230 }
4231 4395
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4396 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4397 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4398 !groupAccess)
4235 { 4399 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4400 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); 4401 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.", 4402 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4403 RegionInfo.RegionName);
4240 return false; 4404 return false;
4405 }
4241 } 4406 }
4242 4407
4243 // TODO: estate/region settings are not properly hooked up 4408 // TODO: estate/region settings are not properly hooked up
@@ -4362,13 +4527,18 @@ namespace OpenSim.Region.Framework.Scenes
4362 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4527 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4363 /// Appearance, animations, position, etc.</param> 4528 /// Appearance, animations, position, etc.</param>
4364 /// <returns>true if we handled it.</returns> 4529 /// <returns>true if we handled it.</returns>
4365 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4530 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4366 { 4531 {
4367 m_log.DebugFormat( 4532 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4533 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4534
4370 // XPTO: if this agent is not allowed here as root, always return false 4535 if (!LoginsEnabled)
4371 4536 {
4537// reason = "Logins Disabled";
4538 m_log.DebugFormat(
4539 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4540 return false;
4541 }
4372 // We have to wait until the viewer contacts this region after receiving EAC. 4542 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4543 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4544 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4382,7 +4552,7 @@ namespace OpenSim.Region.Framework.Scenes
4382 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4552 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4383 if (nearestParcel == null) 4553 if (nearestParcel == null)
4384 { 4554 {
4385 m_log.DebugFormat( 4555 m_log.InfoFormat(
4386 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4556 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4387 cAgentData.AgentID, RegionInfo.RegionName); 4557 cAgentData.AgentID, RegionInfo.RegionName);
4388 4558
@@ -4390,13 +4560,50 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4560 }
4391 4561
4392 // We have to wait until the viewer contacts this region 4562 // 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 4563 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4394 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4564 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4565 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4566 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4567
4397 if (childAgentUpdate != null) 4568 if (sp != null)
4398 { 4569 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4570 if (!sp.IsChildAgent)
4571 {
4572 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4573 sp.Name, sp.UUID, Name);
4574 return false;
4575 }
4576 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4577 {
4578 m_log.WarnFormat(
4579 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4580 sp.UUID, cAgentData.SessionID);
4581
4582 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4583 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4584 }
4585
4586 sp.UpdateChildAgent(cAgentData);
4587
4588 int ntimes = 20;
4589 if (cAgentData.SenderWantsToWaitForRoot)
4590 {
4591 while (sp.IsChildAgent && ntimes-- > 0)
4592 Thread.Sleep(1000);
4593
4594 if (sp.IsChildAgent)
4595 m_log.WarnFormat(
4596 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4597 sp.Name, sp.UUID, Name);
4598 else
4599 m_log.InfoFormat(
4600 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4601 sp.Name, sp.UUID, Name, 20 - ntimes);
4602
4603 if (sp.IsChildAgent)
4604 return false;
4605 }
4606
4400 return true; 4607 return true;
4401 } 4608 }
4402 4609
@@ -4409,12 +4616,17 @@ namespace OpenSim.Region.Framework.Scenes
4409 /// </summary> 4616 /// </summary>
4410 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4617 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
4411 /// <returns>true if we handled it.</returns> 4618 /// <returns>true if we handled it.</returns>
4412 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4619 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4413 { 4620 {
4414 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4621 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4622 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4623 if (childAgentUpdate != null)
4417 { 4624 {
4625// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4626// // Only warn for now
4627// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4628// childAgentUpdate.UUID, cAgentData.SessionID);
4629
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4630 // 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.. 4631 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4632 if (childAgentUpdate.IsChildAgent)
@@ -4424,7 +4636,7 @@ namespace OpenSim.Region.Framework.Scenes
4424 uint tRegionX = RegionInfo.RegionLocX; 4636 uint tRegionX = RegionInfo.RegionLocX;
4425 uint tRegionY = RegionInfo.RegionLocY; 4637 uint tRegionY = RegionInfo.RegionLocY;
4426 //Send Data to ScenePresence 4638 //Send Data to ScenePresence
4427 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4639 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4428 // Not Implemented: 4640 // Not Implemented:
4429 //TODO: Do we need to pass the message on to one of our neighbors? 4641 //TODO: Do we need to pass the message on to one of our neighbors?
4430 } 4642 }
@@ -4451,35 +4663,99 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4663 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4664 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4665 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 4666
4459 return sp; 4667 return sp;
4460 } 4668 }
4461 4669
4462 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4670 /// <summary>
4671 /// Authenticated close (via network)
4672 /// </summary>
4673 /// <param name="agentID"></param>
4674 /// <param name="force"></param>
4675 /// <param name="auth_token"></param>
4676 /// <returns></returns>
4677 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4463 { 4678 {
4464 agent = null; 4679 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4465 ScenePresence sp = GetScenePresence(id); 4680
4466 if ((sp != null) && (!sp.IsChildAgent)) 4681 // Check that the auth_token is valid
4682 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4683
4684 if (acd == null)
4467 { 4685 {
4468 sp.IsChildAgent = true; 4686 m_log.DebugFormat(
4469 return sp.CopyAgent(out agent); 4687 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4688 agentID, Name);
4689
4690 return false;
4691 }
4692
4693 if (acd.SessionID.ToString() == auth_token)
4694 {
4695 return CloseAgent(agentID, force);
4696 }
4697 else
4698 {
4699 m_log.WarnFormat(
4700 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4701 agentID, auth_token, Name);
4470 } 4702 }
4471 4703
4472 return false; 4704 return false;
4473 } 4705 }
4474 4706
4475 public bool IncomingCloseAgent(UUID agentID) 4707// public bool IncomingCloseAgent(UUID agentID)
4476 { 4708// {
4477 return IncomingCloseAgent(agentID, false); 4709// return IncomingCloseAgent(agentID, false);
4478 } 4710// }
4711
4712// public bool IncomingCloseChildAgent(UUID agentID)
4713// {
4714// return IncomingCloseAgent(agentID, true);
4715// }
4479 4716
4480 public bool IncomingCloseChildAgent(UUID agentID) 4717 /// <summary>
4718 /// Tell a single client to prepare to close.
4719 /// </summary>
4720 /// <remarks>
4721 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4722 /// internal use - other callers should almost certainly called CloseClient().
4723 /// </remarks>
4724 /// <param name="sp"></param>
4725 /// <returns>true if pre-close state notification was successful. false if the agent
4726 /// was not in a state where it could transition to pre-close.</returns>
4727 public bool IncomingPreCloseClient(ScenePresence sp)
4481 { 4728 {
4482 return IncomingCloseAgent(agentID, true); 4729 lock (m_removeClientLock)
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 pre-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 if (sp.LifecycleState != ScenePresenceState.Running)
4747 {
4748 m_log.DebugFormat(
4749 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4750 sp.Name, Name, sp.LifecycleState);
4751
4752 return false;
4753 }
4754
4755 sp.LifecycleState = ScenePresenceState.PreRemove;
4756
4757 return true;
4758 }
4483 } 4759 }
4484 4760
4485 /// <summary> 4761 /// <summary>
@@ -4490,18 +4766,71 @@ namespace OpenSim.Region.Framework.Scenes
4490 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4766 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4491 /// force unless you are absolutely sure that the agent is dead and a normal close is not working. 4767 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4492 /// </param> 4768 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4769 public override bool CloseAgent(UUID agentID, bool force)
4494 { 4770 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4771 ScenePresence sp;
4496 4772
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4773 lock (m_removeClientLock)
4498 if (presence != null)
4499 { 4774 {
4500 presence.ControllingClient.Close(force, force); 4775 sp = GetScenePresence(agentID);
4776
4777 if (sp == null)
4778 {
4779 // If there is no scene presence, we may be handling a dead
4780 // client. These can keep an avatar from reentering a region
4781 // and since they don't get cleaned up they will stick
4782 // around until region restart. So, if there is no SP,
4783 // remove the client as well.
4784 IClientAPI client = null;
4785 if (m_clientManager.TryGetValue(agentID, out client))
4786 {
4787 m_clientManager.Remove(agentID);
4788 if (CapsModule != null)
4789 CapsModule.RemoveCaps(agentID, 0);
4790 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4791 return true;
4792 }
4793 m_log.DebugFormat(
4794 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4795 agentID, Name);
4796
4797 return false;
4798 }
4799
4800 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4801 {
4802 m_log.DebugFormat(
4803 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4804 sp.Name, Name, sp.LifecycleState);
4805
4806 return false;
4807 }
4808
4809 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4810 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4811 // want to obey this close since C may have renewed the child agent lease on B.
4812 if (sp.DoNotCloseAfterTeleport)
4813 {
4814 m_log.DebugFormat(
4815 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4816 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4817
4818 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4819 sp.DoNotCloseAfterTeleport = false;
4820
4821 return false;
4822 }
4823
4824 sp.LifecycleState = ScenePresenceState.Removing;
4825 }
4826
4827 if (sp != null)
4828 {
4829 sp.ControllingClient.Close(force, force);
4501 return true; 4830 return true;
4502 } 4831 }
4503 4832
4504 // Agent not here 4833 // Agent not here
4505 return false; 4834 return false;
4506 } 4835 }
4507 4836
@@ -4700,7 +5029,10 @@ namespace OpenSim.Region.Framework.Scenes
4700 5029
4701 public LandData GetLandData(float x, float y) 5030 public LandData GetLandData(float x, float y)
4702 { 5031 {
4703 return LandChannel.GetLandObject(x, y).LandData; 5032 ILandObject parcel = LandChannel.GetLandObject(x, y);
5033 if (parcel == null)
5034 return null;
5035 return parcel.LandData;
4704 } 5036 }
4705 5037
4706 /// <summary> 5038 /// <summary>
@@ -4716,7 +5048,10 @@ namespace OpenSim.Region.Framework.Scenes
4716 public LandData GetLandData(uint x, uint y) 5048 public LandData GetLandData(uint x, uint y)
4717 { 5049 {
4718 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5050 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4719 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5051 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5052 if (parcel == null)
5053 return null;
5054 return parcel.LandData;
4720 } 5055 }
4721 5056
4722 #endregion 5057 #endregion
@@ -5091,21 +5426,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5426
5092 #endregion 5427 #endregion
5093 5428
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 5429
5110// Commented pending deletion since this method no longer appears to do anything at all 5430// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5431// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5977,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5977 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5978 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5979 {
5660 minX = 256; 5980 minX = float.MaxValue;
5661 maxX = -256; 5981 maxX = float.MinValue;
5662 minY = 256; 5982 minY = float.MaxValue;
5663 maxY = -256; 5983 maxY = float.MinValue;
5664 minZ = 8192; 5984 minZ = float.MaxValue;
5665 maxZ = -256; 5985 maxZ = float.MinValue;
5666 5986
5667 List<Vector3> offsets = new List<Vector3>(); 5987 List<Vector3> offsets = new List<Vector3>();
5668 5988
@@ -5802,17 +6122,6 @@ Environment.Exit(1);
5802 { 6122 {
5803 reason = "You are banned from the region"; 6123 reason = "You are banned from the region";
5804 6124
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)) 6125 if (Permissions.IsGod(agentID))
5817 { 6126 {
5818 reason = String.Empty; 6127 reason = String.Empty;
@@ -5862,9 +6171,9 @@ Environment.Exit(1);
5862 6171
5863 try 6172 try
5864 { 6173 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6174 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6175 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6176 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6177 return false;
5869 } 6178 }
5870 } 6179 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 74c9582..f5be7a7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -1,575 +1,593 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading; 31using System.Threading;
32using OpenMetaverse; 32using OpenMetaverse;
33using log4net; 33using log4net;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37 37
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using GridRegion = OpenSim.Services.Interfaces.GridRegion; 39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40 40
41namespace OpenSim.Region.Framework.Scenes 41namespace OpenSim.Region.Framework.Scenes
42{ 42{
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46 protected static readonly string LogHeader = "[SCENE]";
47 #region Events 47
48 48 #region Events
49 public event restart OnRestart; 49
50 50 public event restart OnRestart;
51 #endregion 51
52 52 #endregion
53 #region Fields 53
54 54 #region Fields
55 public string Name { get { return RegionInfo.RegionName; } } 55
56 56 public string Name { get { return RegionInfo.RegionName; } }
57 public IConfigSource Config 57
58 { 58 public IConfigSource Config
59 get { return GetConfig(); } 59 {
60 } 60 get { return GetConfig(); }
61 61 }
62 protected virtual IConfigSource GetConfig() 62
63 { 63 protected virtual IConfigSource GetConfig()
64 return null; 64 {
65 } 65 return null;
66 66 }
67 /// <value> 67
68 /// All the region modules attached to this scene. 68 /// <value>
69 /// </value> 69 /// All the region modules attached to this scene.
70 public Dictionary<string, IRegionModuleBase> RegionModules 70 /// </value>
71 { 71 public Dictionary<string, IRegionModuleBase> RegionModules
72 get { return m_regionModules; } 72 {
73 } 73 get { return m_regionModules; }
74 private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>(); 74 }
75 75 private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>();
76 /// <value> 76
77 /// The module interfaces available from this scene. 77 /// <value>
78 /// </value> 78 /// The module interfaces available from this scene.
79 protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>(); 79 /// </value>
80 80 protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>();
81 protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>(); 81
82 82 protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>();
83 /// <value> 83
84 /// The module commanders available from this scene 84 /// <value>
85 /// </value> 85 /// The module commanders available from this scene
86 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>(); 86 /// </value>
87 87 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
88 /// <value> 88
89 /// Registered classes that are capable of creating entities. 89 /// <value>
90 /// </value> 90 /// Registered classes that are capable of creating entities.
91 protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>(); 91 /// </value>
92 92 protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>();
93 /// <summary> 93
94 /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is 94 /// <summary>
95 /// dispensed. 95 /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
96 /// </summary> 96 /// dispensed.
97 protected uint m_lastAllocatedLocalId = 720000; 97 /// </summary>
98 98 protected uint m_lastAllocatedLocalId = 720000;
99 private readonly Mutex _primAllocateMutex = new Mutex(false); 99
100 100 private readonly Mutex _primAllocateMutex = new Mutex(false);
101 protected readonly ClientManager m_clientManager = new ClientManager(); 101
102 102 protected readonly ClientManager m_clientManager = new ClientManager();
103 public bool LoginsEnabled 103
104 { 104 public bool LoginsEnabled
105 get 105 {
106 { 106 get
107 return m_loginsEnabled; 107 {
108 } 108 return m_loginsEnabled;
109 109 }
110 set 110
111 { 111 set
112 if (m_loginsEnabled != value) 112 {
113 { 113 if (m_loginsEnabled != value)
114 m_loginsEnabled = value; 114 {
115 EventManager.TriggerRegionLoginsStatusChange(this); 115 m_loginsEnabled = value;
116 } 116 EventManager.TriggerRegionLoginsStatusChange(this);
117 } 117 }
118 } 118 }
119 private bool m_loginsEnabled; 119 }
120 120 private bool m_loginsEnabled;
121 public bool Ready 121
122 { 122 public bool Ready
123 get 123 {
124 { 124 get
125 return m_ready; 125 {
126 } 126 return m_ready;
127 127 }
128 set 128
129 { 129 set
130 if (m_ready != value) 130 {
131 { 131 if (m_ready != value)
132 m_ready = value; 132 {
133 EventManager.TriggerRegionReadyStatusChange(this); 133 m_ready = value;
134 } 134 EventManager.TriggerRegionReadyStatusChange(this);
135 } 135 }
136 } 136 }
137 private bool m_ready; 137 }
138 138 private bool m_ready;
139 public float TimeDilation 139
140 { 140 public float TimeDilation
141 get { return 1.0f; } 141 {
142 } 142 get { return 1.0f; }
143 143 }
144 protected ulong m_regionHandle; 144
145 protected string m_regionName; 145 protected ulong m_regionHandle;
146 146 protected string m_regionName;
147 public ITerrainChannel Heightmap; 147
148 148 public ITerrainChannel Heightmap;
149 /// <value> 149
150 /// Allows retrieval of land information for this scene. 150 /// <value>
151 /// </value> 151 /// Allows retrieval of land information for this scene.
152 public ILandChannel LandChannel; 152 /// </value>
153 153 public ILandChannel LandChannel;
154 /// <value> 154
155 /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules 155 /// <value>
156 /// to subscribe to scene events. 156 /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules
157 /// </value> 157 /// to subscribe to scene events.
158 public EventManager EventManager 158 /// </value>
159 { 159 public EventManager EventManager
160 get { return m_eventManager; } 160 {
161 } 161 get { return m_eventManager; }
162 protected EventManager m_eventManager; 162 }
163 163 protected EventManager m_eventManager;
164 protected ScenePermissions m_permissions; 164
165 public ScenePermissions Permissions 165 protected ScenePermissions m_permissions;
166 { 166 public ScenePermissions Permissions
167 get { return m_permissions; } 167 {
168 } 168 get { return m_permissions; }
169 169 }
170 protected string m_datastore; 170
171 171 protected string m_datastore;
172 /* Used by the loadbalancer plugin on GForge */ 172
173 protected RegionStatus m_regStatus; 173 /* Used by the loadbalancer plugin on GForge */
174 public RegionStatus RegionStatus 174 protected RegionStatus m_regStatus;
175 { 175 public RegionStatus RegionStatus
176 get { return m_regStatus; } 176 {
177 set { m_regStatus = value; } 177 get { return m_regStatus; }
178 } 178 set { m_regStatus = value; }
179 179 }
180 #endregion 180
181 181 #endregion
182 public SceneBase(RegionInfo regInfo) 182
183 { 183 public SceneBase(RegionInfo regInfo)
184 RegionInfo = regInfo; 184 {
185 } 185 RegionInfo = regInfo;
186 186 }
187 #region Update Methods 187
188 188 #region Update Methods
189 /// <summary> 189
190 /// Called to update the scene loop by a number of frames and until shutdown. 190 /// <summary>
191 /// </summary> 191 /// Called to update the scene loop by a number of frames and until shutdown.
192 /// <param name="frames"> 192 /// </summary>
193 /// Number of frames to update. Exits on shutdown even if there are frames remaining. 193 /// <param name="frames">
194 /// If -1 then updates until shutdown. 194 /// Number of frames to update. Exits on shutdown even if there are frames remaining.
195 /// </param> 195 /// If -1 then updates until shutdown.
196 public abstract void Update(int frames); 196 /// </param>
197 197 public abstract void Update(int frames);
198 #endregion 198
199 199 #endregion
200 #region Terrain Methods 200
201 201 #region Terrain Methods
202 /// <summary> 202
203 /// Loads the World heightmap 203 /// <summary>
204 /// </summary> 204 /// Loads the World heightmap
205 public abstract void LoadWorldMap(); 205 /// </summary>
206 206 public abstract void LoadWorldMap();
207 /// <summary> 207
208 /// Send the region heightmap to the client 208 /// <summary>
209 /// </summary> 209 /// Send the region heightmap to the client
210 /// <param name="RemoteClient">Client to send to</param> 210 /// </summary>
211 public virtual void SendLayerData(IClientAPI RemoteClient) 211 /// <param name="RemoteClient">Client to send to</param>
212 { 212 public virtual void SendLayerData(IClientAPI RemoteClient)
213 RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); 213 {
214 } 214 RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
215 215 }
216 #endregion 216
217 217 #endregion
218 #region Add/Remove Agent/Avatar 218
219 219 #region Add/Remove Agent/Avatar
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 220
221 public abstract void RemoveClient(UUID agentID, bool closeChildAgents); 221 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
222 222
223 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 223 public abstract bool CloseAgent(UUID agentID, bool force);
224 { 224
225 scenePresence = null; 225 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
226 ScenePresence sp = null; 226 {
227 if (TryGetScenePresence(agentID, out sp)) 227 scenePresence = null;
228 { 228 ScenePresence sp = null;
229 scenePresence = sp; 229 if (TryGetScenePresence(agentID, out sp))
230 return true; 230 {
231 } 231 scenePresence = sp;
232 232 return true;
233 return false; 233 }
234 } 234
235 235 return false;
236 /// <summary> 236 }
237 /// Try to get a scene presence from the scene 237
238 /// </summary> 238 /// <summary>
239 /// <param name="agentID"></param> 239 /// Try to get a scene presence from the scene
240 /// <param name="scenePresence">null if there is no scene presence with the given agent id</param> 240 /// </summary>
241 /// <returns>true if there was a scene presence with the given id, false otherwise.</returns> 241 /// <param name="agentID"></param>
242 public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); 242 /// <param name="scenePresence">null if there is no scene presence with the given agent id</param>
243 243 /// <returns>true if there was a scene presence with the given id, false otherwise.</returns>
244 #endregion 244 public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence);
245 245
246 /// <summary> 246 #endregion
247 /// 247
248 /// </summary> 248 /// <summary>
249 /// <returns></returns> 249 ///
250 public virtual RegionInfo RegionInfo { get; private set; } 250 /// </summary>
251 251 /// <returns></returns>
252 #region admin stuff 252 public virtual RegionInfo RegionInfo { get; private set; }
253 253
254 public abstract void OtherRegionUp(GridRegion otherRegion); 254 #region admin stuff
255 255
256 public virtual string GetSimulatorVersion() 256 public abstract void OtherRegionUp(GridRegion otherRegion);
257 { 257
258 return "OpenSimulator Server"; 258 public virtual string GetSimulatorVersion()
259 } 259 {
260 260 return "OpenSimulator Server";
261 #endregion 261 }
262 262
263 #region Shutdown 263 #endregion
264 264
265 /// <summary> 265 #region Shutdown
266 /// Tidy before shutdown 266
267 /// </summary> 267 /// <summary>
268 public virtual void Close() 268 /// Tidy before shutdown
269 { 269 /// </summary>
270 try 270 public virtual void Close()
271 { 271 {
272 EventManager.TriggerShutdown(); 272 try
273 } 273 {
274 catch (Exception e) 274 EventManager.TriggerShutdown();
275 { 275 }
276 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); 276 catch (Exception e)
277 } 277 {
278 } 278 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e));
279 279 }
280 #endregion 280 }
281 281
282 /// <summary> 282 #endregion
283 /// Returns a new unallocated local ID 283
284 /// </summary> 284 /// <summary>
285 /// <returns>A brand new local ID</returns> 285 /// Returns a new unallocated local ID
286 public uint AllocateLocalId() 286 /// </summary>
287 { 287 /// <returns>A brand new local ID</returns>
288 uint myID; 288 public uint AllocateLocalId()
289 289 {
290 _primAllocateMutex.WaitOne(); 290 uint myID;
291 myID = ++m_lastAllocatedLocalId; 291
292 _primAllocateMutex.ReleaseMutex(); 292 _primAllocateMutex.WaitOne();
293 293 myID = ++m_lastAllocatedLocalId;
294 return myID; 294 _primAllocateMutex.ReleaseMutex();
295 } 295
296 296 return myID;
297 #region Module Methods 297 }
298 298
299 /// <summary> 299 public uint AllocatePresenceLocalId()
300 /// Add a region-module to this scene. TODO: This will replace AddModule in the future. 300 {
301 /// </summary> 301 uint myID;
302 /// <param name="name"></param> 302
303 /// <param name="module"></param> 303 _primAllocateMutex.WaitOne();
304 public void AddRegionModule(string name, IRegionModuleBase module) 304 myID = ++m_lastAllocatedLocalId;
305 { 305 ++m_lastAllocatedLocalId;
306 if (!RegionModules.ContainsKey(name)) 306 _primAllocateMutex.ReleaseMutex();
307 { 307
308 RegionModules.Add(name, module); 308 return myID;
309 } 309 }
310 } 310
311 311 #region Module Methods
312 public void RemoveRegionModule(string name) 312
313 { 313 /// <summary>
314 RegionModules.Remove(name); 314 /// Add a region-module to this scene. TODO: This will replace AddModule in the future.
315 } 315 /// </summary>
316 316 /// <param name="name"></param>
317 /// <summary> 317 /// <param name="module"></param>
318 /// Register a module commander. 318 public void AddRegionModule(string name, IRegionModuleBase module)
319 /// </summary> 319 {
320 /// <param name="commander"></param> 320 if (!RegionModules.ContainsKey(name))
321 public void RegisterModuleCommander(ICommander commander) 321 {
322 { 322 RegionModules.Add(name, module);
323 lock (m_moduleCommanders) 323 }
324 { 324 }
325 m_moduleCommanders.Add(commander.Name, commander); 325
326 } 326 public void RemoveRegionModule(string name)
327 } 327 {
328 328 RegionModules.Remove(name);
329 /// <summary> 329 }
330 /// Unregister a module commander and all its commands 330
331 /// </summary> 331 /// <summary>
332 /// <param name="name"></param> 332 /// Register a module commander.
333 public void UnregisterModuleCommander(string name) 333 /// </summary>
334 { 334 /// <param name="commander"></param>
335 lock (m_moduleCommanders) 335 public void RegisterModuleCommander(ICommander commander)
336 { 336 {
337 ICommander commander; 337 lock (m_moduleCommanders)
338 if (m_moduleCommanders.TryGetValue(name, out commander)) 338 {
339 m_moduleCommanders.Remove(name); 339 m_moduleCommanders.Add(commander.Name, commander);
340 } 340 }
341 } 341 }
342 342
343 /// <summary> 343 /// <summary>
344 /// Get a module commander 344 /// Unregister a module commander and all its commands
345 /// </summary> 345 /// </summary>
346 /// <param name="name"></param> 346 /// <param name="name"></param>
347 /// <returns>The module commander, null if no module commander with that name was found</returns> 347 public void UnregisterModuleCommander(string name)
348 public ICommander GetCommander(string name) 348 {
349 { 349 lock (m_moduleCommanders)
350 lock (m_moduleCommanders) 350 {
351 { 351 ICommander commander;
352 if (m_moduleCommanders.ContainsKey(name)) 352 if (m_moduleCommanders.TryGetValue(name, out commander))
353 return m_moduleCommanders[name]; 353 m_moduleCommanders.Remove(name);
354 } 354 }
355 355 }
356 return null; 356
357 } 357 /// <summary>
358 358 /// Get a module commander
359 public Dictionary<string, ICommander> GetCommanders() 359 /// </summary>
360 { 360 /// <param name="name"></param>
361 return m_moduleCommanders; 361 /// <returns>The module commander, null if no module commander with that name was found</returns>
362 } 362 public ICommander GetCommander(string name)
363 363 {
364 /// <summary> 364 lock (m_moduleCommanders)
365 /// Register an interface to a region module. This allows module methods to be called directly as 365 {
366 /// well as via events. If there is already a module registered for this interface, it is not replaced 366 if (m_moduleCommanders.ContainsKey(name))
367 /// (is this the best behaviour?) 367 return m_moduleCommanders[name];
368 /// </summary> 368 }
369 /// <param name="mod"></param> 369
370 public void RegisterModuleInterface<M>(M mod) 370 return null;
371 { 371 }
372// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); 372
373 373 public Dictionary<string, ICommander> GetCommanders()
374 List<Object> l = null; 374 {
375 if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) 375 return m_moduleCommanders;
376 { 376 }
377 l = new List<Object>(); 377
378 ModuleInterfaces.Add(typeof(M), l); 378 /// <summary>
379 } 379 /// Register an interface to a region module. This allows module methods to be called directly as
380 380 /// well as via events. If there is already a module registered for this interface, it is not replaced
381 if (l.Count > 0) 381 /// (is this the best behaviour?)
382 return; 382 /// </summary>
383 383 /// <param name="mod"></param>
384 l.Add(mod); 384 public void RegisterModuleInterface<M>(M mod)
385 385 {
386 if (mod is IEntityCreator) 386// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M));
387 { 387
388 IEntityCreator entityCreator = (IEntityCreator)mod; 388 List<Object> l = null;
389 foreach (PCode pcode in entityCreator.CreationCapabilities) 389 if (!ModuleInterfaces.TryGetValue(typeof(M), out l))
390 { 390 {
391 m_entityCreators[pcode] = entityCreator; 391 l = new List<Object>();
392 } 392 ModuleInterfaces.Add(typeof(M), l);
393 } 393 }
394 } 394
395 395 if (l.Count > 0)
396 public void UnregisterModuleInterface<M>(M mod) 396 return;
397 { 397
398 List<Object> l; 398 l.Add(mod);
399 if (ModuleInterfaces.TryGetValue(typeof(M), out l)) 399
400 { 400 if (mod is IEntityCreator)
401 if (l.Remove(mod)) 401 {
402 { 402 IEntityCreator entityCreator = (IEntityCreator)mod;
403 if (mod is IEntityCreator) 403 foreach (PCode pcode in entityCreator.CreationCapabilities)
404 { 404 {
405 IEntityCreator entityCreator = (IEntityCreator)mod; 405 m_entityCreators[pcode] = entityCreator;
406 foreach (PCode pcode in entityCreator.CreationCapabilities) 406 }
407 { 407 }
408 m_entityCreators[pcode] = null; 408 }
409 } 409
410 } 410 public void UnregisterModuleInterface<M>(M mod)
411 } 411 {
412 } 412 List<Object> l;
413 } 413 if (ModuleInterfaces.TryGetValue(typeof(M), out l))
414 414 {
415 public void StackModuleInterface<M>(M mod) 415 if (l.Remove(mod))
416 { 416 {
417 List<Object> l; 417 if (mod is IEntityCreator)
418 if (ModuleInterfaces.ContainsKey(typeof(M))) 418 {
419 l = ModuleInterfaces[typeof(M)]; 419 IEntityCreator entityCreator = (IEntityCreator)mod;
420 else 420 foreach (PCode pcode in entityCreator.CreationCapabilities)
421 l = new List<Object>(); 421 {
422 422 m_entityCreators[pcode] = null;
423 if (l.Contains(mod)) 423 }
424 return; 424 }
425 425 }
426 l.Add(mod); 426 }
427 427 }
428 if (mod is IEntityCreator) 428
429 { 429 public void StackModuleInterface<M>(M mod)
430 IEntityCreator entityCreator = (IEntityCreator)mod; 430 {
431 foreach (PCode pcode in entityCreator.CreationCapabilities) 431 List<Object> l;
432 { 432 if (ModuleInterfaces.ContainsKey(typeof(M)))
433 m_entityCreators[pcode] = entityCreator; 433 l = ModuleInterfaces[typeof(M)];
434 } 434 else
435 } 435 l = new List<Object>();
436 436
437 ModuleInterfaces[typeof(M)] = l; 437 if (l.Contains(mod))
438 } 438 return;
439 439
440 /// <summary> 440 l.Add(mod);
441 /// For the given interface, retrieve the region module which implements it. 441
442 /// </summary> 442 if (mod is IEntityCreator)
443 /// <returns>null if there is no registered module implementing that interface</returns> 443 {
444 public T RequestModuleInterface<T>() 444 IEntityCreator entityCreator = (IEntityCreator)mod;
445 { 445 foreach (PCode pcode in entityCreator.CreationCapabilities)
446 if (ModuleInterfaces.ContainsKey(typeof(T)) && 446 {
447 (ModuleInterfaces[typeof(T)].Count > 0)) 447 m_entityCreators[pcode] = entityCreator;
448 return (T)ModuleInterfaces[typeof(T)][0]; 448 }
449 else 449 }
450 return default(T); 450
451 } 451 ModuleInterfaces[typeof(M)] = l;
452 452 }
453 /// <summary> 453
454 /// For the given interface, retrieve an array of region modules that implement it. 454 /// <summary>
455 /// </summary> 455 /// For the given interface, retrieve the region module which implements it.
456 /// <returns>an empty array if there are no registered modules implementing that interface</returns> 456 /// </summary>
457 public T[] RequestModuleInterfaces<T>() 457 /// <returns>null if there is no registered module implementing that interface</returns>
458 { 458 public T RequestModuleInterface<T>()
459 if (ModuleInterfaces.ContainsKey(typeof(T))) 459 {
460 { 460 if (ModuleInterfaces.ContainsKey(typeof(T)) &&
461 List<T> ret = new List<T>(); 461 (ModuleInterfaces[typeof(T)].Count > 0))
462 462 return (T)ModuleInterfaces[typeof(T)][0];
463 foreach (Object o in ModuleInterfaces[typeof(T)]) 463 else
464 ret.Add((T)o); 464 return default(T);
465 return ret.ToArray(); 465 }
466 } 466
467 else 467 /// <summary>
468 { 468 /// For the given interface, retrieve an array of region modules that implement it.
469 return new T[] {}; 469 /// </summary>
470 } 470 /// <returns>an empty array if there are no registered modules implementing that interface</returns>
471 } 471 public T[] RequestModuleInterfaces<T>()
472 472 {
473 #endregion 473 if (ModuleInterfaces.ContainsKey(typeof(T)))
474 474 {
475 /// <summary> 475 List<T> ret = new List<T>();
476 /// Call this from a region module to add a command to the OpenSim console. 476
477 /// </summary> 477 foreach (Object o in ModuleInterfaces[typeof(T)])
478 /// <param name="mod"></param> 478 ret.Add((T)o);
479 /// <param name="command"></param> 479 return ret.ToArray();
480 /// <param name="shorthelp"></param> 480 }
481 /// <param name="longhelp"></param> 481 else
482 /// <param name="callback"></param> 482 {
483 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) 483 return new T[] {};
484 { 484 }
485 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); 485 }
486 } 486
487 487 #endregion
488 /// <summary> 488
489 /// Call this from a region module to add a command to the OpenSim console. 489 /// <summary>
490 /// </summary> 490 /// Call this from a region module to add a command to the OpenSim console.
491 /// <param name="mod"> 491 /// </summary>
492 /// The use of IRegionModuleBase is a cheap trick to get a different method signature, 492 /// <param name="mod"></param>
493 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. 493 /// <param name="command"></param>
494 /// </param> 494 /// <param name="shorthelp"></param>
495 /// <param name="category"> 495 /// <param name="longhelp"></param>
496 /// Category of the command. This is the section under which it will appear when the user asks for help 496 /// <param name="callback"></param>
497 /// </param> 497 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
498 /// <param name="command"></param> 498 {
499 /// <param name="shorthelp"></param> 499 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback);
500 /// <param name="longhelp"></param> 500 }
501 /// <param name="callback"></param> 501
502 public void AddCommand( 502 /// <summary>
503 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) 503 /// Call this from a region module to add a command to the OpenSim console.
504 { 504 /// </summary>
505 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); 505 /// <param name="mod">
506 } 506 /// The use of IRegionModuleBase is a cheap trick to get a different method signature,
507 507 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway.
508 /// <summary> 508 /// </param>
509 /// Call this from a region module to add a command to the OpenSim console. 509 /// <param name="category">
510 /// </summary> 510 /// Category of the command. This is the section under which it will appear when the user asks for help
511 /// <param name="mod"></param> 511 /// </param>
512 /// <param name="command"></param> 512 /// <param name="command"></param>
513 /// <param name="shorthelp"></param> 513 /// <param name="shorthelp"></param>
514 /// <param name="longhelp"></param> 514 /// <param name="longhelp"></param>
515 /// <param name="descriptivehelp"></param> 515 /// <param name="callback"></param>
516 /// <param name="callback"></param> 516 public void AddCommand(
517 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 517 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
518 { 518 {
519 string moduleName = ""; 519 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback);
520 520 }
521 if (module != null) 521
522 moduleName = module.Name; 522 /// <summary>
523 523 /// Call this from a region module to add a command to the OpenSim console.
524 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); 524 /// </summary>
525 } 525 /// <param name="mod"></param>
526 526 /// <param name="command"></param>
527 /// <summary> 527 /// <param name="shorthelp"></param>
528 /// Call this from a region module to add a command to the OpenSim console. 528 /// <param name="longhelp"></param>
529 /// </summary> 529 /// <param name="descriptivehelp"></param>
530 /// <param name="category"> 530 /// <param name="callback"></param>
531 /// Category of the command. This is the section under which it will appear when the user asks for help 531 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
532 /// </param> 532 {
533 /// <param name="mod"></param> 533 string moduleName = "";
534 /// <param name="command"></param> 534
535 /// <param name="shorthelp"></param> 535 if (module != null)
536 /// <param name="longhelp"></param> 536 moduleName = module.Name;
537 /// <param name="descriptivehelp"></param> 537
538 /// <param name="callback"></param> 538 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback);
539 public void AddCommand( 539 }
540 string category, IRegionModuleBase module, string command, 540
541 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 541 /// <summary>
542 { 542 /// Call this from a region module to add a command to the OpenSim console.
543 if (MainConsole.Instance == null) 543 /// </summary>
544 return; 544 /// <param name="category">
545 545 /// Category of the command. This is the section under which it will appear when the user asks for help
546 bool shared = false; 546 /// </param>
547 547 /// <param name="mod"></param>
548 if (module != null) 548 /// <param name="command"></param>
549 shared = module is ISharedRegionModule; 549 /// <param name="shorthelp"></param>
550 550 /// <param name="longhelp"></param>
551 MainConsole.Instance.Commands.AddCommand( 551 /// <param name="descriptivehelp"></param>
552 category, shared, command, shorthelp, longhelp, descriptivehelp, callback); 552 /// <param name="callback"></param>
553 } 553 public void AddCommand(
554 554 string category, IRegionModuleBase module, string command,
555 public virtual ISceneObject DeserializeObject(string representation) 555 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
556 { 556 {
557 return null; 557 if (MainConsole.Instance == null)
558 } 558 return;
559 559
560 public virtual bool AllowScriptCrossings 560 bool shared = false;
561 { 561
562 get { return false; } 562 if (module != null)
563 } 563 shared = module is ISharedRegionModule;
564 564
565 public void Restart() 565 MainConsole.Instance.Commands.AddCommand(
566 { 566 category, shared, command, shorthelp, longhelp, descriptivehelp, callback);
567 // This has to be here to fire the event 567 }
568 restart handlerPhysicsCrash = OnRestart; 568
569 if (handlerPhysicsCrash != null) 569 public virtual ISceneObject DeserializeObject(string representation)
570 handlerPhysicsCrash(RegionInfo); 570 {
571 } 571 return null;
572 572 }
573 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); 573
574 } 574 public virtual bool AllowScriptCrossings
575} 575 {
576 get { return false; }
577 }
578
579 public virtual void Start()
580 {
581 }
582
583 public void Restart()
584 {
585 // This has to be here to fire the event
586 restart handlerPhysicsCrash = OnRestart;
587 if (handlerPhysicsCrash != null)
588 handlerPhysicsCrash(RegionInfo);
589 }
590
591 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
592 }
593}
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 775a4c2..52f46f2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// This Closes child agents on neighboring regions 200 /// This Closes child agents on neighboring regions
201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
202 /// </summary> 202 /// </summary>
203 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 203 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
204 { 204 {
205 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 205 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
206 206
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes
209 Utils.LongToUInts(regionHandle, out x, out y); 209 Utils.LongToUInts(regionHandle, out x, out y);
210 210
211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
212 m_scene.SimulationService.CloseChildAgent(destination, agentID);
213 }
214 212
215 private void SendCloseChildAgentCompleted(IAsyncResult iar) 213 m_log.DebugFormat(
216 { 214 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
217 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; 215
218 icon.EndInvoke(iar); 216 m_scene.SimulationService.CloseAgent(destination, agentID, auth_token);
219 } 217 }
220 218
221 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 219 /// <summary>
220 /// Closes a child agents in a collection of regions. Does so asynchronously
221 /// so that the caller doesn't wait.
222 /// </summary>
223 /// <param name="agentID"></param>
224 /// <param name="regionslst"></param>
225 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
222 { 226 {
223 foreach (ulong handle in regionslst) 227 foreach (ulong handle in regionslst)
224 { 228 {
225 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; 229 ulong handleCopy = handle;
226 d.BeginInvoke(agentID, handle, 230 Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
227 SendCloseChildAgentCompleted,
228 d);
229 } 231 }
230 } 232 }
231 233
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..92ce411 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -271,38 +271,52 @@ namespace OpenSim.Region.Framework.Scenes
271 { 271 {
272 if (!m_parentScene.CombineRegions) 272 if (!m_parentScene.CombineRegions)
273 { 273 {
274 // temporary checks to remove after varsize suport
275 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
276 if (regionSizeX == 0)
277 regionSizeX = Constants.RegionSize;
278 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
279 if (regionSizeY == 0)
280 regionSizeY = Constants.RegionSize;
281
274 // KF: Check for out-of-region, move inside and make static. 282 // KF: Check for out-of-region, move inside and make static.
275 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, 283 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
276 sceneObject.RootPart.GroupPosition.Y, 284 sceneObject.RootPart.GroupPosition.Y,
277 sceneObject.RootPart.GroupPosition.Z); 285 sceneObject.RootPart.GroupPosition.Z);
278 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || 286 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
279 npos.X > Constants.RegionSize || 287 npos.X > regionSizeX ||
280 npos.Y > Constants.RegionSize)) 288 npos.Y > regionSizeY))
281 { 289 {
282 if (npos.X < 0.0) npos.X = 1.0f; 290 if (npos.X < 0.0) npos.X = 1.0f;
283 if (npos.Y < 0.0) npos.Y = 1.0f; 291 if (npos.Y < 0.0) npos.Y = 1.0f;
284 if (npos.Z < 0.0) npos.Z = 0.0f; 292 if (npos.Z < 0.0) npos.Z = 0.0f;
285 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; 293 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
286 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; 294 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
287 295
296 SceneObjectPart rootpart = sceneObject.RootPart;
297 rootpart.GroupPosition = npos;
298
288 foreach (SceneObjectPart part in sceneObject.Parts) 299 foreach (SceneObjectPart part in sceneObject.Parts)
289 { 300 {
301 if (part == rootpart)
302 continue;
290 part.GroupPosition = npos; 303 part.GroupPosition = npos;
291 } 304 }
292 sceneObject.RootPart.Velocity = Vector3.Zero; 305 rootpart.Velocity = Vector3.Zero;
293 sceneObject.RootPart.AngularVelocity = Vector3.Zero; 306 rootpart.AngularVelocity = Vector3.Zero;
294 sceneObject.RootPart.Acceleration = Vector3.Zero; 307 rootpart.Acceleration = Vector3.Zero;
295 sceneObject.RootPart.Velocity = Vector3.Zero;
296 } 308 }
297 } 309 }
298 310
311 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
312
299 if (attachToBackup && (!alreadyPersisted)) 313 if (attachToBackup && (!alreadyPersisted))
300 { 314 {
301 sceneObject.ForceInventoryPersistence(); 315 sceneObject.ForceInventoryPersistence();
302 sceneObject.HasGroupChanged = true; 316 sceneObject.HasGroupChanged = true;
303 } 317 }
304 318
305 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 319 return ret;
306 } 320 }
307 321
308 /// <summary> 322 /// <summary>
@@ -319,12 +333,16 @@ namespace OpenSim.Region.Framework.Scenes
319 /// </returns> 333 /// </returns>
320 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 334 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
321 { 335 {
322 // Ensure that we persist this new scene object if it's not an 336
337 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
338
339 // Ensure that we persist this new scene object if it's not an
323 // attachment 340 // attachment
341
324 if (attachToBackup) 342 if (attachToBackup)
325 sceneObject.HasGroupChanged = true; 343 sceneObject.HasGroupChanged = true;
326 344
327 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 345 return ret;
328 } 346 }
329 347
330 /// <summary> 348 /// <summary>
@@ -421,9 +439,9 @@ namespace OpenSim.Region.Framework.Scenes
421 { 439 {
422 Vector3 scale = part.Shape.Scale; 440 Vector3 scale = part.Shape.Scale;
423 441
424 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 442 scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
425 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 443 scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
426 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 444 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
427 445
428 part.Shape.Scale = scale; 446 part.Shape.Scale = scale;
429 } 447 }
@@ -432,36 +450,39 @@ namespace OpenSim.Region.Framework.Scenes
432 450
433 sceneObject.AttachToScene(m_parentScene); 451 sceneObject.AttachToScene(m_parentScene);
434 452
435 if (sendClientUpdates)
436 sceneObject.ScheduleGroupForFullUpdate();
437
438 Entities.Add(sceneObject); 453 Entities.Add(sceneObject);
439 454
440 if (attachToBackup)
441 sceneObject.AttachToBackup();
442
443 lock (SceneObjectGroupsByFullID) 455 lock (SceneObjectGroupsByFullID)
444 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 456 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
445 457
446 lock (SceneObjectGroupsByFullPartID) 458 foreach (SceneObjectPart part in parts)
447 { 459 {
448 foreach (SceneObjectPart part in parts) 460 lock (SceneObjectGroupsByFullPartID)
449 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 461 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
450 }
451 462
452 lock (SceneObjectGroupsByLocalPartID) 463 lock (SceneObjectGroupsByLocalPartID)
453 {
454// m_log.DebugFormat(
455// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
456// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
457
458 foreach (SceneObjectPart part in parts)
459 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 464 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
460 } 465 }
461 466
467 if (sendClientUpdates)
468 sceneObject.ScheduleGroupForFullUpdate();
469
470 if (attachToBackup)
471 sceneObject.AttachToBackup();
472
462 return true; 473 return true;
463 } 474 }
464 475
476 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
477 {
478 // no tests, caller has responsability...
479 lock (SceneObjectGroupsByFullPartID)
480 SceneObjectGroupsByFullPartID[part.UUID] = grp;
481
482 lock (SceneObjectGroupsByLocalPartID)
483 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
484 }
485
465 /// <summary> 486 /// <summary>
466 /// Delete an object from the scene 487 /// Delete an object from the scene
467 /// </summary> 488 /// </summary>
@@ -488,25 +509,23 @@ namespace OpenSim.Region.Framework.Scenes
488 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 509 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
489 RemovePhysicalPrim(grp.PrimCount); 510 RemovePhysicalPrim(grp.PrimCount);
490 } 511 }
491 512
513 bool ret = Entities.Remove(uuid);
514
492 lock (SceneObjectGroupsByFullID) 515 lock (SceneObjectGroupsByFullID)
493 SceneObjectGroupsByFullID.Remove(grp.UUID); 516 SceneObjectGroupsByFullID.Remove(grp.UUID);
494 517
495 lock (SceneObjectGroupsByFullPartID) 518 SceneObjectPart[] parts = grp.Parts;
519 for (int i = 0; i < parts.Length; i++)
496 { 520 {
497 SceneObjectPart[] parts = grp.Parts; 521 lock (SceneObjectGroupsByFullPartID)
498 for (int i = 0; i < parts.Length; i++)
499 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 522 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
500 }
501 523
502 lock (SceneObjectGroupsByLocalPartID) 524 lock (SceneObjectGroupsByLocalPartID)
503 {
504 SceneObjectPart[] parts = grp.Parts;
505 for (int i = 0; i < parts.Length; i++)
506 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 525 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
507 } 526 }
508 527
509 return Entities.Remove(uuid); 528 return ret;
510 } 529 }
511 530
512 /// <summary> 531 /// <summary>
@@ -631,40 +650,16 @@ namespace OpenSim.Region.Framework.Scenes
631 protected internal ScenePresence CreateAndAddChildScenePresence( 650 protected internal ScenePresence CreateAndAddChildScenePresence(
632 IClientAPI client, AvatarAppearance appearance, PresenceType type) 651 IClientAPI client, AvatarAppearance appearance, PresenceType type)
633 { 652 {
634 ScenePresence newAvatar = null;
635
636 // ScenePresence always defaults to child agent 653 // ScenePresence always defaults to child agent
637 newAvatar = new ScenePresence(client, m_parentScene, appearance, type); 654 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 655
663 Entities[presence.UUID] = presence; 656 Entities[presence.UUID] = presence;
664 657
665 m_scenePresencesLock.EnterWriteLock(); 658 m_scenePresencesLock.EnterWriteLock();
666 try 659 try
667 { 660 {
661 m_numChildAgents++;
662
668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 663 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 664 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
670 665
@@ -675,7 +670,7 @@ namespace OpenSim.Region.Framework.Scenes
675 } 670 }
676 else 671 else
677 { 672 {
678 // Remember the old presene reference from the dictionary 673 // Remember the old presence reference from the dictionary
679 ScenePresence oldref = newmap[presence.UUID]; 674 ScenePresence oldref = newmap[presence.UUID];
680 // Replace the presence reference in the dictionary with the new value 675 // Replace the presence reference in the dictionary with the new value
681 newmap[presence.UUID] = presence; 676 newmap[presence.UUID] = presence;
@@ -691,6 +686,8 @@ namespace OpenSim.Region.Framework.Scenes
691 { 686 {
692 m_scenePresencesLock.ExitWriteLock(); 687 m_scenePresencesLock.ExitWriteLock();
693 } 688 }
689
690 return presence;
694 } 691 }
695 692
696 /// <summary> 693 /// <summary>
@@ -949,7 +946,7 @@ namespace OpenSim.Region.Framework.Scenes
949 m_log.WarnFormat( 946 m_log.WarnFormat(
950 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", 947 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
951 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); 948 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
952 949 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
953 SceneObjectGroupsByLocalPartID.Remove(localID); 950 SceneObjectGroupsByLocalPartID.Remove(localID);
954 } 951 }
955 } 952 }
@@ -1569,6 +1566,7 @@ namespace OpenSim.Region.Framework.Scenes
1569 // VolumeDetect can't be set via UI and will always be off when a change is made there 1566 // VolumeDetect can't be set via UI and will always be off when a change is made there
1570 // now only change volume dtc if phantom off 1567 // now only change volume dtc if phantom off
1571 1568
1569 bool wantedPhys = UsePhysics;
1572 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1570 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1573 { 1571 {
1574 bool vdtc; 1572 bool vdtc;
@@ -1585,10 +1583,17 @@ namespace OpenSim.Region.Framework.Scenes
1585 if (part != null) 1583 if (part != null)
1586 { 1584 {
1587 part.UpdateExtraPhysics(PhysData); 1585 part.UpdateExtraPhysics(PhysData);
1588 if (part.UpdatePhysRequired) 1586 if (part.UpdatePhysRequired && remoteClient != null)
1589 remoteClient.SendPartPhysicsProprieties(part); 1587 remoteClient.SendPartPhysicsProprieties(part);
1590 } 1588 }
1591 } 1589 }
1590
1591 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1592 {
1593 remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " +
1594 m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None");
1595 group.RootPart.ScheduleFullUpdate();
1596 }
1592 } 1597 }
1593 } 1598 }
1594 } 1599 }
@@ -1818,7 +1823,7 @@ namespace OpenSim.Region.Framework.Scenes
1818 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1823 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1819 1824
1820 // We do this in reverse to get the link order of the prims correct 1825 // We do this in reverse to get the link order of the prims correct
1821 for (int i = 0 ; i < children.Count ; i++) 1826 for (int i = 0; i < children.Count; i++)
1822 { 1827 {
1823 SceneObjectGroup child = children[i].ParentGroup; 1828 SceneObjectGroup child = children[i].ParentGroup;
1824 1829
@@ -1829,7 +1834,7 @@ namespace OpenSim.Region.Framework.Scenes
1829 // Make sure no child prim is set for sale 1834 // Make sure no child prim is set for sale
1830 // So that, on delink, no prims are unwittingly 1835 // So that, on delink, no prims are unwittingly
1831 // left for sale and sold off 1836 // left for sale and sold off
1832 1837
1833 if (child != null) 1838 if (child != null)
1834 { 1839 {
1835 child.RootPart.ObjectSaleType = 0; 1840 child.RootPart.ObjectSaleType = 0;
@@ -1864,12 +1869,13 @@ namespace OpenSim.Region.Framework.Scenes
1864 } 1869 }
1865 finally 1870 finally
1866 { 1871 {
1872/*
1867 lock (SceneObjectGroupsByLocalPartID) 1873 lock (SceneObjectGroupsByLocalPartID)
1868 { 1874 {
1869 foreach (SceneObjectPart part in parentGroup.Parts) 1875 foreach (SceneObjectPart part in parentGroup.Parts)
1870 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; 1876 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1871 } 1877 }
1872 1878*/
1873 parentGroup.AdjustChildPrimPermissions(); 1879 parentGroup.AdjustChildPrimPermissions();
1874 parentGroup.HasGroupChanged = true; 1880 parentGroup.HasGroupChanged = true;
1875 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); 1881 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
@@ -1952,20 +1958,17 @@ namespace OpenSim.Region.Framework.Scenes
1952 // slated for unlink, we need to do this 1958 // slated for unlink, we need to do this
1953 // Unlink the remaining set 1959 // Unlink the remaining set
1954 // 1960 //
1955 bool sendEventsToRemainder = true; 1961 bool sendEventsToRemainder = false;
1956 if (numChildren > 1) 1962 if (numChildren == 2) // only one child prim no re-link needed
1957 sendEventsToRemainder = false; 1963 sendEventsToRemainder = true;
1958 1964
1959 foreach (SceneObjectPart p in newSet) 1965 foreach (SceneObjectPart p in newSet)
1960 { 1966 {
1961 if (p != group.RootPart) 1967 if (p != group.RootPart)
1962 { 1968 {
1963 group.DelinkFromGroup(p, sendEventsToRemainder); 1969 group.DelinkFromGroup(p, sendEventsToRemainder);
1964 if (numChildren > 2) 1970 if (sendEventsToRemainder) // finish single child prim now
1965 { 1971 {
1966 }
1967 else
1968 {
1969 p.ParentGroup.HasGroupChanged = true; 1972 p.ParentGroup.HasGroupChanged = true;
1970 p.ParentGroup.ScheduleGroupForFullUpdate(); 1973 p.ParentGroup.ScheduleGroupForFullUpdate();
1971 } 1974 }
@@ -1998,8 +2001,8 @@ namespace OpenSim.Region.Framework.Scenes
1998 newChild.ClearUpdateSchedule(); 2001 newChild.ClearUpdateSchedule();
1999 2002
2000 LinkObjects(newRoot, newSet); 2003 LinkObjects(newRoot, newSet);
2001 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2004// if (!affectedGroups.Contains(newRoot.ParentGroup))
2002 affectedGroups.Add(newRoot.ParentGroup); 2005// affectedGroups.Add(newRoot.ParentGroup);
2003 } 2006 }
2004 } 2007 }
2005 2008
@@ -2126,21 +2129,15 @@ namespace OpenSim.Region.Framework.Scenes
2126 lock (SceneObjectGroupsByFullID) 2129 lock (SceneObjectGroupsByFullID)
2127 SceneObjectGroupsByFullID[copy.UUID] = copy; 2130 SceneObjectGroupsByFullID[copy.UUID] = copy;
2128 2131
2129 SceneObjectPart[] children = copy.Parts; 2132 SceneObjectPart[] parts = copy.Parts;
2130 2133 foreach (SceneObjectPart part in parts)
2131 lock (SceneObjectGroupsByFullPartID)
2132 { 2134 {
2133 SceneObjectGroupsByFullPartID[copy.UUID] = copy; 2135 lock (SceneObjectGroupsByFullPartID)
2134 foreach (SceneObjectPart part in children)
2135 SceneObjectGroupsByFullPartID[part.UUID] = copy; 2136 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2136 } 2137 lock (SceneObjectGroupsByLocalPartID)
2137
2138 lock (SceneObjectGroupsByLocalPartID)
2139 {
2140 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2141 foreach (SceneObjectPart part in children)
2142 SceneObjectGroupsByLocalPartID[part.LocalId] = copy; 2138 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2143 } 2139 }
2140
2144 // PROBABLE END OF FIXME 2141 // PROBABLE END OF FIXME
2145 2142
2146 // Since we copy from a source group that is in selected 2143 // Since we copy from a source group that is in selected
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index c70342f..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes
420 return false; 420 return false;
421 } 421 }
422 422
423 /// <summary>
424 /// Set the debug packet level on each current scene. This level governs which packets are printed out to the
425 /// console.
426 /// </summary>
427 /// <param name="newDebug"></param>
428 /// <param name="name">Name of avatar to debug</param>
429 public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name)
430 {
431 ForEachSelectedScene(scene =>
432 scene.ForEachScenePresence(sp =>
433 {
434 if (name == null || sp.Name == name)
435 {
436 m_log.DebugFormat(
437 "Packet debug for {0} ({1}) set to {2}",
438 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug);
439
440 sp.ControllingClient.DebugPacketLevel = newDebug;
441 }
442 })
443 );
444 }
445
446 public List<ScenePresence> GetCurrentSceneAvatars() 423 public List<ScenePresence> GetCurrentSceneAvatars()
447 { 424 {
448 List<ScenePresence> avatars = new List<ScenePresence>(); 425 List<ScenePresence> avatars = new List<ScenePresence>();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f8624e7..8c50a81 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes
67 { 67 {
68 int scriptsStarted = 0; 68 int scriptsStarted = 0;
69 69
70 if (m_scene == null)
71 {
72 m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances");
73 return 0;
74 }
75
70 // Don't start scripts if they're turned off in the region! 76 // Don't start scripts if they're turned off in the region!
71 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 77 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
72 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 86f60bb..0e2e3c7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -111,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes
111 STATUS_ROTATE_Z = 0x008, 111 STATUS_ROTATE_Z = 0x008,
112 } 112 }
113 113
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
115 public static readonly uint SLAM = 16;
116
114 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 117 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
115 118
116 /// <summary> 119 /// <summary>
@@ -506,15 +509,17 @@ namespace OpenSim.Region.Framework.Scenes
506 { 509 {
507 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 510 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
508 } 511 }
509 512
510
511
512 private struct avtocrossInfo 513 private struct avtocrossInfo
513 { 514 {
514 public ScenePresence av; 515 public ScenePresence av;
515 public uint ParentID; 516 public uint ParentID;
516 } 517 }
517 518
519
520 public bool inTransit = false;
521 public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
522
518 /// <summary> 523 /// <summary>
519 /// The absolute position of this scene object in the scene 524 /// The absolute position of this scene object in the scene
520 /// </summary> 525 /// </summary>
@@ -525,213 +530,253 @@ namespace OpenSim.Region.Framework.Scenes
525 { 530 {
526 Vector3 val = value; 531 Vector3 val = value;
527 532
528 if (Scene != null) 533 if (!IsAttachmentCheckFull() && !Scene.LoadingPrims &&
534 ( Scene.TestBorderCross(val, Cardinals.E) ||
535 Scene.TestBorderCross(val, Cardinals.W) ||
536 Scene.TestBorderCross(val, Cardinals.N) ||
537 Scene.TestBorderCross(val, Cardinals.S))
538 )
529 { 539 {
530 if ( 540 if (!inTransit)
531 // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E)
532 // || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
533 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N)
534 // || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
535 // Experimental change for better border crossings.
536 // The commented out original lines above would, it seems, trigger
537 // a border crossing a little early or late depending on which
538 // direction the object was moving.
539 (Scene.TestBorderCross(val, Cardinals.E)
540 || Scene.TestBorderCross(val, Cardinals.W)
541 || Scene.TestBorderCross(val, Cardinals.N)
542 || Scene.TestBorderCross(val, Cardinals.S))
543 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
544 {
545 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
546 uint x = 0;
547 uint y = 0;
548 string version = String.Empty;
549 Vector3 newpos = Vector3.Zero;
550 OpenSim.Services.Interfaces.GridRegion destination = null;
551
552 if (m_rootPart.KeyframeMotion != null)
553 m_rootPart.KeyframeMotion.StartCrossingCheck();
554
555 bool canCross = true;
556 foreach (ScenePresence av in m_linkedAvatars)
557 {
558 // We need to cross these agents. First, let's find
559 // out if any of them can't cross for some reason.
560 // We have to deny the crossing entirely if any
561 // of them are banned. Alternatively, we could
562 // unsit banned agents....
563
564
565 // We set the avatar position as being the object
566 // position to get the region to send to
567 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
568 {
569 canCross = false;
570 break;
571 }
572
573 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
574 }
575
576 if (canCross)
577 {
578 // We unparent the SP quietly so that it won't
579 // be made to stand up
580
581 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
582
583 foreach (ScenePresence av in m_linkedAvatars)
584 {
585 avtocrossInfo avinfo = new avtocrossInfo();
586 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
587 if (parentPart != null)
588 av.ParentUUID = parentPart.UUID;
589
590 avinfo.av = av;
591 avinfo.ParentID = av.ParentID;
592 avsToCross.Add(avinfo);
593
594 av.PrevSitOffset = av.OffsetPosition;
595 av.ParentID = 0;
596 }
597
598 // m_linkedAvatars.Clear();
599 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
600
601 // Normalize
602 if (val.X >= Constants.RegionSize)
603 val.X -= Constants.RegionSize;
604 if (val.Y >= Constants.RegionSize)
605 val.Y -= Constants.RegionSize;
606 if (val.X < 0)
607 val.X += Constants.RegionSize;
608 if (val.Y < 0)
609 val.Y += Constants.RegionSize;
610
611 // If it's deleted, crossing was successful
612 if (IsDeleted)
613 {
614 // foreach (ScenePresence av in m_linkedAvatars)
615 foreach (avtocrossInfo avinfo in avsToCross)
616 {
617 ScenePresence av = avinfo.av;
618 if (!av.IsInTransit) // just in case...
619 {
620 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
621
622 av.IsInTransit = true;
623
624 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
625 d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
626 }
627 else
628 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
629 }
630 avsToCross.Clear();
631 return;
632 }
633 else // cross failed, put avas back ??
634 {
635 foreach (avtocrossInfo avinfo in avsToCross)
636 {
637 ScenePresence av = avinfo.av;
638 av.ParentUUID = UUID.Zero;
639 av.ParentID = avinfo.ParentID;
640// m_linkedAvatars.Add(av);
641 }
642 }
643 avsToCross.Clear();
644
645 }
646 else
647 { 541 {
648 if (m_rootPart.KeyframeMotion != null) 542 inTransit = true;
649 m_rootPart.KeyframeMotion.CrossingFailure(); 543 SOGCrossDelegate d = CrossAsync;
650 544 d.BeginInvoke(this, val, CrossAsyncCompleted, d);
651 if (RootPart.PhysActor != null)
652 {
653 RootPart.PhysActor.CrossingFailure();
654 }
655 } 545 }
656 Vector3 oldp = AbsolutePosition; 546 return;
657 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
658 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
659 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
660 }
661 } 547 }
662 548
663/* don't see the need but worse don't see where is restored to false if things stay in
664 foreach (SceneObjectPart part in m_parts.GetArray())
665 {
666 part.IgnoreUndoUpdate = true;
667 }
668 */
669 if (RootPart.GetStatusSandbox()) 549 if (RootPart.GetStatusSandbox())
670 { 550 {
671 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 551 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
672 { 552 {
673 RootPart.ScriptSetPhysicsStatus(false); 553 RootPart.ScriptSetPhysicsStatus(false);
674 554
675 if (Scene != null) 555 if (Scene != null)
676 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 556 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
677 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 557 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
678 558
679 return; 559 return;
680 } 560 }
681 } 561 }
682 562
683 // Restuff the new GroupPosition into each SOP of the linkset.
684 // This has the affect of resetting and tainting the physics actors.
685 SceneObjectPart[] parts = m_parts.GetArray();
686 bool triggerScriptEvent = m_rootPart.GroupPosition != val; 563 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
687 if (m_dupeInProgress) 564 if (m_dupeInProgress || IsDeleted)
688 triggerScriptEvent = false; 565 triggerScriptEvent = false;
566
567 m_rootPart.GroupPosition = val;
568
569 // Restuff the new GroupPosition into each child SOP of the linkset.
570 // this is needed because physics may not have linksets but just loose SOPs in world
571
572 SceneObjectPart[] parts = m_parts.GetArray();
573
689 foreach (SceneObjectPart part in parts) 574 foreach (SceneObjectPart part in parts)
690 { 575 {
691 part.GroupPosition = val; 576 if (part != m_rootPart)
692 if (triggerScriptEvent) 577 part.GroupPosition = val;
578 }
579
580 foreach (ScenePresence av in m_linkedAvatars)
581 {
582 av.sitSOGmoved();
583 }
584
585 // now that position is changed tell it to scripts
586 if (triggerScriptEvent)
587 {
588 foreach (SceneObjectPart part in parts)
589 {
693 part.TriggerScriptChangedEvent(Changed.POSITION); 590 part.TriggerScriptChangedEvent(Changed.POSITION);
591 }
694 } 592 }
695 593
696/* 594 Scene.EventManager.TriggerParcelPrimCountTainted();
697 This seems not needed and should not be needed: 595 }
698 sp absolute position depends on sit part absolute position fixed above. 596 }
699 sp ParentPosition is not used anywhere. 597
700 Since presence is sitting, viewer considers it 'linked' to root prim, so it will move/rotate it 598 public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
701 Sending a extra packet with avatar position is not only bandwidth waste, but may cause jitter in viewers due to UPD nature. 599 {
702 600 Scene sogScene = sog.m_scene;
703 if (!m_dupeInProgress) 601 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
602
603 Vector3 newpos = Vector3.Zero;
604 OpenSim.Services.Interfaces.GridRegion destination = null;
605
606 if (sog.RootPart.DIE_AT_EDGE)
607 {
608 try
609 {
610 sogScene.DeleteSceneObject(sog, false);
611 }
612 catch (Exception)
613 {
614 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
615 }
616 return sog;
617 }
618
619 if (sog.RootPart.RETURN_AT_EDGE)
620 {
621 // We remove the object here
622 try
623 {
624 List<uint> localIDs = new List<uint>();
625 localIDs.Add(sog.RootPart.LocalId);
626 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
627 "Returned at region cross");
628 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
629 }
630 catch (Exception)
631 {
632 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
633 }
634 return sog;
635 }
636
637 if (sog.m_rootPart.KeyframeMotion != null)
638 sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
639
640 if (entityTransfer == null)
641 return sog;
642
643 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
644 if (destination == null)
645 return sog;
646
647 if (sog.m_linkedAvatars.Count == 0)
648 {
649 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true);
650 return sog;
651 }
652
653 string reason = String.Empty;
654 string version = String.Empty;
655
656 foreach (ScenePresence av in sog.m_linkedAvatars)
657 {
658 // We need to cross these agents. First, let's find
659 // out if any of them can't cross for some reason.
660 // We have to deny the crossing entirely if any
661 // of them are banned. Alternatively, we could
662 // unsit banned agents....
663
664 // We set the avatar position as being the object
665 // position to get the region to send to
666 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason))
667 {
668 return sog;
669 }
670 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
671 }
672
673 // We unparent the SP quietly so that it won't
674 // be made to stand up
675
676 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
677
678 foreach (ScenePresence av in sog.m_linkedAvatars)
679 {
680 avtocrossInfo avinfo = new avtocrossInfo();
681 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
682 if (parentPart != null)
683 av.ParentUUID = parentPart.UUID;
684
685 avinfo.av = av;
686 avinfo.ParentID = av.ParentID;
687 avsToCross.Add(avinfo);
688
689 av.PrevSitOffset = av.OffsetPosition;
690 av.ParentID = 0;
691 }
692
693 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true))
694 {
695 foreach (avtocrossInfo avinfo in avsToCross)
704 { 696 {
705 foreach (ScenePresence av in m_linkedAvatars) 697 ScenePresence av = avinfo.av;
698 if (!av.IsInTransit) // just in case...
706 { 699 {
707 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID); 700 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
708 if (p != null && m_parts.TryGetValue(p.UUID, out p)) 701
702 av.IsInTransit = true;
703
704// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
705// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
706 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version);
707 if(av.IsChildAgent)
709 { 708 {
710 Vector3 offset = p.GetWorldPosition() - av.ParentPosition; 709 if (av.ParentUUID != UUID.Zero)
711 av.AbsolutePosition += offset; 710 {
712// av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition 711 av.ClearControls();
713 av.SendAvatarDataToAllAgents(); 712 av.ParentPart = null;
713 }
714 } 714 }
715 av.ParentUUID = UUID.Zero;
716 // In any case
717 av.IsInTransit = false;
718
719 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
715 } 720 }
721 else
722 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
716 } 723 }
717*/ 724 avsToCross.Clear();
718 //if (m_rootPart.PhysActor != null) 725 return sog;
719 //{
720 //m_rootPart.PhysActor.Position =
721 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
722 //m_rootPart.GroupPosition.Z);
723 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
724 //}
725
726 if (Scene != null)
727 Scene.EventManager.TriggerParcelPrimCountTainted();
728 } 726 }
727 else // cross failed, put avas back ??
728 {
729 foreach (avtocrossInfo avinfo in avsToCross)
730 {
731 ScenePresence av = avinfo.av;
732 av.ParentUUID = UUID.Zero;
733 av.ParentID = avinfo.ParentID;
734 }
735 }
736 avsToCross.Clear();
737
738 return sog;
729 } 739 }
730 740
731 public override Vector3 Velocity 741 public void CrossAsyncCompleted(IAsyncResult iar)
732 { 742 {
733 get { return RootPart.Velocity; } 743 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
734 set { RootPart.Velocity = value; } 744 SceneObjectGroup sog = icon.EndInvoke(iar);
745
746 if (!sog.IsDeleted)
747 {
748 SceneObjectPart rootp = sog.m_rootPart;
749 Vector3 oldp = rootp.GroupPosition;
750 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
751 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
752 rootp.GroupPosition = oldp;
753
754 SceneObjectPart[] parts = sog.m_parts.GetArray();
755
756 foreach (SceneObjectPart part in parts)
757 {
758 if (part != rootp)
759 part.GroupPosition = oldp;
760 }
761
762 foreach (ScenePresence av in sog.m_linkedAvatars)
763 {
764 av.sitSOGmoved();
765 }
766
767 sog.Velocity = Vector3.Zero;
768
769 if (sog.m_rootPart.KeyframeMotion != null)
770 sog.m_rootPart.KeyframeMotion.CrossingFailure();
771
772 if (sog.RootPart.PhysActor != null)
773 {
774 sog.RootPart.PhysActor.CrossingFailure();
775 }
776
777 sog.inTransit = false;
778 sog.ScheduleGroupForFullUpdate();
779 }
735 } 780 }
736 781
737 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 782 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
@@ -744,6 +789,7 @@ namespace OpenSim.Region.Framework.Scenes
744 { 789 {
745 if (agent.ParentUUID != UUID.Zero) 790 if (agent.ParentUUID != UUID.Zero)
746 { 791 {
792 agent.ClearControls();
747 agent.ParentPart = null; 793 agent.ParentPart = null;
748// agent.ParentPosition = Vector3.Zero; 794// agent.ParentPosition = Vector3.Zero;
749// agent.ParentUUID = UUID.Zero; 795// agent.ParentUUID = UUID.Zero;
@@ -751,7 +797,6 @@ namespace OpenSim.Region.Framework.Scenes
751 } 797 }
752 798
753 agent.ParentUUID = UUID.Zero; 799 agent.ParentUUID = UUID.Zero;
754
755// agent.Reset(); 800// agent.Reset();
756// else // Not successful 801// else // Not successful
757// agent.RestoreInCurrentScene(); 802// agent.RestoreInCurrentScene();
@@ -762,6 +807,12 @@ namespace OpenSim.Region.Framework.Scenes
762 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 807 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
763 } 808 }
764 809
810 public override Vector3 Velocity
811 {
812 get { return RootPart.Velocity; }
813 set { RootPart.Velocity = value; }
814 }
815
765 public override uint LocalId 816 public override uint LocalId
766 { 817 {
767 get { return m_rootPart.LocalId; } 818 get { return m_rootPart.LocalId; }
@@ -885,20 +936,20 @@ namespace OpenSim.Region.Framework.Scenes
885 return; 936 return;
886 } 937 }
887 IsSelected = partSelect; 938 IsSelected = partSelect;
888 if (!IsAttachment) 939// if (!IsAttachment)
889 { 940// {
890 ScheduleGroupForFullUpdate(); 941// ScheduleGroupForFullUpdate();
891 } 942// }
892 } 943 }
893 } 944 }
894 945 // PlaySoundMasterPrim no longer in use to remove
895 private SceneObjectPart m_PlaySoundMasterPrim = null; 946 private SceneObjectPart m_PlaySoundMasterPrim = null;
896 public SceneObjectPart PlaySoundMasterPrim 947 public SceneObjectPart PlaySoundMasterPrim
897 { 948 {
898 get { return m_PlaySoundMasterPrim; } 949 get { return m_PlaySoundMasterPrim; }
899 set { m_PlaySoundMasterPrim = value; } 950 set { m_PlaySoundMasterPrim = value; }
900 } 951 }
901 952 // PlaySoundSlavePrims no longer in use to remove
902 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 953 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
903 public List<SceneObjectPart> PlaySoundSlavePrims 954 public List<SceneObjectPart> PlaySoundSlavePrims
904 { 955 {
@@ -906,6 +957,7 @@ namespace OpenSim.Region.Framework.Scenes
906 set { m_PlaySoundSlavePrims = value; } 957 set { m_PlaySoundSlavePrims = value; }
907 } 958 }
908 959
960 // LoopSoundMasterPrim no longer in use to remove
909 private SceneObjectPart m_LoopSoundMasterPrim = null; 961 private SceneObjectPart m_LoopSoundMasterPrim = null;
910 public SceneObjectPart LoopSoundMasterPrim 962 public SceneObjectPart LoopSoundMasterPrim
911 { 963 {
@@ -913,6 +965,7 @@ namespace OpenSim.Region.Framework.Scenes
913 set { m_LoopSoundMasterPrim = value; } 965 set { m_LoopSoundMasterPrim = value; }
914 } 966 }
915 967
968 // m_LoopSoundSlavePrims no longer in use to remove
916 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 969 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
917 public List<SceneObjectPart> LoopSoundSlavePrims 970 public List<SceneObjectPart> LoopSoundSlavePrims
918 { 971 {
@@ -1667,7 +1720,8 @@ namespace OpenSim.Region.Framework.Scenes
1667 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1720 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1668 if (avatar == null) 1721 if (avatar == null)
1669 return; 1722 return;
1670 1723 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1724 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1671 avatar.RemoveAttachment(this); 1725 avatar.RemoveAttachment(this);
1672 1726
1673 Vector3 detachedpos = new Vector3(127f,127f,127f); 1727 Vector3 detachedpos = new Vector3(127f,127f,127f);
@@ -1687,7 +1741,9 @@ namespace OpenSim.Region.Framework.Scenes
1687 m_rootPart.SetParentLocalId(0); 1741 m_rootPart.SetParentLocalId(0);
1688 AttachmentPoint = (byte)0; 1742 AttachmentPoint = (byte)0;
1689 // must check if buildind should be true or false here 1743 // must check if buildind should be true or false here
1690 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false); 1744// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1745 ApplyPhysics();
1746
1691 HasGroupChanged = true; 1747 HasGroupChanged = true;
1692 RootPart.Rezzed = DateTime.Now; 1748 RootPart.Rezzed = DateTime.Now;
1693 RootPart.RemFlag(PrimFlags.TemporaryOnRez); 1749 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
@@ -1820,11 +1876,21 @@ namespace OpenSim.Region.Framework.Scenes
1820 // Setting this SOG's absolute position also loops through and sets the positions 1876 // Setting this SOG's absolute position also loops through and sets the positions
1821 // of the SOP's in this SOG's linkset. This has the side affect of making sure 1877 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1822 // the physics world matches the simulated world. 1878 // the physics world matches the simulated world.
1823 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1879 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1824 1880
1825 // teravus: AbsolutePosition is NOT a normal property! 1881 // teravus: AbsolutePosition is NOT a normal property!
1826 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1882 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1827 // jhurliman: Then why is it a property instead of two methods? 1883 // jhurliman: Then why is it a property instead of two methods?
1884
1885 // do only what is supposed to do
1886 Vector3 groupPosition = m_rootPart.GroupPosition;
1887 SceneObjectPart[] parts = m_parts.GetArray();
1888
1889 foreach (SceneObjectPart part in parts)
1890 {
1891 if (part != m_rootPart)
1892 part.GroupPosition = groupPosition;
1893 }
1828 } 1894 }
1829 1895
1830 public UUID GetPartsFullID(uint localID) 1896 public UUID GetPartsFullID(uint localID)
@@ -1868,11 +1934,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1934 /// <summary>
1869 /// Delete this group from its scene. 1935 /// Delete this group from its scene.
1870 /// </summary> 1936 /// </summary>
1871 /// 1937 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1938 /// 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 1939 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1940 /// must be handled by the caller.
1875 /// 1941 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1942 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1943 public void DeleteGroupFromScene(bool silent)
1878 { 1944 {
@@ -1901,7 +1967,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 if (!IsAttachment 1967 if (!IsAttachment
1902 || AttachedAvatar == avatar.ControllingClient.AgentId 1968 || AttachedAvatar == avatar.ControllingClient.AgentId
1903 || !HasPrivateAttachmentPoint) 1969 || !HasPrivateAttachmentPoint)
1904 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1970 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1905 } 1971 }
1906 } 1972 }
1907 }); 1973 });
@@ -2037,7 +2103,7 @@ namespace OpenSim.Region.Framework.Scenes
2037 return; 2103 return;
2038 } 2104 }
2039 2105
2040 if (IsDeleted || UUID == UUID.Zero) 2106 if (IsDeleted || inTransit || UUID == UUID.Zero)
2041 { 2107 {
2042// m_log.DebugFormat( 2108// m_log.DebugFormat(
2043// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2109// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
@@ -2109,6 +2175,7 @@ namespace OpenSim.Region.Framework.Scenes
2109 2175
2110 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) 2176 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2111 { 2177 {
2178 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2112 RootPart.Shape.State = 0; 2179 RootPart.Shape.State = 0;
2113 ScheduleGroupForFullUpdate(); 2180 ScheduleGroupForFullUpdate();
2114 } 2181 }
@@ -2122,23 +2189,22 @@ namespace OpenSim.Region.Framework.Scenes
2122 HasGroupChangedDueToDelink = false; 2189 HasGroupChangedDueToDelink = false;
2123 2190
2124 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2191 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2125/* 2192
2126 backup_group.ForEachPart(delegate(SceneObjectPart part)
2127 {
2128 if (part.KeyframeMotion != null)
2129 {
2130 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
2131// part.KeyframeMotion.UpdateSceneObject(this);
2132 }
2133 });
2134*/
2135 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2193 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
2136 2194
2137 backup_group.ForEachPart(delegate(SceneObjectPart part) 2195 backup_group.ForEachPart(delegate(SceneObjectPart part)
2138 { 2196 {
2139 part.Inventory.ProcessInventoryBackup(datastore); 2197 part.Inventory.ProcessInventoryBackup(datastore);
2198
2199 // take the change to delete things
2200 if(part.KeyframeMotion != null)
2201 {
2202 part.KeyframeMotion.Delete();
2203 part.KeyframeMotion = null;
2204 }
2140 }); 2205 });
2141 2206
2207
2142 backup_group = null; 2208 backup_group = null;
2143 } 2209 }
2144// else 2210// else
@@ -2193,29 +2259,11 @@ namespace OpenSim.Region.Framework.Scenes
2193 dupe.m_isBackedUp = false; 2259 dupe.m_isBackedUp = false;
2194 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2260 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
2195 2261
2262 dupe.inTransit = inTransit; // this shouldn't be needed TEST
2263
2196 // new group as no sitting avatars 2264 // new group as no sitting avatars
2197 dupe.m_linkedAvatars = new List<ScenePresence>(); 2265 dupe.m_linkedAvatars = new List<ScenePresence>();
2198 2266 dupe.m_sittingAvatars = new List<UUID>();
2199 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
2200 // attachments do not bordercross while they're being duplicated. This is hacktastic!
2201 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
2202 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
2203 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
2204 // then restore it's attachment state
2205
2206 // This is only necessary when userExposed is false!
2207
2208 bool previousAttachmentStatus = dupe.IsAttachment;
2209
2210 if (!userExposed)
2211 dupe.IsAttachment = true;
2212
2213 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
2214
2215 if (!userExposed)
2216 {
2217 dupe.IsAttachment = previousAttachmentStatus;
2218 }
2219 2267
2220 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2268 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
2221 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2269 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
@@ -2239,7 +2287,7 @@ namespace OpenSim.Region.Framework.Scenes
2239 { 2287 {
2240 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2288 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
2241 newPart.LinkNum = part.LinkNum; 2289 newPart.LinkNum = part.LinkNum;
2242 if (userExposed) 2290// if (userExposed)
2243 newPart.ParentID = dupe.m_rootPart.LocalId; 2291 newPart.ParentID = dupe.m_rootPart.LocalId;
2244 } 2292 }
2245 else 2293 else
@@ -2300,10 +2348,9 @@ namespace OpenSim.Region.Framework.Scenes
2300 /// <param name="cGroupID"></param> 2348 /// <param name="cGroupID"></param>
2301 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2349 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2302 { 2350 {
2303 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2351 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2304 // give newpart a new local ID lettng old part keep same 2352// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2305 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed); 2353// newpart.LocalId = m_scene.AllocateLocalId();
2306 newpart.LocalId = m_scene.AllocateLocalId();
2307 2354
2308 SetRootPart(newpart); 2355 SetRootPart(newpart);
2309 if (userExposed) 2356 if (userExposed)
@@ -2522,11 +2569,9 @@ namespace OpenSim.Region.Framework.Scenes
2522 /// <param name="cGroupID"></param> 2569 /// <param name="cGroupID"></param>
2523 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2570 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2524 { 2571 {
2525 // give new ID to the new part, letting old keep original 2572 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2526 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2573// SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2527 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed); 2574// newPart.LocalId = m_scene.AllocateLocalId();
2528 newPart.LocalId = m_scene.AllocateLocalId();
2529 newPart.SetParent(this);
2530 2575
2531 AddPart(newPart); 2576 AddPart(newPart);
2532 2577
@@ -2585,7 +2630,7 @@ namespace OpenSim.Region.Framework.Scenes
2585 // an object has been deleted from a scene before update was processed. 2630 // an object has been deleted from a scene before update was processed.
2586 // A more fundamental overhaul of the update mechanism is required to eliminate all 2631 // A more fundamental overhaul of the update mechanism is required to eliminate all
2587 // the race conditions. 2632 // the race conditions.
2588 if (IsDeleted) 2633 if (IsDeleted || inTransit)
2589 return; 2634 return;
2590 2635
2591 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2636 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2600,6 +2645,16 @@ namespace OpenSim.Region.Framework.Scenes
2600 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 2645 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2601 } 2646 }
2602 2647
2648 if (IsAttachment)
2649 {
2650 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2651 if (sp != null)
2652 {
2653 sp.SendAttachmentScheduleUpdate(this);
2654 return;
2655 }
2656 }
2657
2603 SceneObjectPart[] parts = m_parts.GetArray(); 2658 SceneObjectPart[] parts = m_parts.GetArray();
2604 for (int i = 0; i < parts.Length; i++) 2659 for (int i = 0; i < parts.Length; i++)
2605 { 2660 {
@@ -2661,15 +2716,25 @@ namespace OpenSim.Region.Framework.Scenes
2661 return; 2716 return;
2662 2717
2663// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2718// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2664 2719
2665 RootPart.SendFullUpdateToAllClients(); 2720 if (IsAttachment)
2721 {
2722 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2723 if (sp != null)
2724 {
2725 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
2726 return;
2727 }
2728 }
2729
2730 RootPart.SendFullUpdateToAllClientsInternal();
2666 2731
2667 SceneObjectPart[] parts = m_parts.GetArray(); 2732 SceneObjectPart[] parts = m_parts.GetArray();
2668 for (int i = 0; i < parts.Length; i++) 2733 for (int i = 0; i < parts.Length; i++)
2669 { 2734 {
2670 SceneObjectPart part = parts[i]; 2735 SceneObjectPart part = parts[i];
2671 if (part != RootPart) 2736 if (part != RootPart)
2672 part.SendFullUpdateToAllClients(); 2737 part.SendFullUpdateToAllClientsInternal();
2673 } 2738 }
2674 } 2739 }
2675 2740
@@ -2681,7 +2746,7 @@ namespace OpenSim.Region.Framework.Scenes
2681 /// </summary> 2746 /// </summary>
2682 public void SendGroupRootTerseUpdate() 2747 public void SendGroupRootTerseUpdate()
2683 { 2748 {
2684 if (IsDeleted) 2749 if (IsDeleted || inTransit)
2685 return; 2750 return;
2686 2751
2687 RootPart.SendTerseUpdateToAllClients(); 2752 RootPart.SendTerseUpdateToAllClients();
@@ -2700,12 +2765,22 @@ namespace OpenSim.Region.Framework.Scenes
2700 /// </summary> 2765 /// </summary>
2701 public void SendGroupTerseUpdate() 2766 public void SendGroupTerseUpdate()
2702 { 2767 {
2703 if (IsDeleted) 2768 if (IsDeleted || inTransit)
2704 return; 2769 return;
2705 2770
2771 if (IsAttachment)
2772 {
2773 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2774 if (sp != null)
2775 {
2776 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
2777 return;
2778 }
2779 }
2780
2706 SceneObjectPart[] parts = m_parts.GetArray(); 2781 SceneObjectPart[] parts = m_parts.GetArray();
2707 for (int i = 0; i < parts.Length; i++) 2782 for (int i = 0; i < parts.Length; i++)
2708 parts[i].SendTerseUpdateToAllClients(); 2783 parts[i].SendTerseUpdateToAllClientsInternal();
2709 } 2784 }
2710 2785
2711 /// <summary> 2786 /// <summary>
@@ -2813,6 +2888,33 @@ namespace OpenSim.Region.Framework.Scenes
2813 return; 2888 return;
2814 } 2889 }
2815 2890
2891 // physical prims count limit
2892 // not very eficient :(
2893
2894 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
2895 m_scene.m_linksetPhysCapacity)
2896 {
2897 int cntr = 0;
2898 foreach (SceneObjectPart part in Parts)
2899 {
2900 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2901 cntr++;
2902 }
2903 foreach (SceneObjectPart part in objectGroup.Parts)
2904 {
2905 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2906 cntr++;
2907 }
2908
2909 if (cntr > m_scene.m_linksetPhysCapacity)
2910 {
2911 // cancel physics
2912 RootPart.Flags &= ~PrimFlags.Physics;
2913 ApplyPhysics();
2914 }
2915 }
2916
2917
2816 // 'linkPart' == the root of the group being linked into this group 2918 // 'linkPart' == the root of the group being linked into this group
2817 SceneObjectPart linkPart = objectGroup.m_rootPart; 2919 SceneObjectPart linkPart = objectGroup.m_rootPart;
2818 2920
@@ -2837,22 +2939,24 @@ namespace OpenSim.Region.Framework.Scenes
2837 // First move the new group's root SOP's position to be relative to ours 2939 // First move the new group's root SOP's position to be relative to ours
2838 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, 2940 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2839 // this code can be reordered to have a more logical flow.) 2941 // this code can be reordered to have a more logical flow.)
2840 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 2942 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2841 // Assign the new parent to the root of the old group 2943 // Assign the new parent to the root of the old group
2842 linkPart.ParentID = m_rootPart.LocalId; 2944 linkPart.ParentID = m_rootPart.LocalId;
2843 // Now that it's a child, it's group position is our root position 2945 // Now that it's a child, it's group position is our root position
2844 linkPart.GroupPosition = AbsolutePosition; 2946 linkPart.setGroupPosition(AbsolutePosition);
2845 2947
2846 Vector3 axPos = linkPart.OffsetPosition;
2847 // Rotate the linking root SOP's position to be relative to the new root prim 2948 // Rotate the linking root SOP's position to be relative to the new root prim
2848 Quaternion parentRot = m_rootPart.RotationOffset; 2949 Quaternion parentRot = m_rootPart.RotationOffset;
2849 axPos *= Quaternion.Conjugate(parentRot);
2850 linkPart.OffsetPosition = axPos;
2851 2950
2852 // Make the linking root SOP's rotation relative to the new root prim 2951 // Make the linking root SOP's rotation relative to the new root prim
2853 Quaternion oldRot = linkPart.RotationOffset; 2952 Quaternion oldRot = linkPart.RotationOffset;
2854 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot; 2953 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2855 linkPart.RotationOffset = newRot; 2954 linkPart.setRotationOffset(newRot);
2955
2956 Vector3 axPos = linkPart.OffsetPosition;
2957 axPos *= Quaternion.Conjugate(parentRot);
2958 linkPart.OffsetPosition = axPos;
2959
2856 2960
2857 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 2961 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2858 // Now that we know this SOG has at least two SOPs in it, the new root 2962 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2882,6 +2986,8 @@ namespace OpenSim.Region.Framework.Scenes
2882 m_parts.Add(linkPart.UUID, linkPart); 2986 m_parts.Add(linkPart.UUID, linkPart);
2883 2987
2884 linkPart.SetParent(this); 2988 linkPart.SetParent(this);
2989 m_scene.updateScenePartGroup(linkPart, this);
2990
2885 linkPart.CreateSelected = true; 2991 linkPart.CreateSelected = true;
2886 2992
2887 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 2993 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
@@ -3074,18 +3180,15 @@ namespace OpenSim.Region.Framework.Scenes
3074 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3180 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
3075 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3181 linkPart.OffsetPosition = new Vector3(0, 0, 0);
3076 */ 3182 */
3077 linkPart.GroupPosition = worldPos; 3183 linkPart.setGroupPosition(worldPos);
3078 linkPart.OffsetPosition = Vector3.Zero; 3184 linkPart.setOffsetPosition(Vector3.Zero);
3079 linkPart.RotationOffset = worldRot; 3185 linkPart.setRotationOffset(worldRot);
3080 3186
3081 // Create a new SOG to go around this unlinked and unattached SOP 3187 // Create a new SOG to go around this unlinked and unattached SOP
3082 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3188 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
3083 3189
3084 m_scene.AddNewSceneObject(objectGroup, true); 3190 m_scene.AddNewSceneObject(objectGroup, true);
3085 3191
3086 if (sendEvents)
3087 linkPart.TriggerScriptChangedEvent(Changed.LINK);
3088
3089 linkPart.Rezzed = RootPart.Rezzed; 3192 linkPart.Rezzed = RootPart.Rezzed;
3090 3193
3091 // When we delete a group, we currently have to force persist to the database if the object id has changed 3194 // When we delete a group, we currently have to force persist to the database if the object id has changed
@@ -3100,6 +3203,9 @@ namespace OpenSim.Region.Framework.Scenes
3100 3203
3101 objectGroup.HasGroupChangedDueToDelink = true; 3204 objectGroup.HasGroupChangedDueToDelink = true;
3102 3205
3206 if (sendEvents)
3207 linkPart.TriggerScriptChangedEvent(Changed.LINK);
3208
3103 return objectGroup; 3209 return objectGroup;
3104 } 3210 }
3105 3211
@@ -3127,15 +3233,14 @@ namespace OpenSim.Region.Framework.Scenes
3127 Quaternion parentRot = oldGroupRotation; 3233 Quaternion parentRot = oldGroupRotation;
3128 Quaternion oldRot = part.RotationOffset; 3234 Quaternion oldRot = part.RotationOffset;
3129 3235
3130 // Move our position to not be relative to the old parent 3236 // Move our position in world
3131 Vector3 axPos = part.OffsetPosition; 3237 Vector3 axPos = part.OffsetPosition;
3132 axPos *= parentRot; 3238 axPos *= parentRot;
3133 part.OffsetPosition = axPos; 3239 Vector3 newPos = oldGroupPosition + axPos;
3134 Vector3 newPos = oldGroupPosition + part.OffsetPosition; 3240 part.setGroupPosition(newPos);
3135 part.GroupPosition = newPos; 3241 part.setOffsetPosition(Vector3.Zero);
3136 part.OffsetPosition = Vector3.Zero;
3137 3242
3138 // Compution our rotation to be not relative to the old parent 3243 // Compution our rotation in world
3139 Quaternion worldRot = parentRot * oldRot; 3244 Quaternion worldRot = parentRot * oldRot;
3140 part.RotationOffset = worldRot; 3245 part.RotationOffset = worldRot;
3141 3246
@@ -3146,25 +3251,27 @@ namespace OpenSim.Region.Framework.Scenes
3146 3251
3147 part.LinkNum = linkNum; 3252 part.LinkNum = linkNum;
3148 3253
3254 m_scene.updateScenePartGroup(part, this);
3255
3149 // Compute the new position of this SOP relative to the group position 3256 // Compute the new position of this SOP relative to the group position
3150 part.OffsetPosition = newPos - AbsolutePosition; 3257 part.setOffsetPosition(newPos - AbsolutePosition);
3151 3258
3152 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3259 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
3153 // It would have the affect of setting the physics engine position multiple 3260 // It would have the affect of setting the physics engine position multiple
3154 // times. In theory, that is not necessary but I don't have a good linkset 3261 // times. In theory, that is not necessary but I don't have a good linkset
3155 // test to know that cleaning up this code wouldn't break things.) 3262 // test to know that cleaning up this code wouldn't break things.)
3156 3263
3157 // Rotate the relative position by the rotation of the group
3158 Quaternion rootRotation = m_rootPart.RotationOffset;
3159 Vector3 pos = part.OffsetPosition;
3160 pos *= Quaternion.Conjugate(rootRotation);
3161 part.OffsetPosition = pos;
3162
3163 // Compute the SOP's rotation relative to the rotation of the group. 3264 // Compute the SOP's rotation relative to the rotation of the group.
3164 parentRot = m_rootPart.RotationOffset; 3265 parentRot = m_rootPart.RotationOffset;
3266
3165 oldRot = part.RotationOffset; 3267 oldRot = part.RotationOffset;
3166 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot; 3268 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
3167 part.RotationOffset = newRot; 3269 part.setRotationOffset(newRot);
3270
3271 Vector3 pos = part.OffsetPosition;
3272 pos *= Quaternion.Conjugate(parentRot);
3273
3274 part.OffsetPosition = pos; // update position and orientation on physics also
3168 3275
3169 // Since this SOP's state has changed, push those changes into the physics engine 3276 // Since this SOP's state has changed, push those changes into the physics engine
3170 // and the simulator. 3277 // and the simulator.
@@ -3411,8 +3518,12 @@ namespace OpenSim.Region.Framework.Scenes
3411 { 3518 {
3412 SceneObjectPart[] parts = m_parts.GetArray(); 3519 SceneObjectPart[] parts = m_parts.GetArray();
3413 3520
3414 if (Scene != null) 3521 if (Scene != null && UsePhysics)
3415 { 3522 {
3523 int maxprims = m_scene.m_linksetPhysCapacity;
3524 bool checkShape = (maxprims > 0 &&
3525 parts.Length > maxprims);
3526
3416 for (int i = 0; i < parts.Length; i++) 3527 for (int i = 0; i < parts.Length; i++)
3417 { 3528 {
3418 SceneObjectPart part = parts[i]; 3529 SceneObjectPart part = parts[i];
@@ -3423,6 +3534,15 @@ namespace OpenSim.Region.Framework.Scenes
3423 UsePhysics = false; // Reset physics 3534 UsePhysics = false; // Reset physics
3424 break; 3535 break;
3425 } 3536 }
3537
3538 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3539 {
3540 if (--maxprims < 0)
3541 {
3542 UsePhysics = false;
3543 break;
3544 }
3545 }
3426 } 3546 }
3427 } 3547 }
3428 3548
@@ -3813,20 +3933,20 @@ namespace OpenSim.Region.Framework.Scenes
3813 /// <summary> 3933 /// <summary>
3814 /// Update just the root prim position in a linkset 3934 /// Update just the root prim position in a linkset
3815 /// </summary> 3935 /// </summary>
3816 /// <param name="pos"></param> 3936 /// <param name="newPos"></param>
3817 public void UpdateRootPosition(Vector3 pos) 3937 public void UpdateRootPosition(Vector3 newPos)
3818 { 3938 {
3819 // needs to be called with phys building true 3939 // needs to be called with phys building true
3820 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3940 Vector3 oldPos;
3821 Vector3 oldPos = 3941
3822 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3942 if (IsAttachment)
3823 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3943 oldPos = m_rootPart.AttachedPos + m_rootPart.OffsetPosition; // OffsetPosition should always be 0 in an attachments's root prim
3824 AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); 3944 else
3945 oldPos = AbsolutePosition + m_rootPart.OffsetPosition;
3946
3825 Vector3 diff = oldPos - newPos; 3947 Vector3 diff = oldPos - newPos;
3826 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3827 Quaternion partRotation = m_rootPart.RotationOffset; 3948 Quaternion partRotation = m_rootPart.RotationOffset;
3828 axDiff *= Quaternion.Inverse(partRotation); 3949 diff *= Quaternion.Inverse(partRotation);
3829 diff = axDiff;
3830 3950
3831 SceneObjectPart[] parts = m_parts.GetArray(); 3951 SceneObjectPart[] parts = m_parts.GetArray();
3832 for (int i = 0; i < parts.Length; i++) 3952 for (int i = 0; i < parts.Length; i++)
@@ -3837,6 +3957,9 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 3957 }
3838 3958
3839 AbsolutePosition = newPos; 3959 AbsolutePosition = newPos;
3960
3961 if (IsAttachment)
3962 m_rootPart.AttachedPos = newPos;
3840 3963
3841 HasGroupChanged = true; 3964 HasGroupChanged = true;
3842 if (m_rootPart.Undoing) 3965 if (m_rootPart.Undoing)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 566605a..91293c4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
231 231
232 public double SoundRadius; 232 public double SoundRadius;
233 233
234 /// <summary>
235 /// Should sounds played from this prim be queued?
236 /// </summary>
237 /// <remarks>
238 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
239 /// </remarks>
240 public bool SoundQueueing { get; set; }
234 241
235 public uint TimeStampFull; 242 public uint TimeStampFull;
236 243
@@ -244,9 +251,6 @@ namespace OpenSim.Region.Framework.Scenes
244 public byte AttachPoint = 0; 251 public byte AttachPoint = 0;
245 252
246 [XmlIgnore] 253 [XmlIgnore]
247 public Vector3 AttachOffset = Vector3.Zero;
248
249 [XmlIgnore]
250 public Quaternion AttachRotation = Quaternion.Identity; 254 public Quaternion AttachRotation = Quaternion.Identity;
251 255
252 [XmlIgnore] 256 [XmlIgnore]
@@ -383,8 +387,6 @@ namespace OpenSim.Region.Framework.Scenes
383 387
384 private SOPVehicle m_vehicleParams = null; 388 private SOPVehicle m_vehicleParams = null;
385 389
386 private KeyframeMotion m_keyframeMotion = null;
387
388 public KeyframeMotion KeyframeMotion 390 public KeyframeMotion KeyframeMotion
389 { 391 {
390 get; set; 392 get; set;
@@ -506,7 +508,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 508 {
507 get 509 get
508 { 510 {
509 if (CreatorData != null && CreatorData != string.Empty) 511 if (!string.IsNullOrEmpty(CreatorData))
510 return CreatorID.ToString() + ';' + CreatorData; 512 return CreatorID.ToString() + ';' + CreatorData;
511 else 513 else
512 return CreatorID.ToString(); 514 return CreatorID.ToString();
@@ -536,7 +538,11 @@ namespace OpenSim.Region.Framework.Scenes
536 CreatorID = uuid; 538 CreatorID = uuid;
537 } 539 }
538 if (parts.Length >= 2) 540 if (parts.Length >= 2)
541 {
539 CreatorData = parts[1]; 542 CreatorData = parts[1];
543 if (!CreatorData.EndsWith("/"))
544 CreatorData += "/";
545 }
540 if (parts.Length >= 3) 546 if (parts.Length >= 3)
541 name = parts[2]; 547 name = parts[2];
542 548
@@ -660,6 +666,7 @@ namespace OpenSim.Region.Framework.Scenes
660 m_isSelected = value; 666 m_isSelected = value;
661 if (ParentGroup != null) 667 if (ParentGroup != null)
662 ParentGroup.PartSelectChanged(value); 668 ParentGroup.PartSelectChanged(value);
669
663 } 670 }
664 } 671 }
665 672
@@ -765,9 +772,20 @@ namespace OpenSim.Region.Framework.Scenes
765 set { m_damage = value; } 772 set { m_damage = value; }
766 } 773 }
767 774
775
776
777
778 public void setGroupPosition(Vector3 pos)
779 {
780 m_groupPosition = pos;
781 }
782
768 /// <summary> 783 /// <summary>
769 /// The position of the entire group that this prim belongs to. 784 /// The position of the entire group that this prim belongs to.
770 /// </summary> 785 /// </summary>
786 ///
787
788
771 public Vector3 GroupPosition 789 public Vector3 GroupPosition
772 { 790 {
773 get 791 get
@@ -805,7 +823,7 @@ namespace OpenSim.Region.Framework.Scenes
805 // Root prim actually goes at Position 823 // Root prim actually goes at Position
806 if (ParentID == 0) 824 if (ParentID == 0)
807 { 825 {
808 actor.Position = value; 826 actor.Position = value;
809 } 827 }
810 else 828 else
811 { 829 {
@@ -815,7 +833,8 @@ namespace OpenSim.Region.Framework.Scenes
815 } 833 }
816 834
817 // Tell the physics engines that this prim changed. 835 // Tell the physics engines that this prim changed.
818 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 836 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
837 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
819 } 838 }
820 catch (Exception e) 839 catch (Exception e)
821 { 840 {
@@ -825,6 +844,11 @@ namespace OpenSim.Region.Framework.Scenes
825 } 844 }
826 } 845 }
827 846
847 public void setOffsetPosition(Vector3 pos)
848 {
849 m_offsetPosition = pos;
850 }
851
828 public Vector3 OffsetPosition 852 public Vector3 OffsetPosition
829 { 853 {
830 get { return m_offsetPosition; } 854 get { return m_offsetPosition; }
@@ -855,7 +879,8 @@ namespace OpenSim.Region.Framework.Scenes
855 { 879 {
856 Vector3 offset = (m_offsetPosition - oldpos); 880 Vector3 offset = (m_offsetPosition - oldpos);
857 av.AbsolutePosition += offset; 881 av.AbsolutePosition += offset;
858 av.SendAvatarDataToAllAgents(); 882// av.SendAvatarDataToAllAgents();
883 av.SendTerseUpdateToAllClients();
859 } 884 }
860 } 885 }
861 } 886 }
@@ -882,6 +907,11 @@ namespace OpenSim.Region.Framework.Scenes
882 } 907 }
883 } 908 }
884 909
910 public void setRotationOffset(Quaternion q)
911 {
912 m_rotationOffset = q;
913 }
914
885 public Quaternion RotationOffset 915 public Quaternion RotationOffset
886 { 916 {
887 get 917 get
@@ -933,7 +963,7 @@ namespace OpenSim.Region.Framework.Scenes
933 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 963 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
934 } 964 }
935 965
936 if (ParentGroup != null) 966 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
937 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 967 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
938 //} 968 //}
939 } 969 }
@@ -1218,23 +1248,14 @@ namespace OpenSim.Region.Framework.Scenes
1218 // the mappings more consistant. 1248 // the mappings more consistant.
1219 public Vector3 SitTargetPositionLL 1249 public Vector3 SitTargetPositionLL
1220 { 1250 {
1221 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1251 get { return m_sitTargetPosition; }
1222 set { m_sitTargetPosition = value; } 1252 set { m_sitTargetPosition = value; }
1223 } 1253 }
1224 1254
1225 public Quaternion SitTargetOrientationLL 1255 public Quaternion SitTargetOrientationLL
1226 { 1256 {
1227 get 1257 get { return m_sitTargetOrientation; }
1228 { 1258 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 } 1259 }
1239 1260
1240 public bool Stopped 1261 public bool Stopped
@@ -2111,7 +2132,7 @@ namespace OpenSim.Region.Framework.Scenes
2111 /// <param name="linkNum"></param> 2132 /// <param name="linkNum"></param>
2112 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2133 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
2113 /// <returns></returns> 2134 /// <returns></returns>
2114 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2135 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
2115 { 2136 {
2116 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); 2137 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone();
2117 dupe.m_shape = m_shape.Copy(); 2138 dupe.m_shape = m_shape.Copy();
@@ -2157,7 +2178,7 @@ namespace OpenSim.Region.Framework.Scenes
2157 } 2178 }
2158 2179
2159 // Move afterwards ResetIDs as it clears the localID 2180 // Move afterwards ResetIDs as it clears the localID
2160 dupe.LocalId = localID; 2181 dupe.LocalId = plocalID;
2161 2182
2162 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2183 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
2163 dupe.LastOwnerID = OwnerID; 2184 dupe.LastOwnerID = OwnerID;
@@ -2187,7 +2208,7 @@ namespace OpenSim.Region.Framework.Scenes
2187 } 2208 }
2188 2209
2189 if (dupe.PhysActor != null) 2210 if (dupe.PhysActor != null)
2190 dupe.PhysActor.LocalID = localID; 2211 dupe.PhysActor.LocalID = plocalID;
2191 2212
2192 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2213 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
2193 2214
@@ -2687,6 +2708,7 @@ namespace OpenSim.Region.Framework.Scenes
2687 detobj.velVector = obj.Velocity; 2708 detobj.velVector = obj.Velocity;
2688 detobj.colliderType = 0; 2709 detobj.colliderType = 0;
2689 detobj.groupUUID = obj.GroupID; 2710 detobj.groupUUID = obj.GroupID;
2711 detobj.linkNumber = LinkNum; // pass my link number
2690 2712
2691 return detobj; 2713 return detobj;
2692 } 2714 }
@@ -2702,6 +2724,7 @@ namespace OpenSim.Region.Framework.Scenes
2702 detobj.velVector = av.Velocity; 2724 detobj.velVector = av.Velocity;
2703 detobj.colliderType = 0; 2725 detobj.colliderType = 0;
2704 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2726 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2727 detobj.linkNumber = LinkNum; // pass my link number
2705 2728
2706 return detobj; 2729 return detobj;
2707 } 2730 }
@@ -2717,6 +2740,7 @@ namespace OpenSim.Region.Framework.Scenes
2717 detobj.velVector = Vector3.Zero; 2740 detobj.velVector = Vector3.Zero;
2718 detobj.colliderType = 0; 2741 detobj.colliderType = 0;
2719 detobj.groupUUID = UUID.Zero; 2742 detobj.groupUUID = UUID.Zero;
2743 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2720 2744
2721 return detobj; 2745 return detobj;
2722 } 2746 }
@@ -2965,7 +2989,27 @@ namespace OpenSim.Region.Framework.Scenes
2965 } 2989 }
2966 //ParentGroup.RootPart.m_groupPosition = newpos; 2990 //ParentGroup.RootPart.m_groupPosition = newpos;
2967 } 2991 }
2968 2992/* ubit: there are no flexible links
2993 if (pa != null && ParentID != 0 && ParentGroup != null)
2994 {
2995 // Special case where a child object is requesting property updates.
2996 // This happens when linksets are modified to use flexible links rather than
2997 // the default links.
2998 // The simulator code presumes that child parts are only modified by scripts
2999 // so the logic for changing position/rotation/etc does not take into
3000 // account the physical object actually moving.
3001 // This code updates the offset position and rotation of the child and then
3002 // lets the update code push the update to the viewer.
3003 // Since physics engines do not normally generate this event for linkset children,
3004 // this code will not be active unless you have a specially configured
3005 // physics engine.
3006 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
3007 m_offsetPosition = pa.Position - m_groupPosition;
3008 RotationOffset = pa.Orientation * invRootRotation;
3009 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
3010 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
3011 }
3012*/
2969 ScheduleTerseUpdate(); 3013 ScheduleTerseUpdate();
2970 } 3014 }
2971 3015
@@ -3144,7 +3188,8 @@ namespace OpenSim.Region.Framework.Scenes
3144 return; 3188 return;
3145 3189
3146 // This was pulled from SceneViewer. Attachments always receive full updates. 3190 // This was pulled from SceneViewer. Attachments always receive full updates.
3147 // I could not verify if this is a requirement but this maintains existing behavior 3191 // This is needed because otherwise if only the root prim changes position, then
3192 // it looks as if the entire object has moved (including the other prims).
3148 if (ParentGroup.IsAttachment) 3193 if (ParentGroup.IsAttachment)
3149 { 3194 {
3150 ScheduleFullUpdate(); 3195 ScheduleFullUpdate();
@@ -3217,7 +3262,19 @@ namespace OpenSim.Region.Framework.Scenes
3217 3262
3218// m_log.DebugFormat( 3263// m_log.DebugFormat(
3219// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3264// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
3220 3265
3266
3267 if (ParentGroup.IsAttachment)
3268 {
3269 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3270 if (sp != null)
3271 {
3272 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3273 }
3274 }
3275
3276/* this does nothing
3277SendFullUpdateToClient(remoteClient, Position) ignores position parameter
3221 if (IsRoot) 3278 if (IsRoot)
3222 { 3279 {
3223 if (ParentGroup.IsAttachment) 3280 if (ParentGroup.IsAttachment)
@@ -3229,6 +3286,7 @@ namespace OpenSim.Region.Framework.Scenes
3229 SendFullUpdateToClient(remoteClient, AbsolutePosition); 3286 SendFullUpdateToClient(remoteClient, AbsolutePosition);
3230 } 3287 }
3231 } 3288 }
3289*/
3232 else 3290 else
3233 { 3291 {
3234 SendFullUpdateToClient(remoteClient); 3292 SendFullUpdateToClient(remoteClient);
@@ -3238,7 +3296,7 @@ namespace OpenSim.Region.Framework.Scenes
3238 /// <summary> 3296 /// <summary>
3239 /// Send a full update for this part to all clients. 3297 /// Send a full update for this part to all clients.
3240 /// </summary> 3298 /// </summary>
3241 public void SendFullUpdateToAllClients() 3299 public void SendFullUpdateToAllClientsInternal()
3242 { 3300 {
3243 if (ParentGroup == null) 3301 if (ParentGroup == null)
3244 return; 3302 return;
@@ -3257,6 +3315,36 @@ namespace OpenSim.Region.Framework.Scenes
3257 }); 3315 });
3258 } 3316 }
3259 3317
3318 public void SendFullUpdateToAllClients()
3319 {
3320 if (ParentGroup == null)
3321 return;
3322
3323 // Update the "last" values
3324 m_lastPosition = OffsetPosition;
3325 m_lastRotation = RotationOffset;
3326 m_lastVelocity = Velocity;
3327 m_lastAcceleration = Acceleration;
3328 m_lastAngularVelocity = AngularVelocity;
3329 m_lastUpdateSentTime = Environment.TickCount;
3330
3331 if (ParentGroup.IsAttachment)
3332 {
3333 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3334 if (sp != null)
3335 {
3336 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3337 }
3338 }
3339 else
3340 {
3341 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3342 {
3343 SendFullUpdate(avatar.ControllingClient);
3344 });
3345 }
3346 }
3347
3260 /// <summary> 3348 /// <summary>
3261 /// Sends a full update to the client 3349 /// Sends a full update to the client
3262 /// </summary> 3350 /// </summary>
@@ -3277,9 +3365,9 @@ namespace OpenSim.Region.Framework.Scenes
3277 return; 3365 return;
3278 3366
3279 // Suppress full updates during attachment editing 3367 // Suppress full updates during attachment editing
3280 // 3368 // sl Does send them
3281 if (ParentGroup.IsSelected && ParentGroup.IsAttachment) 3369 // if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
3282 return; 3370 // return;
3283 3371
3284 if (ParentGroup.IsDeleted) 3372 if (ParentGroup.IsDeleted)
3285 return; 3373 return;
@@ -3326,24 +3414,24 @@ namespace OpenSim.Region.Framework.Scenes
3326 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3414 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
3327 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE) 3415 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
3328 { 3416 {
3329 SendTerseUpdateToAllClients(); 3417 SendTerseUpdateToAllClientsInternal();
3330
3331 } 3418 }
3332 break; 3419 break;
3333 } 3420 }
3334 case UpdateRequired.FULL: 3421 case UpdateRequired.FULL:
3335 { 3422 {
3336 ClearUpdateSchedule(); 3423 ClearUpdateSchedule();
3337 SendFullUpdateToAllClients(); 3424 SendFullUpdateToAllClientsInternal();
3338 break; 3425 break;
3339 } 3426 }
3340 } 3427 }
3341 } 3428 }
3342 3429
3430
3343 /// <summary> 3431 /// <summary>
3344 /// Send a terse update to all clients 3432 /// Send a terse update to all clients
3345 /// </summary> 3433 /// </summary>
3346 public void SendTerseUpdateToAllClients() 3434 public void SendTerseUpdateToAllClientsInternal()
3347 { 3435 {
3348 if (ParentGroup == null || ParentGroup.Scene == null) 3436 if (ParentGroup == null || ParentGroup.Scene == null)
3349 return; 3437 return;
@@ -3362,6 +3450,36 @@ namespace OpenSim.Region.Framework.Scenes
3362 }); 3450 });
3363 } 3451 }
3364 3452
3453 public void SendTerseUpdateToAllClients()
3454 {
3455 if (ParentGroup == null || ParentGroup.Scene == null)
3456 return;
3457
3458 // Update the "last" values
3459 m_lastPosition = OffsetPosition;
3460 m_lastRotation = RotationOffset;
3461 m_lastVelocity = Velocity;
3462 m_lastAcceleration = Acceleration;
3463 m_lastAngularVelocity = AngularVelocity;
3464 m_lastUpdateSentTime = Environment.TickCount;
3465
3466 if (ParentGroup.IsAttachment)
3467 {
3468 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3469 if (sp != null)
3470 {
3471 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3472 }
3473 }
3474 else
3475 {
3476 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3477 {
3478 SendTerseUpdateToClient(client);
3479 });
3480 }
3481 }
3482
3365 public void SetAxisRotation(int axis, int rotate) 3483 public void SetAxisRotation(int axis, int rotate)
3366 { 3484 {
3367 ParentGroup.SetAxisRotation(axis, rotate); 3485 ParentGroup.SetAxisRotation(axis, rotate);
@@ -3714,8 +3832,8 @@ namespace OpenSim.Region.Framework.Scenes
3714// Name, groupID, OwnerID); 3832// Name, groupID, OwnerID);
3715 3833
3716 GroupID = groupID; 3834 GroupID = groupID;
3717 if (client != null) 3835// if (client != null)
3718 SendPropertiesToClient(client); 3836// SendPropertiesToClient(client);
3719 UpdateFlag = UpdateRequired.FULL; 3837 UpdateFlag = UpdateRequired.FULL;
3720 } 3838 }
3721 3839
@@ -4357,30 +4475,31 @@ namespace OpenSim.Region.Framework.Scenes
4357 } 4475 }
4358 } 4476 }
4359 4477
4360 public void UpdateGroupPosition(Vector3 pos) 4478 public void UpdateGroupPosition(Vector3 newPos)
4361 { 4479 {
4362 if ((pos.X != GroupPosition.X) || 4480 Vector3 oldPos = GroupPosition;
4363 (pos.Y != GroupPosition.Y) || 4481
4364 (pos.Z != GroupPosition.Z)) 4482 if ((newPos.X != oldPos.X) ||
4483 (newPos.Y != oldPos.Y) ||
4484 (newPos.Z != oldPos.Z))
4365 { 4485 {
4366 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4367 GroupPosition = newPos; 4486 GroupPosition = newPos;
4368 ScheduleTerseUpdate(); 4487 ScheduleTerseUpdate();
4369 } 4488 }
4370 } 4489 }
4371 4490
4372 /// <summary> 4491 /// <summary>
4373 /// 4492 /// Update this part's offset position.
4374 /// </summary> 4493 /// </summary>
4375 /// <param name="pos"></param> 4494 /// <param name="pos"></param>
4376 public void UpdateOffSet(Vector3 pos) 4495 public void UpdateOffSet(Vector3 newPos)
4377 { 4496 {
4378 if ((pos.X != OffsetPosition.X) || 4497 Vector3 oldPos = OffsetPosition;
4379 (pos.Y != OffsetPosition.Y) ||
4380 (pos.Z != OffsetPosition.Z))
4381 {
4382 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4383 4498
4499 if ((newPos.X != oldPos.X) ||
4500 (newPos.Y != oldPos.Y) ||
4501 (newPos.Z != oldPos.Z))
4502 {
4384 if (ParentGroup.RootPart.GetStatusSandbox()) 4503 if (ParentGroup.RootPart.GetStatusSandbox())
4385 { 4504 {
4386 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4505 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -4527,7 +4646,7 @@ namespace OpenSim.Region.Framework.Scenes
4527 // For now, we use the NINJA naming scheme for identifying joints. 4646 // For now, we use the NINJA naming scheme for identifying joints.
4528 // In the future, we can support other joint specification schemes such as a 4647 // In the future, we can support other joint specification schemes such as a
4529 // custom checkbox in the viewer GUI. 4648 // custom checkbox in the viewer GUI.
4530 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4649 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4531 { 4650 {
4532 return IsHingeJoint() || IsBallJoint(); 4651 return IsHingeJoint() || IsBallJoint();
4533 } 4652 }
@@ -4649,6 +4768,11 @@ namespace OpenSim.Region.Framework.Scenes
4649 } 4768 }
4650 } 4769 }
4651*/ 4770*/
4771 if (pa != null)
4772 {
4773 pa.SetMaterial(Material);
4774 DoPhysicsPropertyUpdate(UsePhysics, true);
4775 }
4652 } 4776 }
4653 else // it already has a physical representation 4777 else // it already has a physical representation
4654 { 4778 {
@@ -5021,6 +5145,14 @@ namespace OpenSim.Region.Framework.Scenes
5021 oldTex.DefaultTexture = fallbackOldFace; 5145 oldTex.DefaultTexture = fallbackOldFace;
5022 } 5146 }
5023 5147
5148 // Materials capable viewers can send a ObjectImage packet
5149 // when nothing in TE has changed. MaterialID should be updated
5150 // by the RenderMaterials CAP handler, so updating it here may cause a
5151 // race condtion. Therefore, if no non-materials TE fields have changed,
5152 // we should ignore any changes and not update Shape.TextureEntry
5153
5154 bool otherFieldsChanged = false;
5155
5024 for (int i = 0 ; i < GetNumberOfSides(); i++) 5156 for (int i = 0 ; i < GetNumberOfSides(); i++)
5025 { 5157 {
5026 5158
@@ -5047,18 +5179,36 @@ namespace OpenSim.Region.Framework.Scenes
5047 // Max change, skip the rest of testing 5179 // Max change, skip the rest of testing
5048 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5180 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
5049 break; 5181 break;
5182
5183 if (!otherFieldsChanged)
5184 {
5185 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
5186 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
5187 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
5188 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
5189 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
5190 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
5191 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
5192 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
5193 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
5194 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
5195 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5196 }
5050 } 5197 }
5051 5198
5052 m_shape.TextureEntry = newTex.GetBytes(); 5199 if (changeFlags != 0 || otherFieldsChanged)
5053 if (changeFlags != 0) 5200 {
5054 TriggerScriptChangedEvent(changeFlags); 5201 m_shape.TextureEntry = newTex.GetBytes();
5055 UpdateFlag = UpdateRequired.FULL; 5202 if (changeFlags != 0)
5056 ParentGroup.HasGroupChanged = true; 5203 TriggerScriptChangedEvent(changeFlags);
5204 UpdateFlag = UpdateRequired.FULL;
5205 ParentGroup.HasGroupChanged = true;
5057 5206
5058 //This is madness.. 5207 //This is madness..
5059 //ParentGroup.ScheduleGroupForFullUpdate(); 5208 //ParentGroup.ScheduleGroupForFullUpdate();
5060 //This is sparta 5209 //This is sparta
5061 ScheduleFullUpdate(); 5210 ScheduleFullUpdate();
5211 }
5062 } 5212 }
5063 5213
5064 5214
@@ -5246,6 +5396,64 @@ namespace OpenSim.Region.Framework.Scenes
5246 { 5396 {
5247 ParentGroup.AddScriptLPS(count); 5397 ParentGroup.AddScriptLPS(count);
5248 } 5398 }
5399
5400 /// <summary>
5401 /// Sets a prim's owner and permissions when it's rezzed.
5402 /// </summary>
5403 /// <param name="item">The inventory item from which the item was rezzed</param>
5404 /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
5405 /// <param name="scene">The scene the prim is being rezzed into</param>
5406 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
5407 {
5408 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
5409 {
5410 if (scene.Permissions.PropagatePermissions())
5411 {
5412 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
5413 {
5414 // Apply the item's permissions to the object
5415 //LogPermissions("Before applying item permissions");
5416 if (userInventory)
5417 {
5418 EveryoneMask = item.EveryOnePermissions;
5419 NextOwnerMask = item.NextPermissions;
5420 }
5421 else
5422 {
5423 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
5424 EveryoneMask = item.EveryOnePermissions;
5425 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
5426 NextOwnerMask = item.NextPermissions;
5427 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
5428 GroupMask = item.GroupPermissions;
5429 }
5430 //LogPermissions("After applying item permissions");
5431 }
5432 }
5433
5434 GroupMask = 0; // DO NOT propagate here
5435 }
5436
5437 if (OwnerID != item.Owner)
5438 {
5439 //LogPermissions("Before ApplyNextOwnerPermissions");
5440 ApplyNextOwnerPermissions();
5441 //LogPermissions("After ApplyNextOwnerPermissions");
5442
5443 LastOwnerID = OwnerID;
5444 OwnerID = item.Owner;
5445 Inventory.ChangeInventoryOwner(item.Owner);
5446 }
5447 }
5448
5449 /// <summary>
5450 /// Logs the prim's permissions. Useful when debugging permission problems.
5451 /// </summary>
5452 /// <param name="message"></param>
5453 private void LogPermissions(String message)
5454 {
5455 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
5456 }
5249 5457
5250 public void ApplyNextOwnerPermissions() 5458 public void ApplyNextOwnerPermissions()
5251 { 5459 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d04d87b..2fa9139 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -46,10 +46,10 @@ namespace OpenSim.Region.Framework.Scenes
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private string m_inventoryFileName = String.Empty;
50 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
51 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
52 private bool m_inventoryPrivileged = false; 51 private bool m_inventoryPrivileged = false;
52 private object m_inventoryFileLock = new object();
53 53
54 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>(); 54 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
55 55
@@ -505,35 +505,24 @@ namespace OpenSim.Region.Framework.Scenes
505 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 505 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
506 { 506 {
507 m_items.LockItemsForRead(true); 507 m_items.LockItemsForRead(true);
508
508 if (m_items.ContainsKey(itemId)) 509 if (m_items.ContainsKey(itemId))
509 { 510 {
510 if (m_items.ContainsKey(itemId)) 511 TaskInventoryItem it = m_items[itemId];
511 { 512 m_items.LockItemsForRead(false);
512 m_items.LockItemsForRead(false); 513
513 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 514 CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
514 }
515 else
516 {
517 m_items.LockItemsForRead(false);
518 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
519 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
520 StoreScriptError(itemId, msg);
521 m_log.ErrorFormat(
522 "[PRIM INVENTORY]: " +
523 "Couldn't start script with ID {0} since it {1}", itemId, msg);
524 }
525 } 515 }
526 else 516 else
527 { 517 {
528 m_items.LockItemsForRead(false); 518 m_items.LockItemsForRead(false);
529 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID); 519 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
520 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
530 StoreScriptError(itemId, msg); 521 StoreScriptError(itemId, msg);
531 m_log.ErrorFormat( 522 m_log.ErrorFormat(
532 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 523 "[PRIM INVENTORY]: " +
533 itemId, m_part.Name, m_part.UUID, 524 "Couldn't start script with ID {0} since it {1}", itemId, msg);
534 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
535 } 525 }
536
537 } 526 }
538 527
539 /// <summary> 528 /// <summary>
@@ -696,7 +685,8 @@ namespace OpenSim.Region.Framework.Scenes
696 /// </param> 685 /// </param>
697 public void StopScriptInstance(TaskInventoryItem item) 686 public void StopScriptInstance(TaskInventoryItem item)
698 { 687 {
699 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); 688 if (m_part.ParentGroup.Scene != null)
689 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
700 690
701 // At the moment, even stopped scripts are counted as active, which is probably wrong. 691 // At the moment, even stopped scripts are counted as active, which is probably wrong.
702// m_part.ParentGroup.AddActiveScriptCount(-1); 692// m_part.ParentGroup.AddActiveScriptCount(-1);
@@ -880,8 +870,8 @@ namespace OpenSim.Region.Framework.Scenes
880 870
881 return items; 871 return items;
882 } 872 }
883 873
884 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 874 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
885 { 875 {
886 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 876 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
887 877
@@ -890,70 +880,102 @@ namespace OpenSim.Region.Framework.Scenes
890 m_log.WarnFormat( 880 m_log.WarnFormat(
891 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 881 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
892 item.AssetID, item.Name, m_part.Name); 882 item.AssetID, item.Name, m_part.Name);
893 return null; 883 objlist = null;
884 veclist = null;
885 return false;
894 } 886 }
895 887
896 string xmlData = Utils.BytesToString(rezAsset.Data); 888 Vector3 bbox;
897 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 889 float offsetHeight;
898 890
899 group.RootPart.AttachPoint = group.RootPart.Shape.State; 891 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
900 group.RootPart.AttachOffset = group.AbsolutePosition;
901 group.RootPart.AttachRotation = group.GroupRotation;
902 892
903 group.ResetIDs(); 893 for (int i = 0; i < objlist.Count; i++)
904 894 {
905 SceneObjectPart rootPart = group.GetPart(group.UUID); 895 SceneObjectGroup group = objlist[i];
906 896/*
907 // Since renaming the item in the inventory does not affect the name stored 897 group.RootPart.AttachPoint = group.RootPart.Shape.State;
908 // in the serialization, transfer the correct name from the inventory to the 898 group.RootPart.AttachedPos = group.AbsolutePosition;
909 // object itself before we rez. 899 group.RootPart.AttachRotation = group.GroupRotation;
910 rootPart.Name = item.Name; 900*/
911 rootPart.Description = item.Description; 901 group.ResetIDs();
902
903 SceneObjectPart rootPart = group.GetPart(group.UUID);
904
905 // Since renaming the item in the inventory does not affect the name stored
906 // in the serialization, transfer the correct name from the inventory to the
907 // object itself before we rez.
908 // Only do these for the first object if we are rezzing a coalescence.
909 // nahh dont mess with coalescence objects,
910 // the name in inventory can be change for inventory purpuses only
911 if (objlist.Count == 1)
912 {
913 rootPart.Name = item.Name;
914 rootPart.Description = item.Description;
915 }
916/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed
917 group.SetGroup(m_part.GroupID, null);
912 918
913 SceneObjectPart[] partList = group.Parts; 919 foreach (SceneObjectPart part in group.Parts)
920 {
921 // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :)
922 InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID);
923 dest.BasePermissions = item.BasePermissions;
924 dest.CurrentPermissions = item.CurrentPermissions;
925 dest.EveryOnePermissions = item.EveryonePermissions;
926 dest.GroupPermissions = item.GroupPermissions;
927 dest.NextPermissions = item.NextPermissions;
928 dest.Flags = item.Flags;
929
930 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
931 }
932*/
933// old code start
934 SceneObjectPart[] partList = group.Parts;
914 935
915 group.SetGroup(m_part.GroupID, null); 936 group.SetGroup(m_part.GroupID, null);
916 937
917 // TODO: Remove magic number badness 938 // TODO: Remove magic number badness
918 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 939 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
919 {
920 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
921 { 940 {
922 foreach (SceneObjectPart part in partList) 941 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
923 { 942 {
924 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 943 foreach (SceneObjectPart part in partList)
925 part.EveryoneMask = item.EveryonePermissions; 944 {
926 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) 945 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
927 part.NextOwnerMask = item.NextPermissions; 946 part.EveryoneMask = item.EveryonePermissions;
928 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 947 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
929 part.GroupMask = item.GroupPermissions; 948 part.NextOwnerMask = item.NextPermissions;
949 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
950 part.GroupMask = item.GroupPermissions;
951 }
952
953 group.ApplyNextOwnerPermissions();
930 } 954 }
931
932 group.ApplyNextOwnerPermissions();
933 } 955 }
934 }
935 956
936 foreach (SceneObjectPart part in partList) 957 foreach (SceneObjectPart part in partList)
937 {
938 // TODO: Remove magic number badness
939 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
940 { 958 {
941 part.LastOwnerID = part.OwnerID; 959 // TODO: Remove magic number badness
942 part.OwnerID = item.OwnerID; 960 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
943 part.Inventory.ChangeInventoryOwner(item.OwnerID); 961 {
962 part.LastOwnerID = part.OwnerID;
963 part.OwnerID = item.OwnerID;
964 part.Inventory.ChangeInventoryOwner(item.OwnerID);
965 }
966
967 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
968 part.EveryoneMask = item.EveryonePermissions;
969 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
970 part.NextOwnerMask = item.NextPermissions;
971 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
972 part.GroupMask = item.GroupPermissions;
944 } 973 }
945 974// old code end
946 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 975 rootPart.TrimPermissions();
947 part.EveryoneMask = item.EveryonePermissions;
948 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
949 part.NextOwnerMask = item.NextPermissions;
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
951 part.GroupMask = item.GroupPermissions;
952 } 976 }
953 977
954 rootPart.TrimPermissions(); 978 return true;
955
956 return group;
957 } 979 }
958 980
959 /// <summary> 981 /// <summary>
@@ -1077,23 +1099,6 @@ namespace OpenSim.Region.Framework.Scenes
1077 return -1; 1099 return -1;
1078 } 1100 }
1079 1101
1080 private bool CreateInventoryFileName()
1081 {
1082// m_log.DebugFormat(
1083// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
1084// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial);
1085
1086 if (m_inventoryFileName == String.Empty ||
1087 m_inventoryFileNameSerial < m_inventorySerial)
1088 {
1089 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
1090 m_inventoryFileNameSerial = m_inventorySerial;
1091
1092 return true;
1093 }
1094
1095 return false;
1096 }
1097 1102
1098 /// <summary> 1103 /// <summary>
1099 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client 1104 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
@@ -1101,110 +1106,124 @@ namespace OpenSim.Region.Framework.Scenes
1101 /// <param name="xferManager"></param> 1106 /// <param name="xferManager"></param>
1102 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1107 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1103 { 1108 {
1104 bool changed = CreateInventoryFileName();
1105 1109
1106 bool includeAssets = false; 1110 lock (m_inventoryFileLock)
1107 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId)) 1111 {
1108 includeAssets = true; 1112 string filename = "inventory_" + UUID.Random().ToString() + ".tmp";
1109 1113
1110 if (m_inventoryPrivileged != includeAssets) 1114 bool changed = false;
1111 changed = true; 1115 if (m_inventoryFileNameSerial < m_inventorySerial)
1116 {
1117 m_inventoryFileNameSerial = m_inventorySerial;
1118 changed = true;
1119 }
1112 1120
1113 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1121 if (m_inventoryFileData.Length < 2)
1122 changed = true;
1114 1123
1115 Items.LockItemsForRead(true); 1124 bool includeAssets = false;
1125 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1126 includeAssets = true;
1116 1127
1117 if (m_inventorySerial == 0) // No inventory 1128 if (m_inventoryPrivileged != includeAssets)
1118 { 1129 changed = true;
1119 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1120 Items.LockItemsForRead(false);
1121 return;
1122 }
1123 1130
1124 if (m_items.Count == 0) // No inventory
1125 {
1126 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1127 Items.LockItemsForRead(false);
1128 return;
1129 }
1130
1131 if (!changed)
1132 {
1133 if (m_inventoryFileData.Length > 2)
1134 {
1135 xferManager.AddNewFile(m_inventoryFileName,
1136 m_inventoryFileData);
1137 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1138 Util.StringToBytes256(m_inventoryFileName));
1139 1131
1132 Items.LockItemsForRead(true);
1133
1134 if (m_inventorySerial == 0) // No inventory
1135 {
1140 Items.LockItemsForRead(false); 1136 Items.LockItemsForRead(false);
1137 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1138
1141 return; 1139 return;
1142 } 1140 }
1143 }
1144
1145 m_inventoryPrivileged = includeAssets;
1146
1147 foreach (TaskInventoryItem item in m_items.Values)
1148 {
1149 UUID ownerID = item.OwnerID;
1150 uint everyoneMask = 0;
1151 uint baseMask = item.BasePermissions;
1152 uint ownerMask = item.CurrentPermissions;
1153 uint groupMask = item.GroupPermissions;
1154 1141
1155 invString.AddItemStart(); 1142 if (m_items.Count == 0) // No inventory
1156 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 1143 {
1157 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 1144 Items.LockItemsForRead(false);
1158 1145 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1159 invString.AddPermissionsStart(); 1146 return;
1160 1147 }
1161 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1162 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1163 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1164 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1165 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1166 1148
1167 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1149 if (!changed)
1168 invString.AddNameValueLine("owner_id", ownerID.ToString()); 1150 {
1151 Items.LockItemsForRead(false);
1169 1152
1170 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1153 xferManager.AddNewFile(filename,
1154 m_inventoryFileData);
1155 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1156 Util.StringToBytes256(filename));
1171 1157
1172 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1158 return;
1173 invString.AddSectionEnd(); 1159 }
1174 1160
1175 if (includeAssets) 1161 m_inventoryPrivileged = includeAssets;
1176 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1177 else
1178 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1179 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1180 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1181 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1182 1162
1183 invString.AddSaleStart(); 1163 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1184 invString.AddNameValueLine("sale_type", "not");
1185 invString.AddNameValueLine("sale_price", "0");
1186 invString.AddSectionEnd();
1187 1164
1188 invString.AddNameValueLine("name", item.Name + "|"); 1165 foreach (TaskInventoryItem item in m_items.Values)
1189 invString.AddNameValueLine("desc", item.Description + "|"); 1166 {
1167 UUID ownerID = item.OwnerID;
1168 uint everyoneMask = 0;
1169 uint baseMask = item.BasePermissions;
1170 uint ownerMask = item.CurrentPermissions;
1171 uint groupMask = item.GroupPermissions;
1172
1173 invString.AddItemStart();
1174 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1175 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1176
1177 invString.AddPermissionsStart();
1178
1179 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1180 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1181 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1182 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1183 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1184
1185 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1186 invString.AddNameValueLine("owner_id", ownerID.ToString());
1187
1188 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1189
1190 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1191 invString.AddSectionEnd();
1192
1193 if (includeAssets)
1194 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1195 else
1196 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1197 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1198 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1199 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1200
1201 invString.AddSaleStart();
1202 invString.AddNameValueLine("sale_type", "not");
1203 invString.AddNameValueLine("sale_price", "0");
1204 invString.AddSectionEnd();
1205
1206 invString.AddNameValueLine("name", item.Name + "|");
1207 invString.AddNameValueLine("desc", item.Description + "|");
1208
1209 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1210 invString.AddSectionEnd();
1211 }
1190 1212
1191 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1213 Items.LockItemsForRead(false);
1192 invString.AddSectionEnd();
1193 }
1194 1214
1195 Items.LockItemsForRead(false); 1215 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
1196 1216
1197 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1217 if (m_inventoryFileData.Length > 2)
1218 {
1219 xferManager.AddNewFile(filename, m_inventoryFileData);
1220 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1221 Util.StringToBytes256(filename));
1222 return;
1223 }
1198 1224
1199 if (m_inventoryFileData.Length > 2) 1225 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1200 {
1201 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1202 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1203 Util.StringToBytes256(m_inventoryFileName));
1204 return;
1205 } 1226 }
1206
1207 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1208 } 1227 }
1209 1228
1210 /// <summary> 1229 /// <summary>
@@ -1221,10 +1240,17 @@ namespace OpenSim.Region.Framework.Scenes
1221// if (HasInventoryChanged) 1240// if (HasInventoryChanged)
1222// { 1241// {
1223 Items.LockItemsForRead(true); 1242 Items.LockItemsForRead(true);
1224 datastore.StorePrimInventory(m_part.UUID, Items.Values); 1243 try
1225 Items.LockItemsForRead(false); 1244 {
1245 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1246 }
1247 catch {}
1226 1248
1227 HasInventoryChanged = false; 1249 HasInventoryChanged = false;
1250
1251 Items.LockItemsForRead(false);
1252
1253
1228// } 1254// }
1229 } 1255 }
1230 1256
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7004d23..c58847b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,7 +29,9 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using Nini.Config;
@@ -73,20 +75,59 @@ namespace OpenSim.Region.Framework.Scenes
73 75
74 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
75 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
76// ~ScenePresence() 80// ~ScenePresence()
77// { 81// {
78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 83// }
80 84
81 private void TriggerScenePresenceUpdated() 85 public void TriggerScenePresenceUpdated()
82 { 86 {
83 if (m_scene != null) 87 if (m_scene != null)
84 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
85 } 89 }
86 90
87 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 91 public bool isNPC { get; private set; }
92
93 private PresenceType m_presenceType;
94 public PresenceType PresenceType {
95 get {return m_presenceType;}
96 private set
97 {
98 m_presenceType = value;
99 isNPC = (m_presenceType == PresenceType.Npc);
100 }
101 }
102
103 private ScenePresenceStateMachine m_stateMachine;
104
105 /// <summary>
106 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
107 /// for more details.
108 /// </summary>
109 public ScenePresenceState LifecycleState
110 {
111 get
112 {
113 return m_stateMachine.GetState();
114 }
115
116 set
117 {
118 m_stateMachine.SetState(value);
119 }
120 }
88 121
89 public PresenceType PresenceType { get; private set; } 122 /// <summary>
123 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
124 /// the viewer fires these in quick succession.
125 /// </summary>
126 /// <remarks>
127 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
128 /// regulation done there.
129 /// </remarks>
130 private object m_completeMovementLock = new object();
90 131
91// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 132// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
92 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 133 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
@@ -109,13 +150,100 @@ namespace OpenSim.Region.Framework.Scenes
109 /// </summary> 150 /// </summary>
110 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 151 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f;
111 152
112 public UUID currentParcelUUID = UUID.Zero; 153 private UUID m_previusParcelUUID = UUID.Zero;
154 private UUID m_currentParcelUUID = UUID.Zero;
155 private bool m_previusParcelHide = false;
156 private bool m_currentParcelHide = false;
157 private object parcelLock = new Object();
158
159 public UUID currentParcelUUID
160 {
161 get { return m_currentParcelUUID; }
162 set
163 {
164 lock (parcelLock)
165 {
166 bool oldhide = m_currentParcelHide;
167 bool checksame = true;
168 if (value != m_currentParcelUUID)
169 {
170 m_previusParcelHide = m_currentParcelHide;
171 m_previusParcelUUID = m_currentParcelUUID;
172 checksame = false;
173 }
174 m_currentParcelUUID = value;
175 m_currentParcelHide = false;
176
177 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
178 if (land != null && !land.LandData.SeeAVs)
179 m_currentParcelHide = true;
113 180
181 if (m_previusParcelUUID != UUID.Zero || checksame)
182 ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
183 }
184 }
185 }
186
187 public void sitSOGmoved()
188 {
189 if (IsDeleted || !IsSatOnObject)
190 //what me? nahh
191 return;
192 if (IsInTransit)
193 return;
194
195 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
196 if (land == null)
197 return; //??
198 UUID parcelID = land.LandData.GlobalID;
199 if (m_currentParcelUUID != parcelID)
200 currentParcelUUID = parcelID;
201 }
202
203
204 public bool ParcelAllowThisAvatarSounds
205 {
206 get
207 {
208 try
209 {
210 lock (parcelLock)
211 {
212 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
213 if (land == null)
214 return true;
215 if (land.LandData.AnyAVSounds)
216 return true;
217 if (!land.LandData.GroupAVSounds)
218 return false;
219 return land.LandData.GroupID == ControllingClient.ActiveGroupId;
220 }
221 }
222 catch
223 {
224 return true;
225 }
226 }
227 }
228
229 public bool ParcelHideThisAvatar
230 {
231 get
232 {
233 return m_currentParcelHide;
234 }
235 }
236
114 /// <value> 237 /// <value>
115 /// The animator for this avatar 238 /// The animator for this avatar
116 /// </value> 239 /// </value>
117 public ScenePresenceAnimator Animator { get; private set; } 240 public ScenePresenceAnimator Animator { get; private set; }
118 241
242 /// <value>
243 /// Server Side Animation Override
244 /// </value>
245 public MovementAnimationOverrides Overrides { get; private set; }
246 public String sitAnimation = "SIT";
119 /// <summary> 247 /// <summary>
120 /// Attachments recorded on this avatar. 248 /// Attachments recorded on this avatar.
121 /// </summary> 249 /// </summary>
@@ -142,6 +270,8 @@ namespace OpenSim.Region.Framework.Scenes
142 private Vector3 m_lastVelocity; 270 private Vector3 m_lastVelocity;
143 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 271 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
144 272
273 private bool m_followCamAuto = false;
274
145 275
146 private Vector3? m_forceToApply; 276 private Vector3? m_forceToApply;
147 private int m_userFlags; 277 private int m_userFlags;
@@ -157,14 +287,7 @@ namespace OpenSim.Region.Framework.Scenes
157 set { PhysicsActor.Flying = value; } 287 set { PhysicsActor.Flying = value; }
158 } 288 }
159 289
160 // add for fly velocity control 290 public bool IsColliding
161 private bool FlyingOld {get; set;}
162 public bool WasFlying
163 {
164 get; private set;
165 }
166
167 public bool IsColliding
168 { 291 {
169 get { return PhysicsActor != null && PhysicsActor.IsColliding; } 292 get { return PhysicsActor != null && PhysicsActor.IsColliding; }
170 // We would expect setting IsColliding to be private but it's used by a hack in Scene 293 // We would expect setting IsColliding to be private but it's used by a hack in Scene
@@ -200,7 +323,7 @@ namespace OpenSim.Region.Framework.Scenes
200 private float m_sitAvatarHeight = 2.0f; 323 private float m_sitAvatarHeight = 2.0f;
201 324
202 private Vector3 m_lastChildAgentUpdatePosition; 325 private Vector3 m_lastChildAgentUpdatePosition;
203 private Vector3 m_lastChildAgentUpdateCamPosition; 326// private Vector3 m_lastChildAgentUpdateCamPosition;
204 327
205 private const int LAND_VELOCITYMAG_MAX = 12; 328 private const int LAND_VELOCITYMAG_MAX = 12;
206 329
@@ -213,7 +336,7 @@ namespace OpenSim.Region.Framework.Scenes
213 336
214 protected ulong crossingFromRegion; 337 protected ulong crossingFromRegion;
215 338
216 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 339 private readonly Vector3[] Dir_Vectors = new Vector3[12];
217 340
218 protected Timer m_reprioritization_timer; 341 protected Timer m_reprioritization_timer;
219 protected bool m_reprioritizing; 342 protected bool m_reprioritizing;
@@ -270,7 +393,7 @@ namespace OpenSim.Region.Framework.Scenes
270 /// <summary> 393 /// <summary>
271 /// Implemented Control Flags 394 /// Implemented Control Flags
272 /// </summary> 395 /// </summary>
273 private enum Dir_ControlFlags 396 private enum Dir_ControlFlags:uint
274 { 397 {
275 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, 398 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
276 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, 399 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
@@ -282,6 +405,7 @@ namespace OpenSim.Region.Framework.Scenes
282 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 405 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
283 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, 406 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
284 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, 407 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
408 DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS,
285 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 409 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
286 } 410 }
287 411
@@ -290,9 +414,37 @@ namespace OpenSim.Region.Framework.Scenes
290 /// </summary> 414 /// </summary>
291 private Vector3 posLastSignificantMove; 415 private Vector3 posLastSignificantMove;
292 416
293 // For teleports and crossings callbacks 417 #region For teleports and crossings callbacks
294 string m_callbackURI; 418
295 UUID m_originRegionID; 419 /// <summary>
420 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
421 /// </summary>
422 private string m_callbackURI;
423
424 /// <summary>
425 /// Records the region from which this presence originated, if not from login.
426 /// </summary>
427 /// <remarks>
428 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
429 /// CompleteMovement and made the previous child agent a root agent.
430 /// </remarks>
431 private UUID m_originRegionID;
432
433 /// <summary>
434 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
435 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
436 /// it is a value type.
437 /// </summary>
438 private object m_originRegionIDAccessLock = new object();
439
440 /// <summary>
441 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
442 /// teleport is reusing the connection.
443 /// </summary>
444 /// <remarks>May be refactored or move somewhere else soon.</remarks>
445 public bool DoNotCloseAfterTeleport { get; set; }
446
447 #endregion
296 448
297 /// <value> 449 /// <value>
298 /// Script engines present in the scene 450 /// Script engines present in the scene
@@ -309,15 +461,12 @@ namespace OpenSim.Region.Framework.Scenes
309 /// <summary> 461 /// <summary>
310 /// Record user movement inputs. 462 /// Record user movement inputs.
311 /// </summary> 463 /// </summary>
312 public byte MovementFlag { get; private set; } 464 public uint MovementFlag { get; private set; }
313 465
314 private bool m_updateflag; 466 /// <summary>
315 467 /// Is the agent stop control flag currently active?
316 public bool Updated 468 /// </summary>
317 { 469 public bool AgentControlStopActive { get; private set; }
318 set { m_updateflag = value; }
319 get { return m_updateflag; }
320 }
321 470
322 private bool m_invulnerable = true; 471 private bool m_invulnerable = true;
323 472
@@ -344,11 +493,18 @@ namespace OpenSim.Region.Framework.Scenes
344 } 493 }
345 494
346 private ulong m_rootRegionHandle; 495 private ulong m_rootRegionHandle;
496 private Vector3 m_rootRegionPosition = new Vector3();
347 497
348 public ulong RegionHandle 498 public ulong RegionHandle
349 { 499 {
350 get { return m_rootRegionHandle; } 500 get { return m_rootRegionHandle; }
351 private set { m_rootRegionHandle = value; } 501 private set
502 {
503 m_rootRegionHandle = value;
504 // position rounded to lower multiple of 256m
505 m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
506 m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
507 }
352 } 508 }
353 509
354 #region Client Camera 510 #region Client Camera
@@ -380,11 +536,8 @@ namespace OpenSim.Region.Framework.Scenes
380 get 536 get
381 { 537 {
382 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 538 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
383 539 a.Normalize();
384 if (a == Vector3.Zero) 540 return a;
385 return a;
386
387 return Util.GetNormalizedVector(a);
388 } 541 }
389 } 542 }
390 #endregion 543 #endregion
@@ -424,6 +577,7 @@ namespace OpenSim.Region.Framework.Scenes
424 } 577 }
425 } 578 }
426 579
580
427 public byte State { get; set; } 581 public byte State { get; set; }
428 582
429 private AgentManager.ControlFlags m_AgentControlFlags; 583 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -462,6 +616,7 @@ namespace OpenSim.Region.Framework.Scenes
462 } 616 }
463 else 617 else
464 { 618 {
619// m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
465 // Obtain the correct position of a seated avatar. 620 // Obtain the correct position of a seated avatar.
466 // In addition to providing the correct position while 621 // In addition to providing the correct position while
467 // the avatar is seated, this value will also 622 // the avatar is seated, this value will also
@@ -475,17 +630,21 @@ namespace OpenSim.Region.Framework.Scenes
475 // in the sim unless the avatar is on a sit target. While 630 // in the sim unless the avatar is on a sit target. While
476 // on a sit target, m_pos will contain the desired offset 631 // on a sit target, m_pos will contain the desired offset
477 // without the parent rotation applied. 632 // without the parent rotation applied.
478 SceneObjectPart sitPart = ParentPart; 633 if (ParentPart != null)
479 634 {
480 if (sitPart != null) 635 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
481 return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 636 // if (sitPart != null)
637 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
638 if (rootPart != null)
639 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
640 }
482 } 641 }
483 642
484 return m_pos; 643 return m_pos;
485 } 644 }
486 set 645 set
487 { 646 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 647// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
489// Util.PrintCallStack(); 648// Util.PrintCallStack();
490 649
491 if (PhysicsActor != null) 650 if (PhysicsActor != null)
@@ -502,10 +661,7 @@ namespace OpenSim.Region.Framework.Scenes
502 661
503 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 662 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
504 if (ParentID == 0) 663 if (ParentID == 0)
505 {
506 m_pos = value; 664 m_pos = value;
507// ParentPosition = Vector3.Zero;
508 }
509 665
510 //m_log.DebugFormat( 666 //m_log.DebugFormat(
511 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 667 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -573,24 +729,7 @@ namespace OpenSim.Region.Framework.Scenes
573// Scene.RegionInfo.RegionName, Name, m_velocity); 729// Scene.RegionInfo.RegionName, Name, m_velocity);
574 } 730 }
575 } 731 }
576/*
577 public override Vector3 AngularVelocity
578 {
579 get
580 {
581 if (PhysicsActor != null)
582 {
583 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
584 732
585 // m_log.DebugFormat(
586 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
587 // m_velocity, Name, Scene.RegionInfo.RegionName);
588 }
589
590 return m_rotationalvelocity;
591 }
592 }
593*/
594 private Quaternion m_bodyRot = Quaternion.Identity; 733 private Quaternion m_bodyRot = Quaternion.Identity;
595 734
596 /// <summary> 735 /// <summary>
@@ -760,6 +899,20 @@ namespace OpenSim.Region.Framework.Scenes
760 } 899 }
761 } 900 }
762 901
902
903 /// <summary>
904 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
905 /// </summary>
906 /// <remarks>
907 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
908 /// </remarks>
909 private const float AgentControlStopSlowVel = 0.2f;
910 // velocities
911 public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
912 public const float AgentControlNormalVel = 1.0f;
913
914 // old normal speed was tuned to match sl normal plus Fast modifiers
915 // so we need to rescale it
763 private float m_speedModifier = 1.0f; 916 private float m_speedModifier = 1.0f;
764 917
765 public float SpeedModifier 918 public float SpeedModifier
@@ -795,13 +948,14 @@ namespace OpenSim.Region.Framework.Scenes
795 948
796 public ScenePresence( 949 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 950 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 951 {
799 AttachmentsSyncLock = new Object(); 952 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 953 AllowMovement = true;
801 IsChildAgent = true; 954 IsChildAgent = true;
802 IsLoggingIn = false; 955 IsLoggingIn = false;
803 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 956 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
804 Animator = new ScenePresenceAnimator(this); 957 Animator = new ScenePresenceAnimator(this);
958 Overrides = new MovementAnimationOverrides();
805 PresenceType = type; 959 PresenceType = type;
806 DrawDistance = world.DefaultDrawDistance; 960 DrawDistance = world.DefaultDrawDistance;
807 RegionHandle = world.RegionInfo.RegionHandle; 961 RegionHandle = world.RegionInfo.RegionHandle;
@@ -811,7 +965,7 @@ namespace OpenSim.Region.Framework.Scenes
811 m_name = String.Format("{0} {1}", Firstname, Lastname); 965 m_name = String.Format("{0} {1}", Firstname, Lastname);
812 m_scene = world; 966 m_scene = world;
813 m_uuid = client.AgentId; 967 m_uuid = client.AgentId;
814 LocalId = m_scene.AllocateLocalId(); 968 LocalId = m_scene.AllocatePresenceLocalId();
815 969
816 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 970 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
817 if (account != null) 971 if (account != null)
@@ -824,7 +978,7 @@ namespace OpenSim.Region.Framework.Scenes
824 978
825 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 979 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
826 if (gm != null) 980 if (gm != null)
827 Grouptitle = gm.GetGroupTitle(m_uuid); 981 Grouptitle = gm.GetGroupTitle(m_uuid);
828 982
829 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 983 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
830 984
@@ -841,6 +995,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 995 SetDirectionVectors();
842 996
843 Appearance = appearance; 997 Appearance = appearance;
998
999 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 1000 }
845 1001
846 private void RegionHeartbeatEnd(Scene scene) 1002 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +1030,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 1030 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 1031 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 1032 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
1033 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 1034 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 1035 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1036 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -890,22 +1047,24 @@ namespace OpenSim.Region.Framework.Scenes
890 1047
891 private void SetDirectionVectors() 1048 private void SetDirectionVectors()
892 { 1049 {
893 Dir_Vectors[0] = Vector3.UnitX; //FORWARD 1050 Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
894 Dir_Vectors[1] = -Vector3.UnitX; //BACK 1051 Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
895 Dir_Vectors[2] = Vector3.UnitY; //LEFT 1052 Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
896 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 1053 Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
897 Dir_Vectors[4] = Vector3.UnitZ; //UP 1054 Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
898 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 1055 Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
899 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE 1056 Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
900 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE 1057 Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
901 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE 1058 Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
902 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE 1059 Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
903 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1060 Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
904 } 1061 Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
905 1062 }
1063
1064/* dont see any use for this
906 private Vector3[] GetWalkDirectionVectors() 1065 private Vector3[] GetWalkDirectionVectors()
907 { 1066 {
908 Vector3[] vector = new Vector3[11]; 1067 Vector3[] vector = new Vector3[12];
909 vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD 1068 vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD
910 vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK 1069 vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK
911 vector[2] = Vector3.UnitY; //LEFT 1070 vector[2] = Vector3.UnitY; //LEFT
@@ -916,10 +1075,11 @@ namespace OpenSim.Region.Framework.Scenes
916 vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE 1075 vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE
917 vector[8] = Vector3.UnitY; //LEFT_NUDGE 1076 vector[8] = Vector3.UnitY; //LEFT_NUDGE
918 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE 1077 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
919 vector[10] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE 1078 vector[10] = new Vector3(CameraAtAxis.Z, 0f, CameraUpAxis.Z); //UP_NUDGE
1079 vector[11] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE
920 return vector; 1080 return vector;
921 } 1081 }
922 1082*/
923 #endregion 1083 #endregion
924 1084
925 #region Status Methods 1085 #region Status Methods
@@ -927,6 +1087,7 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <summary> 1087 /// <summary>
928 /// Turns a child agent into a root agent. 1088 /// Turns a child agent into a root agent.
929 /// </summary> 1089 /// </summary>
1090 /// <remarks>
930 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 1091 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
931 /// avatar is actual in the sim. They can perform all actions. 1092 /// avatar is actual in the sim. They can perform all actions.
932 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1093 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -934,90 +1095,81 @@ namespace OpenSim.Region.Framework.Scenes
934 /// 1095 ///
935 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1096 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
936 /// delays that crossing. 1097 /// delays that crossing.
937 /// </summary> 1098 /// </remarks>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 1099
1100
1101 // only in use as part of completemovement
1102 // other uses need fix
1103 private bool MakeRootAgent(Vector3 pos, bool isFlying)
939 { 1104 {
940 m_log.DebugFormat( 1105 int ts = Util.EnvironmentTickCount();
941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName);
943 1106
944 if (ParentUUID != UUID.Zero) 1107 lock (m_completeMovementLock)
945 { 1108 {
946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1109 if (!IsChildAgent)
947 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1110 return false;
948 if (part == null) 1111
1112 m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1113 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1114
1115 // m_log.InfoFormat(
1116 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1117 // Name, m_scene.RegionInfo.RegionName);
1118
1119 if (ParentUUID != UUID.Zero)
949 { 1120 {
950 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1121 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1122 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1123 if (part == null)
1124 {
1125 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1126 ParentID = 0;
1127 ParentPart = null;
1128 PrevSitOffset = Vector3.Zero;
1129 HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1130 IsLoggingIn = false;
1131 }
1132 else
1133 {
1134 part.ParentGroup.AddAvatar(UUID);
1135 if (part.SitTargetPosition != Vector3.Zero)
1136 part.SitTargetAvatar = UUID;
1137 ParentID = part.LocalId;
1138 ParentPart = part;
1139 m_pos = PrevSitOffset;
1140 pos = part.GetWorldPosition();
1141 }
1142 ParentUUID = UUID.Zero;
951 } 1143 }
952 else 1144 else
953 { 1145 {
954 part.ParentGroup.AddAvatar(UUID); 1146 IsLoggingIn = false;
955 if (part.SitTargetPosition != Vector3.Zero)
956 part.SitTargetAvatar = UUID;
957// ParentPosition = part.GetWorldPosition();
958 ParentID = part.LocalId;
959 ParentPart = part;
960 m_pos = PrevSitOffset;
961// pos = ParentPosition;
962 pos = part.GetWorldPosition();
963 } 1147 }
964 ParentUUID = UUID.Zero;
965 1148
966 IsChildAgent = false; 1149 IsChildAgent = false;
967
968// Animator.TrySetMovementAnimation("SIT");
969 }
970 else
971 {
972 IsChildAgent = false;
973 IsLoggingIn = false;
974 } 1150 }
975 1151
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1152 m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
977 1153
978 IsChildAgent = false; 1154 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1155 // set and prevent the close of the connection on a subsequent re-teleport.
1156 // Should not be needed if we are not trying to tell this region to close
1157 // DoNotCloseAfterTeleport = false;
979 1158
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1159 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1160 if (gm != null)
982 Grouptitle = gm.GetGroupTitle(m_uuid); 1161 Grouptitle = gm.GetGroupTitle(m_uuid);
983 1162
1163 m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1164
984 RegionHandle = m_scene.RegionInfo.RegionHandle; 1165 RegionHandle = m_scene.RegionInfo.RegionHandle;
985 1166
986 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1167 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1168 m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
987 1169
988 UUID groupUUID = UUID.Zero;
989 string GroupName = string.Empty;
990 ulong groupPowers = 0;
991
992 // ----------------------------------
993 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
994 try
995 {
996 if (gm != null)
997 {
998 groupUUID = ControllingClient.ActiveGroupId;
999 GroupRecord record = gm.GetGroupRecord(groupUUID);
1000 if (record != null)
1001 GroupName = record.GroupName;
1002 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1003 if (groupMembershipData != null)
1004 groupPowers = groupMembershipData.GroupPowers;
1005 }
1006 ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName,
1007 Grouptitle);
1008 }
1009 catch (Exception e)
1010 {
1011 m_log.Debug("[AGENTUPDATE]: " + e.ToString());
1012 }
1013 // ------------------------------------
1014 1170
1015 if (ParentID == 0) 1171 if (ParentID == 0)
1016 { 1172 {
1017 // Moved this from SendInitialData to ensure that Appearance is initialized
1018 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1019 // related to the handling of attachments
1020 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1021 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1173 if (m_scene.TestBorderCross(pos, Cardinals.E))
1022 { 1174 {
1023 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1175 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
@@ -1051,7 +1203,7 @@ namespace OpenSim.Region.Framework.Scenes
1051 1203
1052 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1204 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
1053 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1205 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1054 1206
1055 float newPosZ = posZLimit + localAVHeight / 2; 1207 float newPosZ = posZLimit + localAVHeight / 2;
1056 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1208 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1057 { 1209 {
@@ -1059,6 +1211,7 @@ namespace OpenSim.Region.Framework.Scenes
1059 } 1211 }
1060 AbsolutePosition = pos; 1212 AbsolutePosition = pos;
1061 1213
1214
1062 if (m_teleportFlags == TeleportFlags.Default) 1215 if (m_teleportFlags == TeleportFlags.Default)
1063 { 1216 {
1064 Vector3 vel = Velocity; 1217 Vector3 vel = Velocity;
@@ -1069,12 +1222,6 @@ namespace OpenSim.Region.Framework.Scenes
1069 else 1222 else
1070 AddToPhysicalScene(isFlying); 1223 AddToPhysicalScene(isFlying);
1071 1224
1072 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1073 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1074 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1075 // the value to a negative position which does not trigger the border cross.
1076 // This may not be the best location for this.
1077 CheckForBorderCrossing();
1078 1225
1079 if (ForceFly) 1226 if (ForceFly)
1080 { 1227 {
@@ -1084,66 +1231,21 @@ namespace OpenSim.Region.Framework.Scenes
1084 { 1231 {
1085 Flying = false; 1232 Flying = false;
1086 } 1233 }
1087 }
1088 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
1089 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
1090 // elsewhere anyway
1091 // Animator.SendAnimPack();
1092 1234
1093 m_scene.SwapRootAgentCount(false); 1235 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1236 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1237 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1238 // the value to a negative position which does not trigger the border cross.
1239 // This may not be the best location for this.
1094 1240
1095 // The initial login scene presence is already root when it gets here
1096 // and it has already rezzed the attachments and started their scripts.
1097 // We do the following only for non-login agents, because their scripts
1098 // haven't started yet.
1099 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1100 {
1101 // Viewers which have a current outfit folder will actually rez their own attachments. However,
1102 // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
1103 if (Scene.AttachmentsModule != null)
1104 Util.FireAndForget(
1105 o =>
1106 {
1107// if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None)
1108// System.Threading.Thread.Sleep(7000);
1109 1241
1110 Scene.AttachmentsModule.RezAttachments(this); 1242 // its not
1111 }); 1243// CheckForBorderCrossing();
1112 } 1244 }
1113 else 1245
1114 { 1246 m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1115 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT 1247 m_scene.SwapRootAgentCount(false);
1116 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1117 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data.
1119 lock (m_attachments)
1120 {
1121 if (HasAttachments())
1122 {
1123 m_log.DebugFormat(
1124 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1125
1126 // Resume scripts
1127 Util.FireAndForget(delegate(object x) {
1128 foreach (SceneObjectGroup sog in m_attachments)
1129 {
1130 sog.ScheduleGroupForFullUpdate();
1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1132 sog.ResumeScripts();
1133 }
1134 });
1135 }
1136 }
1137 }
1138
1139 SendAvatarDataToAllAgents();
1140 1248
1141 // send the animations of the other presences to me
1142 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1143 {
1144 if (presence != this)
1145 presence.Animator.SendAnimPackToClient(ControllingClient);
1146 });
1147 1249
1148 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1250 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1149 // stall on the border crossing since the existing child agent will still have the last movement 1251 // stall on the border crossing since the existing child agent will still have the last movement
@@ -1152,8 +1254,9 @@ namespace OpenSim.Region.Framework.Scenes
1152 MovementFlag = 0; 1254 MovementFlag = 0;
1153 1255
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1256 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1257 m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1155 1258
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1259 return true;
1157 } 1260 }
1158 1261
1159 public int GetStateSource() 1262 public int GetStateSource()
@@ -1179,11 +1282,19 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// It doesn't get called for a teleport. Reason being, an agent that 1282 /// It doesn't get called for a teleport. Reason being, an agent that
1180 /// teleports out may not end up anywhere near this region 1283 /// teleports out may not end up anywhere near this region
1181 /// </remarks> 1284 /// </remarks>
1182 public void MakeChildAgent() 1285 public void MakeChildAgent(ulong newRegionHandle)
1183 { 1286 {
1184 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1287 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1185 1288
1186 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1289 RegionHandle = newRegionHandle;
1290
1291 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1292 Name, Scene.RegionInfo.RegionName, newRegionHandle);
1293
1294 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1295 // from the source simulator has completed on a V2 teleport.
1296 lock (m_originRegionIDAccessLock)
1297 m_originRegionID = UUID.Zero;
1187 1298
1188 // Reset these so that teleporting in and walking out isn't seen 1299 // Reset these so that teleporting in and walking out isn't seen
1189 // as teleporting back 1300 // as teleporting back
@@ -1198,7 +1309,7 @@ namespace OpenSim.Region.Framework.Scenes
1198 else 1309 else
1199 Animator.ResetAnimations(); 1310 Animator.ResetAnimations();
1200 1311
1201 1312
1202// m_log.DebugFormat( 1313// m_log.DebugFormat(
1203// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1314// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1204// Name, UUID, m_scene.RegionInfo.RegionName); 1315// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1212,8 +1323,15 @@ namespace OpenSim.Region.Framework.Scenes
1212 RemoveFromPhysicalScene(); 1323 RemoveFromPhysicalScene();
1213 ParentID = 0; // Child agents can't be sitting 1324 ParentID = 0; // Child agents can't be sitting
1214 1325
1326// we dont have land information for child
1327 m_previusParcelHide = false;
1328 m_previusParcelUUID = UUID.Zero;
1329 m_currentParcelHide = false;
1330 m_currentParcelUUID = UUID.Zero;
1215 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1331 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1216 1332
1333 CollisionPlane = Vector4.UnitW;
1334
1217 m_scene.EventManager.TriggerOnMakeChildAgent(this); 1335 m_scene.EventManager.TriggerOnMakeChildAgent(this);
1218 } 1336 }
1219 1337
@@ -1306,7 +1424,29 @@ namespace OpenSim.Region.Framework.Scenes
1306 1424
1307 public void StopFlying() 1425 public void StopFlying()
1308 { 1426 {
1309 ControllingClient.StopFlying(this); 1427 if (IsInTransit)
1428 return;
1429
1430 Vector3 pos = AbsolutePosition;
1431 if (Appearance.AvatarHeight != 127.0f)
1432 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1433 else
1434 pos += new Vector3(0f, 0f, (1.56f / 6f));
1435
1436 AbsolutePosition = pos;
1437
1438 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1439 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1440 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1441 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1442
1443 // why are we still testing for this really old height value default???
1444 if (Appearance.AvatarHeight != 127.0f)
1445 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1446 else
1447 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1448
1449 SendAgentTerseUpdate(this);
1310 } 1450 }
1311 1451
1312 /// <summary> 1452 /// <summary>
@@ -1426,6 +1566,14 @@ namespace OpenSim.Region.Framework.Scenes
1426 } 1566 }
1427 } 1567 }
1428 1568
1569 public void DropThisRootRegionFromNeighbours()
1570 {
1571 ulong handle = m_scene.RegionInfo.RegionHandle;
1572 RemoveNeighbourRegion(handle);
1573 Scene.CapsModule.DropChildSeed(UUID, handle);
1574 }
1575
1576
1429 public Dictionary<ulong, string> KnownRegions 1577 public Dictionary<ulong, string> KnownRegions
1430 { 1578 {
1431 get 1579 get
@@ -1480,6 +1628,37 @@ namespace OpenSim.Region.Framework.Scenes
1480 1628
1481 } 1629 }
1482 1630
1631 private bool WaitForUpdateAgent(IClientAPI client)
1632 {
1633 // Before the source region executes UpdateAgent
1634 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1635 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1636 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1637 int count = 50;
1638 UUID originID;
1639
1640 lock (m_originRegionIDAccessLock)
1641 originID = m_originRegionID;
1642
1643 while (originID.Equals(UUID.Zero) && count-- > 0)
1644 {
1645 lock (m_originRegionIDAccessLock)
1646 originID = m_originRegionID;
1647
1648 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1649 Thread.Sleep(200);
1650 }
1651
1652 if (originID.Equals(UUID.Zero))
1653 {
1654 // Movement into region will fail
1655 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1656 return false;
1657 }
1658
1659 return true;
1660 }
1661
1483 /// <summary> 1662 /// <summary>
1484 /// Complete Avatar's movement into the region. 1663 /// Complete Avatar's movement into the region.
1485 /// </summary> 1664 /// </summary>
@@ -1491,53 +1670,88 @@ namespace OpenSim.Region.Framework.Scenes
1491 /// </param> 1670 /// </param>
1492 public void CompleteMovement(IClientAPI client, bool openChildAgents) 1671 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1493 { 1672 {
1494// DateTime startTime = DateTime.Now; 1673 int ts = Util.EnvironmentTickCount();
1495 1674
1496 m_log.DebugFormat( 1675 m_log.InfoFormat(
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1676 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1677 client.Name, Scene.Name, AbsolutePosition);
1499 1678
1500 Vector3 look = Velocity; 1679 m_inTransit = true;
1501 1680
1502 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1681 try
1503 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1504 { 1682 {
1505 look = new Vector3(0.99f, 0.042f, 0); 1683 // Make sure it's not a login agent. We don't want to wait for updates during login
1506 } 1684 if (!isNPC && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1685 {
1507 1686
1508 // Prevent teleporting to an underground location 1687 // Let's wait until UpdateAgent (called by departing region) is done
1509 // (may crash client otherwise) 1688 if (!WaitForUpdateAgent(client))
1510 // 1689 // The sending region never sent the UpdateAgent data, we have to refuse
1511 Vector3 pos = AbsolutePosition; 1690 return;
1512 float ground = m_scene.GetGroundHeight(pos.X, pos.Y); 1691 }
1513 if (pos.Z < ground + 1.5f)
1514 {
1515 pos.Z = ground + 1.5f;
1516 AbsolutePosition = pos;
1517 }
1518 1692
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1693 m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1520 MakeRootAgent(AbsolutePosition, flying);
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1522 1694
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1695 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1524 1696
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1697 if (!MakeRootAgent(AbsolutePosition, flying))
1526 { 1698 {
1527 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1699 m_log.DebugFormat(
1528 // CompleteMovement() is executed synchronously. However, it might be better to delay the release 1700 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1529 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 1701 Name, Scene.Name);
1530 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1531 // region as the current region, meaning that a close sent before then will fail the teleport.
1532// System.Threading.Thread.Sleep(2000);
1533 1702
1534 m_log.DebugFormat( 1703 return;
1535 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1704 }
1536 client.Name, client.AgentId, m_callbackURI);
1537 1705
1538 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1706 m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1539 m_callbackURI = null; 1707
1540 } 1708 Vector3 look = Lookat;
1709 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1710 {
1711 look = Velocity;
1712 look.Z = 0;
1713 look.Normalize();
1714 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1715 look = new Vector3(0.99f, 0.042f, 0);
1716 }
1717
1718 if (!IsChildAgent && !isNPC)
1719 {
1720 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
1721 if (cof == null)
1722 COF = UUID.Zero;
1723 else
1724 COF = cof.ID;
1725
1726 m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1727 }
1728
1729 // Tell the client that we're totally ready
1730 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1731
1732 m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1733
1734 if (!string.IsNullOrEmpty(m_callbackURI))
1735 {
1736 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1737 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1738 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1739 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1740 // region as the current region, meaning that a close sent before then will fail the teleport.
1741 // System.Threading.Thread.Sleep(2000);
1742
1743 m_log.DebugFormat(
1744 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1745 client.Name, client.AgentId, m_callbackURI);
1746
1747 UUID originID;
1748
1749 lock (m_originRegionIDAccessLock)
1750 originID = m_originRegionID;
1751
1752 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1753 m_callbackURI = null;
1754 }
1541// else 1755// else
1542// { 1756// {
1543// m_log.DebugFormat( 1757// m_log.DebugFormat(
@@ -1545,34 +1759,181 @@ namespace OpenSim.Region.Framework.Scenes
1545// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 1759// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1546// } 1760// }
1547 1761
1548 ValidateAndSendAppearanceAndAgentData(); 1762 m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1549 1763
1550 // Create child agents in neighbouring regions 1764 m_previusParcelHide = false;
1551 if (openChildAgents && !IsChildAgent) 1765 m_previusParcelUUID = UUID.Zero;
1552 { 1766 m_currentParcelHide = false;
1767 m_currentParcelUUID = UUID.Zero;
1553 1768
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1769 // send initial land overlay and parcel
1555 if (m_agentTransfer != null) 1770 ILandChannel landch = m_scene.LandChannel;
1556 m_agentTransfer.EnableChildAgents(this); 1771 if (landch != null)
1772 landch.sendClientInitialLandInfo(client);
1557 1773
1558 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1774 if (!IsChildAgent)
1559 if (friendsModule != null) 1775 {
1560 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1561 1776
1562 } 1777 // ValidateAndSendAppearanceAndAgentData();
1563 1778
1564 // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region 1779 // do it here in line
1565 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. 1780 // so sequence is clear
1566 // This may be due to viewer code or it may be something we're not doing properly simulator side. 1781
1567 lock (m_attachments) 1782 // verify baked textures and cache
1783
1784
1785 bool cachedbaked = false;
1786
1787 if (isNPC)
1788 cachedbaked = true;
1789 else
1790 {
1791 if (m_scene.AvatarFactory != null)
1792 cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
1793
1794 // not sure we need this
1795 if (!cachedbaked)
1796 {
1797 if (m_scene.AvatarFactory != null)
1798 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
1799 }
1800 }
1801
1802 List<ScenePresence> allpresences = m_scene.GetScenePresences();
1803
1804 // send avatar object to all presences including us, so they cross it into region
1805 // then hide if necessary
1806 SendInitialAvatarDataToAllAgents(allpresences);
1807
1808 // send this look
1809 SendAppearanceToAgent(this);
1810
1811 // send this animations
1812
1813 UUID[] animIDs = null;
1814 int[] animseqs = null;
1815 UUID[] animsobjs = null;
1816
1817 if (Animator != null)
1818 Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
1819
1820 bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
1821
1822 if(haveAnims)
1823 SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
1824
1825 // we should be able to receive updates, etc
1826 // so release them
1827 m_inTransit = false;
1828
1829 // send look and animations to others
1830 // if not cached we send greys
1831 // uncomented if will wait till avatar does baking
1832 //if (cachedbaked)
1833 {
1834 foreach (ScenePresence p in allpresences)
1835 {
1836 if (p == this)
1837 continue;
1838
1839 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1840 continue;
1841
1842 SendAppearanceToAgentNF(p);
1843 if (haveAnims)
1844 SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
1845 }
1846 } // greys if
1847
1848 m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1849
1850 // attachments
1851
1852 if (isNPC || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1853 {
1854 if (Scene.AttachmentsModule != null)
1855 // Util.FireAndForget(
1856 // o =>
1857 // {
1858 Scene.AttachmentsModule.RezAttachments(this);
1859 // });
1860 }
1861 else
1862 {
1863 if (m_attachments.Count > 0)
1864 {
1865 m_log.DebugFormat(
1866 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1867
1868 foreach(SceneObjectGroup sog in m_attachments)
1869 {
1870 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1871 sog.ResumeScripts();
1872 }
1873
1874 foreach (ScenePresence p in allpresences)
1875 {
1876 if (p == this)
1877 {
1878 SendTerseUpdateToAgentNF(this);
1879 SendAttachmentsToAgentNF(this);
1880 continue;
1881 }
1882
1883 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1884 continue;
1885
1886 SendTerseUpdateToAgentNF(p);
1887 SendAttachmentsToAgentNF(p);
1888 }
1889 }
1890 }
1891
1892 m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1893
1894 // Create child agents in neighbouring regions
1895 if (openChildAgents)
1896 {
1897 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1898 if (m_agentTransfer != null)
1899 {
1900 m_agentTransfer.EnableChildAgents(this);
1901 }
1902 }
1903 }
1904
1905 m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1906
1907 // send the rest of the world
1908 if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
1909 SendInitialDataToMe();
1910
1911 m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1912
1913 if (!IsChildAgent && openChildAgents)
1914 {
1915 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1916 if (friendsModule != null)
1917 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1918
1919 m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1920
1921 }
1922 }
1923 finally
1568 { 1924 {
1569 foreach (SceneObjectGroup sog in m_attachments) 1925 m_inTransit = false;
1570 sog.ScheduleGroupForFullUpdate();
1571 } 1926 }
1927 // if hide force a check
1928 // if (!IsChildAgent && newhide)
1929 // {
1930 // ParcelLoginCheck(m_currentParcelUUID);
1931 // m_currentParcelHide = newhide;
1932 // }
1572 1933
1573// m_log.DebugFormat( 1934 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1935
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1936 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1576 } 1937 }
1577 1938
1578 /// <summary> 1939 /// <summary>
@@ -1653,9 +2014,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 2014 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 2015 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 2016 {
1656// m_log.DebugFormat( 2017 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 2018 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 2019 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 2020
1660 if (IsChildAgent) 2021 if (IsChildAgent)
1661 { 2022 {
@@ -1663,9 +2024,8 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 2024 return;
1664 } 2025 }
1665 2026
1666 ++m_movementUpdateCount; 2027 if (IsInTransit)
1667 if (m_movementUpdateCount < 1) 2028 return;
1668 m_movementUpdateCount = 1;
1669 2029
1670 #region Sanity Checking 2030 #region Sanity Checking
1671 2031
@@ -1697,21 +2057,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 2057
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 2058 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 2059
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 2060 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 2061 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 2062 // changes, then start using the agent's drawdistance rather than the
@@ -1733,6 +2078,7 @@ namespace OpenSim.Region.Framework.Scenes
1733// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2078// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1734// m_updateCount = UPDATE_COUNT; 2079// m_updateCount = UPDATE_COUNT;
1735 2080
2081
1736 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2082 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1737 { 2083 {
1738 StandUp(); 2084 StandUp();
@@ -1783,9 +2129,16 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 2129 // Here's where you get them.
1784 m_AgentControlFlags = flags; 2130 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 2131 m_headrotation = agentData.HeadRotation;
2132 byte oldState = State;
1786 State = agentData.State; 2133 State = agentData.State;
1787 2134
2135 // We need to send this back to the client in order to stop the edit beams
2136 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2137 SendAgentTerseUpdate(this);
2138
1788 PhysicsActor actor = PhysicsActor; 2139 PhysicsActor actor = PhysicsActor;
2140
2141 // This will be the case if the agent is sitting on the groudn or on an object.
1789 if (actor == null) 2142 if (actor == null)
1790 { 2143 {
1791 SendControlsToScripts(flagsForScripts); 2144 SendControlsToScripts(flagsForScripts);
@@ -1794,12 +2147,11 @@ namespace OpenSim.Region.Framework.Scenes
1794 2147
1795 if (AllowMovement && !SitGround) 2148 if (AllowMovement && !SitGround)
1796 { 2149 {
1797 Quaternion bodyRotation = agentData.BodyRotation; 2150// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1798 bool update_rotation = false; 2151 bool update_rotation = false;
1799 2152 if (agentData.BodyRotation != Rotation)
1800 if (bodyRotation != Rotation)
1801 { 2153 {
1802 Rotation = bodyRotation; 2154 Rotation = agentData.BodyRotation;
1803 update_rotation = true; 2155 update_rotation = true;
1804 } 2156 }
1805 2157
@@ -1815,7 +2167,7 @@ namespace OpenSim.Region.Framework.Scenes
1815 bool DCFlagKeyPressed = false; 2167 bool DCFlagKeyPressed = false;
1816 Vector3 agent_control_v3 = Vector3.Zero; 2168 Vector3 agent_control_v3 = Vector3.Zero;
1817 2169
1818 bool newFlying = actor.Flying; 2170 bool newFlying = false;
1819 2171
1820 if (ForceFly) 2172 if (ForceFly)
1821 newFlying = true; 2173 newFlying = true;
@@ -1840,15 +2192,13 @@ namespace OpenSim.Region.Framework.Scenes
1840 2192
1841 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying 2193 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
1842 // this prevents 'jumping' in inappropriate situations. 2194 // this prevents 'jumping' in inappropriate situations.
1843 if (!Flying && (m_mouseLook || m_leftButtonDown)) 2195// if (!Flying && (m_mouseLook || m_leftButtonDown))
1844 dirVectors = GetWalkDirectionVectors(); 2196// dirVectors = GetWalkDirectionVectors();
1845 else 2197// else
1846 dirVectors = Dir_Vectors; 2198 dirVectors = Dir_Vectors;
1847 2199
1848 // The fact that MovementFlag is a byte needs to be fixed 2200
1849 // it really should be a uint
1850 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2201 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
1851 uint nudgehack = 250;
1852 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2202 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1853 { 2203 {
1854 if (((uint)flags & (uint)DCF) != 0) 2204 if (((uint)flags & (uint)DCF) != 0)
@@ -1865,29 +2215,19 @@ namespace OpenSim.Region.Framework.Scenes
1865 // Why did I get this? 2215 // Why did I get this?
1866 } 2216 }
1867 2217
1868 if ((MovementFlag & (byte)(uint)DCF) == 0) 2218 if (((MovementFlag & (uint)DCF) == 0))
1869 { 2219 {
1870 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1871 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1872 {
1873 MovementFlag |= (byte)nudgehack;
1874 }
1875
1876 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2220 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1877 MovementFlag += (byte)(uint)DCF; 2221 MovementFlag |= (uint)DCF;
1878 update_movementflag = true; 2222 update_movementflag = true;
1879 } 2223 }
1880 } 2224 }
1881 else 2225 else
1882 { 2226 {
1883 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2227 if ((MovementFlag & (uint)DCF) != 0)
1884 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1885 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1886 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1887 ) // This or is for Nudge forward
1888 { 2228 {
1889 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2229 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1890 MovementFlag -= ((byte)(uint)DCF); 2230 MovementFlag &= (uint)~DCF;
1891 update_movementflag = true; 2231 update_movementflag = true;
1892 2232
1893 /* 2233 /*
@@ -1907,6 +2247,13 @@ namespace OpenSim.Region.Framework.Scenes
1907 i++; 2247 i++;
1908 } 2248 }
1909 2249
2250 // Detect AGENT_CONTROL_STOP state changes
2251 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2252 {
2253 AgentControlStopActive = !AgentControlStopActive;
2254 update_movementflag = true;
2255 }
2256
1910 if (MovingToTarget) 2257 if (MovingToTarget)
1911 { 2258 {
1912 // If the user has pressed a key then we want to cancel any move to target. 2259 // If the user has pressed a key then we want to cancel any move to target.
@@ -1932,74 +2279,168 @@ namespace OpenSim.Region.Framework.Scenes
1932 // Only do this if we're flying 2279 // Only do this if we're flying
1933 if (Flying && !ForceFly) 2280 if (Flying && !ForceFly)
1934 { 2281 {
1935 // Landing detection code 2282 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1936 2283 // if (AgentControlStopActive)
1937 // Are the landing controls requirements filled? 2284 // {
1938 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2285 // agent_control_v3 = Vector3.Zero;
1939 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2286 // }
1940 2287 // else
1941 //m_log.Debug("[CONTROL]: " +flags);
1942 // Applies a satisfying roll effect to the avatar when flying.
1943 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
1944 {
1945 ApplyFlyingRoll(
1946 FLY_ROLL_RADIANS_PER_UPDATE,
1947 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1948 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1949 }
1950 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
1951 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1952 { 2288 {
1953 ApplyFlyingRoll( 2289 // Landing detection code
1954 -FLY_ROLL_RADIANS_PER_UPDATE,
1955 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1956 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1957 }
1958 else
1959 {
1960 if (m_AngularVelocity.Z != 0)
1961 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1962 }
1963 2290
1964 if (Flying && IsColliding && controlland) 2291 // Are the landing controls requirements filled?
1965 { 2292 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1966 // nesting this check because LengthSquared() is expensive and we don't 2293 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1967 // want to do it every step when flying. 2294
1968 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2295 //m_log.Debug("[CONTROL]: " +flags);
1969 StopFlying(); 2296 // Applies a satisfying roll effect to the avatar when flying.
2297 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2298 {
2299 ApplyFlyingRoll(
2300 FLY_ROLL_RADIANS_PER_UPDATE,
2301 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2302 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2303 }
2304 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2305 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2306 {
2307 ApplyFlyingRoll(
2308 -FLY_ROLL_RADIANS_PER_UPDATE,
2309 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2310 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2311 }
2312 else
2313 {
2314 if (m_AngularVelocity.Z != 0)
2315 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2316 }
2317
2318 /*
2319 if (Flying && IsColliding && controlland)
2320 {
2321 // nesting this check because LengthSquared() is expensive and we don't
2322 // want to do it every step when flying.
2323 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2324 StopFlying();
2325 }
2326 */
1970 } 2327 }
1971 } 2328 }
2329 else if (IsColliding && agent_control_v3.Z < 0f)
2330 agent_control_v3.Z = 0;
2331// else if(AgentControlStopActive %% Velocity.Z <0.01f)
2332
2333
2334// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
1972 2335
1973 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2336 // If the agent update does move the avatar, then calculate the force ready for the velocity update,
1974 // which occurs later in the main scene loop 2337 // which occurs later in the main scene loop
1975 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2338 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2339 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2340 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2341 // avatar location in place).
2342 if (update_movementflag
2343 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1976 { 2344 {
1977// m_log.DebugFormat(
1978// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
1979// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);
1980 2345
1981 AddNewMovement(agent_control_v3); 2346 if (AgentControlStopActive)
2347 {
2348 // if (MovementFlag == 0 && Animator.Falling)
2349 if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2350 {
2351 AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2352 }
2353 else
2354 AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2355 }
2356 else
2357 {
2358 AddNewMovement(agent_control_v3);
2359 }
2360
1982 } 2361 }
1983// else
1984// {
1985// if (!update_movementflag)
1986// {
1987// m_log.DebugFormat(
1988// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
1989// m_scene.RegionInfo.RegionName, agent_control_v3, Name);
1990// }
1991// }
1992 2362
1993 if (update_movementflag && ParentID == 0) 2363 if (update_movementflag && ParentID == 0)
2364 {
2365// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1994 Animator.UpdateMovementAnimations(); 2366 Animator.UpdateMovementAnimations();
2367 }
1995 2368
1996 SendControlsToScripts(flagsForScripts); 2369 SendControlsToScripts(flagsForScripts);
1997 } 2370 }
1998 2371
2372 // We need to send this back to the client in order to see the edit beams
2373 if ((State & (uint)AgentState.Editing) != 0)
2374 SendAgentTerseUpdate(this);
2375
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2376 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2377 }
2002 2378
2379
2380 /// <summary>
2381 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2382 /// </summary>
2383 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2384 {
2385 //m_log.DebugFormat(
2386 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2387 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2388
2389 if (IsChildAgent)
2390 {
2391 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2392 return;
2393 }
2394
2395 ++m_movementUpdateCount;
2396 if (m_movementUpdateCount < 1)
2397 m_movementUpdateCount = 1;
2398
2399// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2400
2401 // Camera location in world. We'll need to raytrace
2402 // from this location from time to time.
2403 CameraPosition = agentData.CameraCenter;
2404 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2405 {
2406 ReprioritizeUpdates();
2407 m_lastCameraPosition = CameraPosition;
2408 }
2409
2410 // Use these three vectors to figure out what the agent is looking at
2411 // Convert it to a Matrix and/or Quaternion
2412 CameraAtAxis = agentData.CameraAtAxis;
2413 CameraLeftAxis = agentData.CameraLeftAxis;
2414 CameraUpAxis = agentData.CameraUpAxis;
2415
2416 // The Agent's Draw distance setting
2417 // When we get to the point of re-computing neighbors everytime this
2418 // changes, then start using the agent's drawdistance rather than the
2419 // region's draw distance.
2420 // DrawDistance = agentData.Far;
2421 DrawDistance = Scene.DefaultDrawDistance;
2422
2423 // Check if Client has camera in 'follow cam' or 'build' mode.
2424 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2425
2426 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2427 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2428
2429
2430 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2431 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2432 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2433 {
2434 if (m_followCamAuto)
2435 {
2436 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2437 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2438 }
2439 }
2440
2441 TriggerScenePresenceUpdated();
2442 }
2443
2003 /// <summary> 2444 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2445 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2446 /// </summary>
@@ -2014,11 +2455,13 @@ namespace OpenSim.Region.Framework.Scenes
2014 2455
2015 bool updated = false; 2456 bool updated = false;
2016 2457
2458 Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition;
2459
2017// m_log.DebugFormat( 2460// m_log.DebugFormat(
2018// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 2461// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2019// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 2462// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2020 2463
2021 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 2464 double distanceToTarget = LocalVectorToTarget3D.Length();
2022 2465
2023// m_log.DebugFormat( 2466// m_log.DebugFormat(
2024// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 2467// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
@@ -2041,11 +2484,11 @@ namespace OpenSim.Region.Framework.Scenes
2041 // Theoretically we might need a more complex PID approach here if other 2484 // Theoretically we might need a more complex PID approach here if other
2042 // unknown forces are acting on the avatar and we need to adaptively respond 2485 // unknown forces are acting on the avatar and we need to adaptively respond
2043 // to such forces, but the following simple approach seems to works fine. 2486 // to such forces, but the following simple approach seems to works fine.
2044 Vector3 LocalVectorToTarget3D = 2487
2045 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 2488 LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords
2046 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
2047 // Ignore z component of vector 2489 // Ignore z component of vector
2048// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 2490// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
2491
2049 LocalVectorToTarget3D.Normalize(); 2492 LocalVectorToTarget3D.Normalize();
2050 2493
2051 // update avatar movement flags. the avatar coordinate system is as follows: 2494 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -2069,28 +2512,37 @@ namespace OpenSim.Region.Framework.Scenes
2069 2512
2070 // based on the above avatar coordinate system, classify the movement into 2513 // based on the above avatar coordinate system, classify the movement into
2071 // one of left/right/back/forward. 2514 // one of left/right/back/forward.
2515
2516 const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2517 Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2518 Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2519 Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2520
2521 MovementFlag &= noMovFlagsMask;
2522 AgentControlFlags &= noMovFlagsMask;
2523
2072 if (LocalVectorToTarget3D.X < 0) //MoveBack 2524 if (LocalVectorToTarget3D.X < 0) //MoveBack
2073 { 2525 {
2074 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2526 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2075 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2527 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2076 updated = true; 2528 updated = true;
2077 } 2529 }
2078 else if (LocalVectorToTarget3D.X > 0) //Move Forward 2530 else if (LocalVectorToTarget3D.X > 0) //Move Forward
2079 { 2531 {
2080 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2532 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2081 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2533 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2082 updated = true; 2534 updated = true;
2083 } 2535 }
2084 2536
2085 if (LocalVectorToTarget3D.Y > 0) //MoveLeft 2537 if (LocalVectorToTarget3D.Y > 0) //MoveLeft
2086 { 2538 {
2087 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2539 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2088 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2540 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2089 updated = true; 2541 updated = true;
2090 } 2542 }
2091 else if (LocalVectorToTarget3D.Y < 0) //MoveRight 2543 else if (LocalVectorToTarget3D.Y < 0) //MoveRight
2092 { 2544 {
2093 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2545 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2094 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2546 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2095 updated = true; 2547 updated = true;
2096 } 2548 }
@@ -2185,6 +2637,8 @@ namespace OpenSim.Region.Framework.Scenes
2185 targetScene = m_scene; 2637 targetScene = m_scene;
2186 2638
2187 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2639 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
2640 // dont try to land underground
2641 terrainHeight += Appearance.AvatarHeight / 2;
2188 pos.Z = Math.Max(terrainHeight, pos.Z); 2642 pos.Z = Math.Max(terrainHeight, pos.Z);
2189 2643
2190 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2644 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2196,10 +2650,11 @@ namespace OpenSim.Region.Framework.Scenes
2196// m_log.DebugFormat( 2650// m_log.DebugFormat(
2197// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2651// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2198// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2652// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2653
2199 2654
2200 if (noFly) 2655 if (noFly)
2201 Flying = false; 2656 Flying = false;
2202 else if (pos.Z > terrainHeight) 2657 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2203 Flying = true; 2658 Flying = true;
2204 2659
2205 LandAtTarget = landAtTarget; 2660 LandAtTarget = landAtTarget;
@@ -2252,17 +2707,13 @@ namespace OpenSim.Region.Framework.Scenes
2252 { 2707 {
2253// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2708// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2254 2709
2710 bool satOnObject = IsSatOnObject;
2711 SceneObjectPart part = ParentPart;
2255 SitGround = false; 2712 SitGround = false;
2256 2713
2257/* move this down so avatar gets physical in the new position and not where it is siting 2714 if (satOnObject)
2258 if (PhysicsActor == null)
2259 AddToPhysicalScene(false);
2260 */
2261
2262 if (ParentID != 0)
2263 { 2715 {
2264 PrevSitOffset = m_pos; // Save sit offset 2716 PrevSitOffset = m_pos; // Save sit offset
2265 SceneObjectPart part = ParentPart;
2266 UnRegisterSeatControls(part.ParentGroup.UUID); 2717 UnRegisterSeatControls(part.ParentGroup.UUID);
2267 2718
2268 TaskInventoryDictionary taskIDict = part.TaskInventory; 2719 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2281,34 +2732,64 @@ namespace OpenSim.Region.Framework.Scenes
2281 } 2732 }
2282 2733
2283 part.ParentGroup.DeleteAvatar(UUID); 2734 part.ParentGroup.DeleteAvatar(UUID);
2284// ParentPosition = part.GetWorldPosition();
2285 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2286 2735
2287// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2736 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2288// ParentPosition = Vector3.Zero; 2737 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2289 m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2738 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2290 if (part.SitTargetAvatar == UUID)
2291 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2292 2739
2293 ParentID = 0; 2740 ParentID = 0;
2294 ParentPart = null; 2741 ParentPart = null;
2295 2742
2296 if (PhysicsActor == null) 2743 if (part.SitTargetAvatar == UUID)
2297 AddToPhysicalScene(false); 2744 standRotation = standRotation * part.SitTargetOrientation;
2745 else
2746 standRotation = standRotation * m_bodyRot;
2298 2747
2299 SendAvatarDataToAllAgents(); 2748 m_bodyRot = standRotation;
2300 m_requestedSitTargetID = 0;
2301 2749
2302 part.RemoveSittingAvatar(UUID); 2750 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2303 2751
2304 if (part != null) 2752 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2753 if (t > 0)
2754 {
2755 t = 1.0f / (float)Math.Sqrt(t);
2756 standRotationZ.W *= t;
2757 standRotationZ.Z *= t;
2758 }
2759 else
2760 {
2761 standRotationZ.W = 1.0f;
2762 standRotationZ.Z = 0f;
2763 }
2764
2765 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2766
2767 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2768
2769 m_pos = standPos;
2306 } 2770 }
2307 2771
2308 else if (PhysicsActor == null) 2772 // We need to wait until we have calculated proper stand positions before sitting up the physical
2773 // avatar to avoid race conditions.
2774 if (PhysicsActor == null)
2309 AddToPhysicalScene(false); 2775 AddToPhysicalScene(false);
2310 2776
2311 Animator.TrySetMovementAnimation("STAND"); 2777 if (satOnObject)
2778 {
2779 m_requestedSitTargetID = 0;
2780 part.RemoveSittingAvatar(UUID);
2781 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2782
2783 SendAvatarDataToAllAgents();
2784 }
2785
2786 // reset to default sitAnimation
2787 sitAnimation = "SIT";
2788
2789// Animator.TrySetMovementAnimation("STAND");
2790 Animator.SetMovementAnimations("STAND");
2791
2792 TriggerScenePresenceUpdated();
2312 } 2793 }
2313 2794
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2795 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2355,20 +2836,17 @@ namespace OpenSim.Region.Framework.Scenes
2355 if (part == null) 2836 if (part == null)
2356 return; 2837 return;
2357 2838
2839
2358 if (PhysicsActor != null) 2840 if (PhysicsActor != null)
2359 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2841 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2360 2842
2361 bool canSit = false; 2843 bool canSit = false;
2362 Vector3 pos = part.AbsolutePosition + offset;
2363 2844
2364 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2845 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2365 { 2846 {
2366// m_log.DebugFormat(
2367// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2368// Name, part.Name, part.LocalId);
2369
2370 offset = part.SitTargetPosition; 2847 offset = part.SitTargetPosition;
2371 sitOrientation = part.SitTargetOrientation; 2848 sitOrientation = part.SitTargetOrientation;
2849
2372 canSit = true; 2850 canSit = true;
2373 } 2851 }
2374 else 2852 else
@@ -2376,9 +2854,10 @@ namespace OpenSim.Region.Framework.Scenes
2376 if (PhysicsSit(part,offset)) // physics engine 2854 if (PhysicsSit(part,offset)) // physics engine
2377 return; 2855 return;
2378 2856
2857 Vector3 pos = part.AbsolutePosition + offset;
2858
2379 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2859 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2380 { 2860 {
2381
2382 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2861 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2383 canSit = true; 2862 canSit = true;
2384 } 2863 }
@@ -2404,10 +2883,31 @@ namespace OpenSim.Region.Framework.Scenes
2404 cameraEyeOffset = part.GetCameraEyeOffset(); 2883 cameraEyeOffset = part.GetCameraEyeOffset();
2405 forceMouselook = part.GetForceMouselook(); 2884 forceMouselook = part.GetForceMouselook();
2406 2885
2886 if (!part.IsRoot)
2887 {
2888 sitOrientation = part.RotationOffset * sitOrientation;
2889 offset = offset * part.RotationOffset;
2890 offset += part.OffsetPosition;
2891
2892 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2893 {
2894 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
2895 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2896 }
2897 else
2898 {
2899 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2900 cameraAtOffset += part.OffsetPosition;
2901 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
2902 cameraEyeOffset += part.OffsetPosition;
2903 }
2904 }
2905
2906
2407 ControllingClient.SendSitResponse( 2907 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2908 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2909
2410 m_requestedSitTargetUUID = targetID; 2910 m_requestedSitTargetUUID = part.UUID;
2411 2911
2412 HandleAgentSit(ControllingClient, UUID); 2912 HandleAgentSit(ControllingClient, UUID);
2413 2913
@@ -2435,7 +2935,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2935 if (part != null)
2436 { 2936 {
2437 m_requestedSitTargetID = part.LocalId; 2937 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2938 m_requestedSitTargetUUID = part.UUID;
2439 2939
2440 } 2940 }
2441 else 2941 else
@@ -2522,6 +3022,7 @@ namespace OpenSim.Region.Framework.Scenes
2522 ResetMoveToTarget(); 3022 ResetMoveToTarget();
2523 3023
2524 Velocity = Vector3.Zero; 3024 Velocity = Vector3.Zero;
3025 m_AngularVelocity = Vector3.Zero;
2525 3026
2526 part.AddSittingAvatar(UUID); 3027 part.AddSittingAvatar(UUID);
2527 3028
@@ -2529,24 +3030,55 @@ namespace OpenSim.Region.Framework.Scenes
2529 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3030 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2530 bool forceMouselook = part.GetForceMouselook(); 3031 bool forceMouselook = part.GetForceMouselook();
2531 3032
2532 ControllingClient.SendSitResponse( 3033 m_bodyRot = Orientation;
2533 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2534 3034
2535 // not using autopilot 3035 if (!part.IsRoot)
3036 {
3037 Orientation = part.RotationOffset * Orientation;
3038 offset = offset * part.RotationOffset;
3039 offset += part.OffsetPosition;
3040
3041 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3042 {
3043 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3044 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3045 }
3046 else
3047 {
3048 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3049 cameraAtOffset += part.OffsetPosition;
3050 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3051 cameraEyeOffset += part.OffsetPosition;
3052 }
3053
3054 }
2536 3055
2537 Rotation = Orientation;
2538 m_pos = offset; 3056 m_pos = offset;
2539 3057
3058 ControllingClient.SendSitResponse(
3059 part.ParentGroup.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
3060
3061
2540 m_requestedSitTargetID = 0; 3062 m_requestedSitTargetID = 0;
2541 part.ParentGroup.AddAvatar(UUID); 3063 part.ParentGroup.AddAvatar(UUID);
2542 3064
2543 ParentPart = part; 3065 ParentPart = part;
2544 ParentID = part.LocalId; 3066 ParentID = part.LocalId;
3067
3068 SendAvatarDataToAllAgents();
3069
3070/*
2545 if(status == 3) 3071 if(status == 3)
2546 Animator.TrySetMovementAnimation("SIT_GROUND"); 3072 Animator.TrySetMovementAnimation("SIT_GROUND");
2547 else 3073 else
2548 Animator.TrySetMovementAnimation("SIT"); 3074 Animator.TrySetMovementAnimation("SIT");
2549 SendAvatarDataToAllAgents(); 3075*/
3076 if (status == 3)
3077 sitAnimation = "SIT_GROUND";
3078 else
3079 sitAnimation = "SIT";
3080
3081 Animator.SetMovementAnimations("SIT");
2550 3082
2551 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3083 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2552 } 3084 }
@@ -2554,6 +3086,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 3086
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 3087 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 3088 {
3089 if (IsChildAgent)
3090 return;
3091
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3092 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 3093
2559 if (part != null) 3094 if (part != null)
@@ -2603,47 +3138,74 @@ namespace OpenSim.Region.Framework.Scenes
2603 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3138 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2604 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 3139 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2605 3140
2606 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 3141 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3142 Quaternion newRot;
3143
3144 if (part.IsRoot)
3145 {
3146 newRot = sitTargetOrient;
3147 }
3148 else
3149 {
3150 newPos = newPos * part.RotationOffset;
3151 newRot = part.RotationOffset * sitTargetOrient;
3152 }
3153
3154 newPos += part.OffsetPosition;
3155
3156 m_pos = newPos;
3157 Rotation = newRot;
2607 3158
2608// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2609 Rotation = sitTargetOrient;
2610// ParentPosition = part.AbsolutePosition; 3159// ParentPosition = part.AbsolutePosition;
2611 part.ParentGroup.AddAvatar(UUID);
2612 } 3160 }
2613 else 3161 else
2614 { 3162 {
2615 m_pos -= part.AbsolutePosition; 3163 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
3164 // being sat upon.
3165 m_pos -= part.GroupPosition;
3166
2616// ParentPosition = part.AbsolutePosition; 3167// ParentPosition = part.AbsolutePosition;
2617 part.ParentGroup.AddAvatar(UUID);
2618 3168
2619// m_log.DebugFormat( 3169// m_log.DebugFormat(
2620// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 3170// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2621// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3171// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2622 } 3172 }
2623 3173
3174 part.ParentGroup.AddAvatar(UUID);
2624 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3175 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2625 ParentID = m_requestedSitTargetID; 3176 ParentID = m_requestedSitTargetID;
2626 m_AngularVelocity = Vector3.Zero; 3177 m_AngularVelocity = Vector3.Zero;
2627 Velocity = Vector3.Zero; 3178 Velocity = Vector3.Zero;
2628 RemoveFromPhysicalScene(); 3179 RemoveFromPhysicalScene();
2629 3180
2630 String sitAnimation = "SIT"; 3181 SendAvatarDataToAllAgents();
3182
3183 sitAnimation = "SIT";
2631 if (!String.IsNullOrEmpty(part.SitAnimation)) 3184 if (!String.IsNullOrEmpty(part.SitAnimation))
2632 { 3185 {
2633 sitAnimation = part.SitAnimation; 3186 sitAnimation = part.SitAnimation;
2634 } 3187 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 3188// Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 3189 Animator.SetMovementAnimations("SIT");
3190 TriggerScenePresenceUpdated();
2637 } 3191 }
2638 } 3192 }
2639 3193
2640 public void HandleAgentSitOnGround() 3194 public void HandleAgentSitOnGround()
2641 { 3195 {
3196 if (IsChildAgent)
3197 return;
3198
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3199// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 3200 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3201 sitAnimation = "SIT_GROUND_CONSTRAINED";
3202// Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3203// TriggerScenePresenceUpdated();
2645 SitGround = true; 3204 SitGround = true;
2646 RemoveFromPhysicalScene(); 3205 RemoveFromPhysicalScene();
3206
3207 Animator.SetMovementAnimations("SITGROUND");
3208 TriggerScenePresenceUpdated();
2647 } 3209 }
2648 3210
2649 /// <summary> 3211 /// <summary>
@@ -2658,11 +3220,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 3220 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 3221 {
2660 Animator.AddAnimation(animID, UUID.Zero); 3222 Animator.AddAnimation(animID, UUID.Zero);
3223 TriggerScenePresenceUpdated();
2661 } 3224 }
2662 3225
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 3226 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 3227 {
2665 Animator.RemoveAnimation(animID, false); 3228 Animator.RemoveAnimation(animID, false);
3229 TriggerScenePresenceUpdated();
2666 } 3230 }
2667 3231
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 3232 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2676,67 +3240,57 @@ namespace OpenSim.Region.Framework.Scenes
2676 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3240 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2677 /// </summary> 3241 /// </summary>
2678 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3242 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2679 public void AddNewMovement(Vector3 vec) 3243 /// <param name="thisAddSpeedModifier">
3244 /// Optional additional speed modifier for this particular add. Default is 1</param>
3245 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
2680 { 3246 {
2681// m_log.DebugFormat( 3247 // m_log.DebugFormat(
2682// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3248 // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3249 // vec, Rotation, thisAddSpeedModifier, Name);
2683 3250
3251 // rotate from avatar coord space to world
3252 // for now all controls assume this is only a rotation around Z
3253 // if not all checks below need to be done before this rotation
2684 Vector3 direc = vec * Rotation; 3254 Vector3 direc = vec * Rotation;
2685 direc.Normalize(); 3255 direc.Normalize();
2686 3256
2687 if (Flying != FlyingOld) // add for fly velocity control 3257 // mouse look situation ?
2688 {
2689 FlyingOld = Flying; // add for fly velocity control
2690 if (!Flying)
2691 WasFlying = true; // add for fly velocity control
2692 }
2693
2694 if (IsColliding)
2695 WasFlying = false; // add for fly velocity control
2696
2697 if ((vec.Z == 0f) && !Flying) 3258 if ((vec.Z == 0f) && !Flying)
2698 direc.Z = 0f; // Prevent camera WASD up. 3259 direc.Z = 0f; // Prevent camera WASD up.
2699 3260
2700 direc *= 0.03f * 128f * SpeedModifier; 3261 // odd rescalings
3262 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2701 3263
2702// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3264 // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2703 3265
2704 if (PhysicsActor != null) 3266 if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2705 { 3267 {
2706 if (Flying) 3268 if (breaking)
2707 { 3269 direc.Z = -9999f; //hack to tell physics to stop on Z
3270 else
3271 direc = Vector3.Zero;
3272 }
3273 else if (Flying)
3274 {
3275 if (IsColliding && direc.Z < 0)
3276 // landing situation, prevent avatar moving or it may fail to land
3277 // animator will handle this condition and do the land
3278 direc = Vector3.Zero;
3279 else
2708 direc *= 4.0f; 3280 direc *= 4.0f;
2709 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 3281 }
2710 //if (controlland) 3282 else if (IsColliding)
2711 // m_log.Info("[AGENT]: landCommand"); 3283 {
2712 //if (IsColliding) 3284 if (direc.Z > 2.0f) // reinforce jumps
2713 // m_log.Info("[AGENT]: colliding");
2714 //if (Flying && IsColliding && controlland)
2715 //{
2716 // StopFlying();
2717 // m_log.Info("[AGENT]: Stop Flying");
2718 //}
2719 }
2720 if (Animator.Falling && WasFlying) // if falling from flying, disable motion add
2721 {
2722 direc *= 0.0f;
2723 }
2724 else if (!Flying && IsColliding)
2725 { 3285 {
2726 if (direc.Z > 2.0f) 3286 direc.Z *= 2.6f;
2727 {
2728 direc.Z *= 2.6f;
2729
2730 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2731// Animator.TrySetMovementAnimation("PREJUMP");
2732// Animator.TrySetMovementAnimation("JUMP");
2733 }
2734 } 3287 }
3288 else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3289 direc.Z = 0;
2735 } 3290 }
2736 3291
2737// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); 3292 // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
2738 3293
2739 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2740 m_forceToApply = direc; 3294 m_forceToApply = direc;
2741 Animator.UpdateMovementAnimations(); 3295 Animator.UpdateMovementAnimations();
2742 } 3296 }
@@ -2753,6 +3307,11 @@ namespace OpenSim.Region.Framework.Scenes
2753 3307
2754 if (IsChildAgent == false) 3308 if (IsChildAgent == false)
2755 { 3309 {
3310 CheckForBorderCrossing();
3311
3312 if (IsInTransit)
3313 return;
3314
2756 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3315 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
2757 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3316 // grab the latest PhysicsActor velocity, whereas m_velocity is often
2758 // storing a requested force instead of an actual traveling velocity 3317 // storing a requested force instead of an actual traveling velocity
@@ -2771,8 +3330,6 @@ namespace OpenSim.Region.Framework.Scenes
2771 m_lastVelocity = Velocity; 3330 m_lastVelocity = Velocity;
2772 } 3331 }
2773 3332
2774 CheckForBorderCrossing();
2775
2776 CheckForSignificantMovement(); // sends update to the modules. 3333 CheckForSignificantMovement(); // sends update to the modules.
2777 } 3334 }
2778 } 3335 }
@@ -2781,9 +3338,38 @@ namespace OpenSim.Region.Framework.Scenes
2781 3338
2782 #region Update Client(s) 3339 #region Update Client(s)
2783 3340
3341 public void SendUpdateToAgent(ScenePresence p)
3342 {
3343 IClientAPI remoteClient = p.ControllingClient;
3344
3345 if (remoteClient.IsActive)
3346 {
3347 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3348 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3349 m_scene.StatsReporter.AddAgentUpdates(1);
3350 }
3351 }
3352
3353 public void SendFullUpdateToClient(IClientAPI remoteClient)
3354 {
3355 if (remoteClient.IsActive)
3356 {
3357 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3358 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3359 m_scene.StatsReporter.AddAgentUpdates(1);
3360 }
3361 }
3362
3363 // this is diferente from SendTerseUpdateToClient
3364 // this sends bypassing entities updates
3365 public void SendAgentTerseUpdate(ISceneEntity p)
3366 {
3367 ControllingClient.SendAgentTerseUpdate(p);
3368 }
2784 3369
2785 /// <summary> 3370 /// <summary>
2786 /// Sends a location update to the client connected to this scenePresence 3371 /// Sends a location update to the client connected to this scenePresence
3372 /// via entity updates
2787 /// </summary> 3373 /// </summary>
2788 /// <param name="remoteClient"></param> 3374 /// <param name="remoteClient"></param>
2789 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3375 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -2793,7 +3379,6 @@ namespace OpenSim.Region.Framework.Scenes
2793 if (remoteClient.IsActive) 3379 if (remoteClient.IsActive)
2794 { 3380 {
2795 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3381 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
2796
2797 remoteClient.SendEntityUpdate( 3382 remoteClient.SendEntityUpdate(
2798 this, 3383 this,
2799 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3384 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -2803,6 +3388,38 @@ namespace OpenSim.Region.Framework.Scenes
2803 } 3388 }
2804 } 3389 }
2805 3390
3391 public void SendTerseUpdateToAgent(ScenePresence p)
3392 {
3393 IClientAPI remoteClient = p.ControllingClient;
3394
3395 if (!remoteClient.IsActive)
3396 return;
3397
3398 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3399 return;
3400
3401 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3402 remoteClient.SendEntityUpdate(
3403 this,
3404 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3405 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3406
3407 m_scene.StatsReporter.AddAgentUpdates(1);
3408 }
3409
3410 public void SendTerseUpdateToAgentNF(ScenePresence p)
3411 {
3412 IClientAPI remoteClient = p.ControllingClient;
3413 if (remoteClient.IsActive)
3414 {
3415 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3416 remoteClient.SendEntityUpdate(this,
3417 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3418 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3419 m_scene.StatsReporter.AddAgentUpdates(1);
3420 }
3421 }
3422
2806 3423
2807 // vars to support reduced update frequency when velocity is unchanged 3424 // vars to support reduced update frequency when velocity is unchanged
2808 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3425 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -2843,7 +3460,9 @@ namespace OpenSim.Region.Framework.Scenes
2843 lastTerseUpdateToAllClientsTick = currentTick; 3460 lastTerseUpdateToAllClientsTick = currentTick;
2844 lastPositionSentToAllClients = OffsetPosition; 3461 lastPositionSentToAllClients = OffsetPosition;
2845 3462
2846 m_scene.ForEachClient(SendTerseUpdateToClient); 3463// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3464// m_scene.ForEachClient(SendTerseUpdateToClient);
3465 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
2847 } 3466 }
2848 TriggerScenePresenceUpdated(); 3467 TriggerScenePresenceUpdated();
2849 } 3468 }
@@ -2876,13 +3495,20 @@ namespace OpenSim.Region.Framework.Scenes
2876 // we created a new ScenePresence (a new child agent) in a fresh region. 3495 // we created a new ScenePresence (a new child agent) in a fresh region.
2877 // Request info about all the (root) agents in this region 3496 // Request info about all the (root) agents in this region
2878 // Note: This won't send data *to* other clients in that region (children don't send) 3497 // Note: This won't send data *to* other clients in that region (children don't send)
2879 SendOtherAgentsAvatarDataToMe(); 3498 if (m_teleportFlags <= 0)
2880 SendOtherAgentsAppearanceToMe(); 3499 {
3500 ILandChannel landch = m_scene.LandChannel;
3501 if (landch != null)
3502 {
3503 landch.sendClientInitialLandInfo(ControllingClient);
3504 }
3505 }
2881 3506
3507 SendOtherAgentsAvatarFullToMe();
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3508 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3509 foreach (EntityBase e in entities)
2884 { 3510 {
2885 if (e != null && e is SceneObjectGroup) 3511 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3512 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3513 }
2888 }); 3514 });
@@ -2892,6 +3518,8 @@ namespace OpenSim.Region.Framework.Scenes
2892 /// Do everything required once a client completes its movement into a region and becomes 3518 /// Do everything required once a client completes its movement into a region and becomes
2893 /// a root agent. 3519 /// a root agent.
2894 /// </summary> 3520 /// </summary>
3521 ///
3522/* only called from on place, do done inline there
2895 private void ValidateAndSendAppearanceAndAgentData() 3523 private void ValidateAndSendAppearanceAndAgentData()
2896 { 3524 {
2897 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); 3525 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
@@ -2905,32 +3533,63 @@ namespace OpenSim.Region.Framework.Scenes
2905 // to see if all the baked textures are already here. 3533 // to see if all the baked textures are already here.
2906 if (m_scene.AvatarFactory != null) 3534 if (m_scene.AvatarFactory != null)
2907 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); 3535 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
2908 3536
2909 // If we aren't using a cached appearance, then clear out the baked textures 3537 // If we aren't using a cached appearance, then clear out the baked textures
2910 if (!cachedappearance) 3538 if (!cachedappearance)
2911 { 3539 {
2912 Appearance.ResetAppearance();
2913 if (m_scene.AvatarFactory != null) 3540 if (m_scene.AvatarFactory != null)
2914 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3541 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
2915 } 3542 }
2916 3543
2917 // This agent just became root. We are going to tell everyone about it. The process of 3544 // send avatar object to all viewers so they cross it into region
2918 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it 3545 bool newhide = m_currentParcelHide;
2919 // again here... this comes after the cached appearance check because the avatars 3546 m_currentParcelHide = false;
2920 // appearance goes into the avatar update packet 3547
2921 SendAvatarDataToAllAgents(); 3548 SendAvatarDataToAllAgents();
3549
3550 // now hide
3551 if (newhide)
3552 {
3553 ParcelLoginCheck(m_currentParcelUUID);
3554 m_currentParcelHide = true;
3555 }
3556
2922 SendAppearanceToAgent(this); 3557 SendAppearanceToAgent(this);
2923 3558
2924 // If we are using the the cached appearance then send it out to everyone 3559 m_inTransit = false;
2925 if (cachedappearance) 3560
3561 SendAppearanceToAllOtherAgents();
3562
3563 if(Animator!= null)
3564 Animator.SendAnimPack();
3565 }
3566*/
3567 /// <summary>
3568 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3569 /// can be either a child or root
3570 /// </summary>
3571 public void SendOtherAgentsAvatarFullToMe()
3572 {
3573 int count = 0;
3574 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
2926 { 3575 {
2927 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3576 // only send information about other root agents
3577 if (p.UUID == UUID)
3578 return;
2928 3579
2929 // If the avatars baked textures are all in the cache, then we have a 3580 // get the avatar, then a kill if can't see it
2930 // complete appearance... send it out, if not, then we'll send it when 3581 p.SendInitialAvatarDataToAgent(this);
2931 // the avatar finishes updating its appearance 3582
2932 SendAppearanceToAllOtherAgents(); 3583 if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200)
2933 } 3584 return;
3585
3586 p.SendAppearanceToAgentNF(this);
3587 p.SendAnimPackToAgentNF(this);
3588 p.SendAttachmentsToAgentNF(this);
3589 count++;
3590 });
3591
3592 m_scene.StatsReporter.AddAgentUpdates(count);
2934 } 3593 }
2935 3594
2936 /// <summary> 3595 /// <summary>
@@ -2946,42 +3605,51 @@ namespace OpenSim.Region.Framework.Scenes
2946 m_log.WarnFormat( 3605 m_log.WarnFormat(
2947 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", 3606 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
2948 Name, Scene.RegionInfo.RegionName); 3607 Name, Scene.RegionInfo.RegionName);
2949
2950 return; 3608 return;
2951 } 3609 }
2952 3610
2953 m_lastSize = Appearance.AvatarSize; 3611 m_lastSize = Appearance.AvatarSize;
2954
2955 int count = 0; 3612 int count = 0;
3613
2956 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3614 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2957 { 3615 {
2958 SendAvatarDataToAgent(scenePresence); 3616 SendAvatarDataToAgent(scenePresence);
2959 count++; 3617 count++;
2960 }); 3618 });
2961 3619
2962 m_scene.StatsReporter.AddAgentUpdates(count); 3620 m_scene.StatsReporter.AddAgentUpdates(count);
2963 } 3621 }
2964 3622
2965 /// <summary> 3623 // sends avatar object to all clients so they cross it into region
2966 /// Send avatar data for all other root agents to this agent, this agent 3624 // then sends kills to hide
2967 /// can be either a child or root 3625 public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
2968 /// </summary>
2969 public void SendOtherAgentsAvatarDataToMe()
2970 { 3626 {
3627 m_lastSize = Appearance.AvatarSize;
2971 int count = 0; 3628 int count = 0;
2972 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
2973 {
2974 // only send information about other root agents
2975 if (scenePresence.UUID == UUID)
2976 return;
2977
2978 scenePresence.SendAvatarDataToAgent(this);
2979 count++;
2980 });
2981 3629
3630 foreach (ScenePresence p in presences)
3631 {
3632 p.ControllingClient.SendAvatarDataImmediate(this);
3633 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3634 // either just kill the object
3635 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3636 // or also attachments viewer may still know about
3637 SendKillTo(p);
3638 count++;
3639 }
2982 m_scene.StatsReporter.AddAgentUpdates(count); 3640 m_scene.StatsReporter.AddAgentUpdates(count);
2983 } 3641 }
2984 3642
3643 public void SendInitialAvatarDataToAgent(ScenePresence p)
3644 {
3645 p.ControllingClient.SendAvatarDataImmediate(this);
3646 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3647 // either just kill the object
3648 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3649 // or also attachments viewer may still know about
3650 SendKillTo(p);
3651 }
3652
2985 /// <summary> 3653 /// <summary>
2986 /// Send avatar data to an agent. 3654 /// Send avatar data to an agent.
2987 /// </summary> 3655 /// </summary>
@@ -2989,18 +3657,23 @@ namespace OpenSim.Region.Framework.Scenes
2989 public void SendAvatarDataToAgent(ScenePresence avatar) 3657 public void SendAvatarDataToAgent(ScenePresence avatar)
2990 { 3658 {
2991 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3659 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2992 3660 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3661 return;
2993 avatar.ControllingClient.SendAvatarDataImmediate(this); 3662 avatar.ControllingClient.SendAvatarDataImmediate(this);
2994 Animator.SendAnimPackToClient(avatar.ControllingClient);
2995 } 3663 }
2996 3664
3665 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3666 {
3667 avatar.ControllingClient.SendAvatarDataImmediate(this);
3668 }
3669
2997 /// <summary> 3670 /// <summary>
2998 /// Send this agent's appearance to all other root and child agents in the scene 3671 /// Send this agent's appearance to all other root and child agents in the scene
2999 /// This agent must be root. 3672 /// This agent must be root.
3000 /// </summary> 3673 /// </summary>
3001 public void SendAppearanceToAllOtherAgents() 3674 public void SendAppearanceToAllOtherAgents()
3002 { 3675 {
3003// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); 3676 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3004 3677
3005 // only send update from root agents to other clients; children are only "listening posts" 3678 // only send update from root agents to other clients; children are only "listening posts"
3006 if (IsChildAgent) 3679 if (IsChildAgent)
@@ -3011,7 +3684,7 @@ namespace OpenSim.Region.Framework.Scenes
3011 3684
3012 return; 3685 return;
3013 } 3686 }
3014 3687
3015 int count = 0; 3688 int count = 0;
3016 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3689 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3017 { 3690 {
@@ -3022,29 +3695,6 @@ namespace OpenSim.Region.Framework.Scenes
3022 SendAppearanceToAgent(scenePresence); 3695 SendAppearanceToAgent(scenePresence);
3023 count++; 3696 count++;
3024 }); 3697 });
3025
3026 m_scene.StatsReporter.AddAgentUpdates(count);
3027 }
3028
3029 /// <summary>
3030 /// Send appearance from all other root agents to this agent. this agent
3031 /// can be either root or child
3032 /// </summary>
3033 public void SendOtherAgentsAppearanceToMe()
3034 {
3035// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID);
3036
3037 int count = 0;
3038 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
3039 {
3040 // only send information about other root agents
3041 if (scenePresence.UUID == UUID)
3042 return;
3043
3044 scenePresence.SendAppearanceToAgent(this);
3045 count++;
3046 });
3047
3048 m_scene.StatsReporter.AddAgentUpdates(count); 3698 m_scene.StatsReporter.AddAgentUpdates(count);
3049 } 3699 }
3050 3700
@@ -3056,11 +3706,63 @@ namespace OpenSim.Region.Framework.Scenes
3056 { 3706 {
3057// m_log.DebugFormat( 3707// m_log.DebugFormat(
3058// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3708// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3709 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3710 return;
3711 avatar.ControllingClient.SendAppearance(
3712 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3713 }
3059 3714
3715 public void SendAppearanceToAgentNF(ScenePresence avatar)
3716 {
3060 avatar.ControllingClient.SendAppearance( 3717 avatar.ControllingClient.SendAppearance(
3061 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3718 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3719 }
3062 3720
3063 3721 public void SendAnimPackToAgent(ScenePresence p)
3722 {
3723 if (IsChildAgent || Animator == null)
3724 return;
3725
3726 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3727 return;
3728
3729 Animator.SendAnimPackToClient(p.ControllingClient);
3730 }
3731
3732 public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3733 {
3734 if (IsChildAgent)
3735 return;
3736
3737 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3738 return;
3739
3740 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3741 }
3742
3743 public void SendAnimPackToAgentNF(ScenePresence p)
3744 {
3745 if (IsChildAgent || Animator == null)
3746 return;
3747 Animator.SendAnimPackToClient(p.ControllingClient);
3748 }
3749
3750 public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3751 {
3752 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3753 }
3754
3755 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3756 {
3757 if (IsChildAgent)
3758 return;
3759
3760 m_scene.ForEachScenePresence(delegate(ScenePresence p)
3761 {
3762 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3763 return;
3764 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3765 });
3064 } 3766 }
3065 3767
3066 #endregion 3768 #endregion
@@ -3079,12 +3781,12 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3781 }
3080 3782
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3783 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3784 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3785 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3786 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3787// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3788
3789/* cadu is not used
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3790 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3791 cadu.ActiveGroupID = UUID.Zero.Guid;
3090 cadu.AgentID = UUID.Guid; 3792 cadu.AgentID = UUID.Guid;
@@ -3098,6 +3800,7 @@ namespace OpenSim.Region.Framework.Scenes
3098 3800
3099 // Throttles 3801 // Throttles
3100 float multiplier = 1; 3802 float multiplier = 1;
3803
3101 int childRegions = KnownRegionCount; 3804 int childRegions = KnownRegionCount;
3102 if (childRegions != 0) 3805 if (childRegions != 0)
3103 multiplier = 1f / childRegions; 3806 multiplier = 1f / childRegions;
@@ -3108,9 +3811,22 @@ namespace OpenSim.Region.Framework.Scenes
3108 3811
3109 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); 3812 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
3110 cadu.Velocity = Velocity; 3813 cadu.Velocity = Velocity;
3111 3814*/
3112 AgentPosition agentpos = new AgentPosition(); 3815 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3816// agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3817
3818 agentpos.AgentID = new UUID(UUID.Guid);
3819 agentpos.SessionID = ControllingClient.SessionId;
3820
3821 agentpos.Size = Appearance.AvatarSize;
3822
3823 agentpos.Center = CameraPosition;
3824 agentpos.Far = DrawDistance;
3825 agentpos.Position = AbsolutePosition;
3826 agentpos.Velocity = Velocity;
3827 agentpos.RegionHandle = RegionHandle;
3828 agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
3829
3114 3830
3115 // Let's get this out of the update loop 3831 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3832 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3130,7 +3846,7 @@ namespace OpenSim.Region.Framework.Scenes
3130 protected void CheckForBorderCrossing() 3846 protected void CheckForBorderCrossing()
3131 { 3847 {
3132 // Check that we we are not a child 3848 // Check that we we are not a child
3133 if (IsChildAgent) 3849 if (IsChildAgent || IsInTransit)
3134 return; 3850 return;
3135 3851
3136 // If we don't have a PhysActor, we can't cross anyway 3852 // If we don't have a PhysActor, we can't cross anyway
@@ -3140,140 +3856,72 @@ namespace OpenSim.Region.Framework.Scenes
3140 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3856 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3141 return; 3857 return;
3142 3858
3143 if (!IsInTransit) 3859 Vector3 pos2 = AbsolutePosition;
3144 { 3860 Vector3 vel = Velocity;
3145 Vector3 pos2 = AbsolutePosition;
3146 Vector3 vel = Velocity;
3147 int neighbor = 0;
3148 int[] fix = new int[2];
3149 3861
3150 float timeStep = 0.1f; 3862 float timeStep = 0.1f;
3151 pos2.X = pos2.X + (vel.X * timeStep); 3863 pos2.X += vel.X * timeStep;
3152 pos2.Y = pos2.Y + (vel.Y * timeStep); 3864 pos2.Y += vel.Y * timeStep;
3153 pos2.Z = pos2.Z + (vel.Z * timeStep); 3865 pos2.Z += vel.Z * timeStep;
3154 3866
3155 if (!IsInTransit)
3156 {
3157// m_log.DebugFormat( 3867// m_log.DebugFormat(
3158// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", 3868// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3159// pos2, Name, Scene.Name); 3869// pos2, Name, Scene.Name);
3160 3870
3161 // Checks if where it's headed exists a region 3871 if( Scene.TestBorderCross(pos2, Cardinals.E) ||
3162 bool needsTransit = false; 3872 Scene.TestBorderCross(pos2, Cardinals.W) ||
3163 if (m_scene.TestBorderCross(pos2, Cardinals.W)) 3873 Scene.TestBorderCross(pos2, Cardinals.N) ||
3164 { 3874 Scene.TestBorderCross(pos2, Cardinals.S)
3165 if (m_scene.TestBorderCross(pos2, Cardinals.S)) 3875 )
3166 { 3876 {
3167 needsTransit = true; 3877 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3168 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3169 }
3170 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3171 {
3172 needsTransit = true;
3173 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3174 }
3175 else
3176 {
3177 needsTransit = true;
3178 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3179 }
3180 }
3181 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3182 {
3183 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3184 {
3185 needsTransit = true;
3186 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3187 }
3188 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3189 {
3190 needsTransit = true;
3191 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3192 }
3193 else
3194 {
3195 needsTransit = true;
3196 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3197 }
3198 }
3199 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3200 {
3201 needsTransit = true;
3202 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3203 }
3204 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3205 {
3206 needsTransit = true;
3207 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3208 }
3209
3210 // Makes sure avatar does not end up outside region
3211 if (neighbor <= 0)
3212 {
3213 if (needsTransit)
3214 {
3215 if (m_requestedSitTargetUUID == UUID.Zero)
3216 {
3217 bool isFlying = Flying;
3218 RemoveFromPhysicalScene();
3219
3220 Vector3 pos = AbsolutePosition;
3221 if (AbsolutePosition.X < 0)
3222 pos.X += Velocity.X * 2;
3223 else if (AbsolutePosition.X > Constants.RegionSize)
3224 pos.X -= Velocity.X * 2;
3225 if (AbsolutePosition.Y < 0)
3226 pos.Y += Velocity.Y * 2;
3227 else if (AbsolutePosition.Y > Constants.RegionSize)
3228 pos.Y -= Velocity.Y * 2;
3229 Velocity = Vector3.Zero;
3230 AbsolutePosition = pos;
3231
3232// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3233
3234 AddToPhysicalScene(isFlying);
3235 }
3236 }
3237 }
3238 else if (neighbor > 0)
3239 {
3240 if (!CrossToNewRegion())
3241 {
3242 if (m_requestedSitTargetUUID == UUID.Zero)
3243 {
3244 bool isFlying = Flying;
3245 RemoveFromPhysicalScene();
3246
3247 Vector3 pos = AbsolutePosition;
3248 if (AbsolutePosition.X < 0)
3249 pos.X += Velocity.X * 2;
3250 else if (AbsolutePosition.X > Constants.RegionSize)
3251 pos.X -= Velocity.X * 2;
3252 if (AbsolutePosition.Y < 0)
3253 pos.Y += Velocity.Y * 2;
3254 else if (AbsolutePosition.Y > Constants.RegionSize)
3255 pos.Y -= Velocity.Y * 2;
3256 Velocity = Vector3.Zero;
3257 AbsolutePosition = pos;
3258
3259 AddToPhysicalScene(isFlying);
3260 }
3261 }
3262 }
3263 }
3264 else
3265 { 3878 {
3266 // This constant has been inferred from experimentation 3879 // we don't have entity transfer module
3267 // I'm not sure what this value should be, so I tried a few values. 3880 Vector3 pos = AbsolutePosition;
3268 timeStep = 0.04f; 3881 float px = pos.X;
3269 pos2 = AbsolutePosition; 3882 if (px < 0)
3270 pos2.X = pos2.X + (vel.X * timeStep); 3883 pos.X += Velocity.X * 2;
3271 pos2.Y = pos2.Y + (vel.Y * timeStep); 3884 else if (px > m_scene.RegionInfo.RegionSizeX)
3272 // Don't touch the Z 3885 pos.X -= Velocity.X * 2;
3273 m_pos = pos2; 3886
3274 m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos); 3887 float py = pos.Y;
3888 if (py < 0)
3889 pos.Y += Velocity.Y * 2;
3890 else if (py > m_scene.RegionInfo.RegionSizeY)
3891 pos.Y -= Velocity.Y * 2;
3892
3893 Velocity = Vector3.Zero;
3894 AbsolutePosition = pos;
3275 } 3895 }
3276 } 3896 }
3897 }
3898
3899 public void CrossToNewRegionFail()
3900 {
3901 if (m_requestedSitTargetUUID == UUID.Zero)
3902 {
3903 bool isFlying = Flying;
3904 RemoveFromPhysicalScene();
3905
3906 Vector3 pos = AbsolutePosition;
3907 float px = pos.X;
3908 if (px < 0)
3909 pos.X += Velocity.X * 2;
3910 else if (px > m_scene.RegionInfo.RegionSizeX)
3911 pos.X -= Velocity.X * 2;
3912
3913 float py = pos.Y;
3914 if (py < 0)
3915 pos.Y += Velocity.Y * 2;
3916 else if (py > m_scene.RegionInfo.RegionSizeY)
3917 pos.Y -= Velocity.Y * 2;
3918
3919 Velocity = Vector3.Zero;
3920 AbsolutePosition = pos;
3921
3922 AddToPhysicalScene(isFlying);
3923 }
3924
3277 } 3925 }
3278 3926
3279 /// <summary> 3927 /// <summary>
@@ -3284,21 +3932,25 @@ namespace OpenSim.Region.Framework.Scenes
3284 /// </summary> 3932 /// </summary>
3285 protected bool CrossToNewRegion() 3933 protected bool CrossToNewRegion()
3286 { 3934 {
3935 bool result = false;
3936// parcelRegionCross(false);
3287 try 3937 try
3288 { 3938 {
3289 return m_scene.CrossAgentToNewRegion(this, Flying); 3939 result = m_scene.CrossAgentToNewRegion(this, Flying);
3290 } 3940 }
3291 catch 3941 catch
3292 { 3942 {
3293 return m_scene.CrossAgentToNewRegion(this, false); 3943// result = m_scene.CrossAgentToNewRegion(this, false);
3944 return false;
3294 } 3945 }
3295 } 3946 // if(!result)
3947 // parcelRegionCross(true);
3948
3949 return result;
3296 3950
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 } 3951 }
3301 3952
3953/* useless. Either use MakeChild or delete the presence
3302 public void Reset() 3954 public void Reset()
3303 { 3955 {
3304// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3956// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3309,7 +3961,7 @@ namespace OpenSim.Region.Framework.Scenes
3309 3961
3310 Animator.ResetAnimations(); 3962 Animator.ResetAnimations();
3311 } 3963 }
3312 3964*/
3313 /// <summary> 3965 /// <summary>
3314 /// Computes which child agents to close when the scene presence moves to another region. 3966 /// Computes which child agents to close when the scene presence moves to another region.
3315 /// Removes those regions from m_knownRegions. 3967 /// Removes those regions from m_knownRegions.
@@ -3348,10 +4000,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 4000 if (byebyeRegions.Count > 0)
3349 { 4001 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 4002 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 4003
3352 { 4004 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 4005 string auth = string.Empty;
3354 }); 4006 if (acd != null)
4007 auth = acd.SessionID.ToString();
4008 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 4009 }
3356 4010
3357 foreach (ulong handle in byebyeRegions) 4011 foreach (ulong handle in byebyeRegions)
@@ -3368,6 +4022,8 @@ namespace OpenSim.Region.Framework.Scenes
3368 /// </summary> 4022 /// </summary>
3369 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 4023 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3370 { 4024 {
4025 int oldgodlevel = GodLevel;
4026
3371 if (godStatus) 4027 if (godStatus)
3372 { 4028 {
3373 // For now, assign god level 200 to anyone 4029 // For now, assign god level 200 to anyone
@@ -3388,11 +4044,14 @@ namespace OpenSim.Region.Framework.Scenes
3388 } 4044 }
3389 4045
3390 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4046 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4047
4048 if(oldgodlevel != GodLevel)
4049 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3391 } 4050 }
3392 4051
3393 #region Child Agent Updates 4052 #region Child Agent Updates
3394 4053
3395 public void ChildAgentDataUpdate(AgentData cAgentData) 4054 public void UpdateChildAgent(AgentData cAgentData)
3396 { 4055 {
3397// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 4056// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3398 if (!IsChildAgent) 4057 if (!IsChildAgent)
@@ -3402,19 +4061,23 @@ namespace OpenSim.Region.Framework.Scenes
3402 } 4061 }
3403 4062
3404 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4063 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
4064
3405 private void RaiseUpdateThrottles() 4065 private void RaiseUpdateThrottles()
3406 { 4066 {
3407 m_scene.EventManager.TriggerThrottleUpdate(this); 4067 m_scene.EventManager.TriggerThrottleUpdate(this);
3408 } 4068 }
4069
3409 /// <summary> 4070 /// <summary>
3410 /// This updates important decision making data about a child agent 4071 /// This updates important decision making data about a child agent
3411 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 4072 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3412 /// </summary> 4073 /// </summary>
3413 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 4074 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3414 { 4075 {
3415 if (!IsChildAgent) 4076 if (!IsChildAgent)
3416 return; 4077 return;
3417 4078
4079 RegionHandle = cAgentData.RegionHandle;
4080
3418 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 4081 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3419 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 4082 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
3420 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 4083 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
@@ -3441,8 +4104,17 @@ namespace OpenSim.Region.Framework.Scenes
3441 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) 4104 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
3442 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); 4105 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
3443 4106
4107 if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4108 {
4109 if (Scene.CapsModule != null)
4110 {
4111 Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4112 }
4113
4114 KnownRegions = cAgentData.ChildrenCapSeeds;
4115 }
4116
3444 //cAgentData.AVHeight; 4117 //cAgentData.AVHeight;
3445 RegionHandle = cAgentData.RegionHandle;
3446 //m_velocity = cAgentData.Velocity; 4118 //m_velocity = cAgentData.Velocity;
3447 } 4119 }
3448 4120
@@ -3452,6 +4124,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 4124
3453 cAgent.AgentID = UUID; 4125 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 4126 cAgent.RegionID = Scene.RegionInfo.RegionID;
4127 cAgent.SessionID = ControllingClient.SessionId;
3455 4128
3456 cAgent.Position = AbsolutePosition; 4129 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 4130 cAgent.Velocity = m_velocity;
@@ -3463,16 +4136,7 @@ namespace OpenSim.Region.Framework.Scenes
3463 cAgent.Far = DrawDistance; 4136 cAgent.Far = DrawDistance;
3464 4137
3465 // Throttles 4138 // Throttles
3466 float multiplier = 1; 4139 cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
3467 int childRegions = KnownRegionCount;
3468 if (childRegions != 0)
3469 multiplier = 1f / childRegions;
3470
3471 // Minimum throttle for a child region is 1/4 of the root region throttle
3472 if (multiplier <= 0.25f)
3473 multiplier = 0.25f;
3474
3475 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
3476 4140
3477 cAgent.HeadRotation = m_headrotation; 4141 cAgent.HeadRotation = m_headrotation;
3478 cAgent.BodyRotation = Rotation; 4142 cAgent.BodyRotation = Rotation;
@@ -3485,7 +4149,8 @@ namespace OpenSim.Region.Framework.Scenes
3485 4149
3486 cAgent.AlwaysRun = SetAlwaysRun; 4150 cAgent.AlwaysRun = SetAlwaysRun;
3487 4151
3488 cAgent.Appearance = new AvatarAppearance(Appearance); 4152 // make clear we want the all thing
4153 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3489 4154
3490 cAgent.ParentPart = ParentUUID; 4155 cAgent.ParentPart = ParentUUID;
3491 cAgent.SitOffset = PrevSitOffset; 4156 cAgent.SitOffset = PrevSitOffset;
@@ -3511,13 +4176,16 @@ namespace OpenSim.Region.Framework.Scenes
3511 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 4176 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3512 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; 4177 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3513 4178
4179 cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4180
4181 cAgent.MotionState = (byte)Animator.currentControlState;
4182
3514 if (Scene.AttachmentsModule != null) 4183 if (Scene.AttachmentsModule != null)
3515 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 4184 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
3516 } 4185 }
3517 4186
3518 private void CopyFrom(AgentData cAgent) 4187 private void CopyFrom(AgentData cAgent)
3519 { 4188 {
3520 m_originRegionID = cAgent.RegionID;
3521 4189
3522 m_callbackURI = cAgent.CallbackURI; 4190 m_callbackURI = cAgent.CallbackURI;
3523// m_log.DebugFormat( 4191// m_log.DebugFormat(
@@ -3539,6 +4207,15 @@ namespace OpenSim.Region.Framework.Scenes
3539 // DrawDistance = cAgent.Far; 4207 // DrawDistance = cAgent.Far;
3540 DrawDistance = Scene.DefaultDrawDistance; 4208 DrawDistance = Scene.DefaultDrawDistance;
3541 4209
4210 if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4211 {
4212 if (Scene.CapsModule != null)
4213 {
4214 Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4215 }
4216 KnownRegions = cAgent.ChildrenCapSeeds;
4217 }
4218
3542 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4219 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
3543 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4220 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
3544 4221
@@ -3550,14 +4227,17 @@ namespace OpenSim.Region.Framework.Scenes
3550 GodLevel = cAgent.GodLevel; 4227 GodLevel = cAgent.GodLevel;
3551 SetAlwaysRun = cAgent.AlwaysRun; 4228 SetAlwaysRun = cAgent.AlwaysRun;
3552 4229
4230
3553 Appearance = new AvatarAppearance(cAgent.Appearance); 4231 Appearance = new AvatarAppearance(cAgent.Appearance);
4232/*
4233 bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4234
3554 if (PhysicsActor != null) 4235 if (PhysicsActor != null)
3555 { 4236 {
3556 bool isFlying = Flying;
3557 RemoveFromPhysicalScene(); 4237 RemoveFromPhysicalScene();
3558 AddToPhysicalScene(isFlying); 4238 AddToPhysicalScene(isFlying);
3559 } 4239 }
3560 4240*/
3561 try 4241 try
3562 { 4242 {
3563 lock (scriptedcontrols) 4243 lock (scriptedcontrols)
@@ -3581,16 +4261,26 @@ namespace OpenSim.Region.Framework.Scenes
3581 } 4261 }
3582 catch { } 4262 catch { }
3583 4263
4264 Animator.ResetAnimations();
4265
4266 Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4267
3584 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4268 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
3585 if (cAgent.Anims != null)
3586 Animator.Animations.FromArray(cAgent.Anims);
3587 if (cAgent.DefaultAnim != null) 4269 if (cAgent.DefaultAnim != null)
3588 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4270 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3589 if (cAgent.AnimState != null) 4271 if (cAgent.AnimState != null)
3590 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4272 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4273 if (cAgent.Anims != null)
4274 Animator.Animations.FromArray(cAgent.Anims);
4275 if (cAgent.MotionState != 0)
4276 Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
3591 4277
3592 if (Scene.AttachmentsModule != null) 4278 if (Scene.AttachmentsModule != null)
3593 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 4279 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4280
4281 lock (m_originRegionIDAccessLock)
4282 m_originRegionID = cAgent.RegionID;
4283
3594 } 4284 }
3595 4285
3596 public bool CopyAgent(out IAgentData agent) 4286 public bool CopyAgent(out IAgentData agent)
@@ -3607,12 +4297,12 @@ namespace OpenSim.Region.Framework.Scenes
3607 /// </summary> 4297 /// </summary>
3608 public void UpdateMovement() 4298 public void UpdateMovement()
3609 { 4299 {
4300 if (IsInTransit)
4301 return;
3610 if (m_forceToApply.HasValue) 4302 if (m_forceToApply.HasValue)
3611 { 4303 {
3612 Vector3 force = m_forceToApply.Value; 4304 Vector3 force = m_forceToApply.Value;
3613 4305
3614 Updated = true;
3615
3616 Velocity = force; 4306 Velocity = force;
3617 4307
3618 m_forceToApply = null; 4308 m_forceToApply = null;
@@ -3687,14 +4377,17 @@ namespace OpenSim.Region.Framework.Scenes
3687 { 4377 {
3688 if (IsChildAgent || Animator == null) 4378 if (IsChildAgent || Animator == null)
3689 return; 4379 return;
3690 4380
4381 if(IsInTransit)
4382 return;
3691 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4383 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3692 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( 4384 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3693 // as of this comment the interval is set in AddToPhysicalScene 4385 // as of this comment the interval is set in AddToPhysicalScene
3694 4386
3695// if (m_updateCount > 0) 4387// if (m_updateCount > 0)
3696// { 4388// {
3697 Animator.UpdateMovementAnimations(); 4389 if (Animator.UpdateMovementAnimations())
4390 TriggerScenePresenceUpdated();
3698// m_updateCount--; 4391// m_updateCount--;
3699// } 4392// }
3700 4393
@@ -3858,6 +4551,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4551// Animator.Close();
3859 Animator = null; 4552 Animator = null;
3860 4553
4554 LifecycleState = ScenePresenceState.Removed;
3861 } 4555 }
3862 4556
3863 public void AddAttachment(SceneObjectGroup gobj) 4557 public void AddAttachment(SceneObjectGroup gobj)
@@ -4033,6 +4727,287 @@ namespace OpenSim.Region.Framework.Scenes
4033 return validated; 4727 return validated;
4034 } 4728 }
4035 4729
4730 public void SendAttachmentsToAllAgents()
4731 {
4732 lock (m_attachments)
4733 {
4734 foreach (SceneObjectGroup sog in m_attachments)
4735 {
4736 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4737 {
4738 if (p != this && sog.HasPrivateAttachmentPoint)
4739 return;
4740
4741 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4742 return;
4743
4744 SendTerseUpdateToAgentNF(p);
4745 SendAttachmentFullUpdateToAgentNF(sog, p);
4746 });
4747 }
4748 }
4749 }
4750
4751 // send attachments to a client without filters except for huds
4752 // for now they are checked in several places down the line...
4753 public void SendAttachmentsToAgentNF(ScenePresence p)
4754 {
4755 SendTerseUpdateToAgentNF(p);
4756 lock (m_attachments)
4757 {
4758 foreach (SceneObjectGroup sog in m_attachments)
4759 {
4760 SendAttachmentFullUpdateToAgentNF(sog, p);
4761 }
4762 }
4763 }
4764
4765 public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
4766 {
4767 if (p != this && sog.HasPrivateAttachmentPoint)
4768 return;
4769
4770 SceneObjectPart[] parts = sog.Parts;
4771 SceneObjectPart rootpart = sog.RootPart;
4772
4773 p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
4774
4775 for (int i = 0; i < parts.Length; i++)
4776 {
4777 SceneObjectPart part = parts[i];
4778 if (part == rootpart)
4779 continue;
4780 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4781 }
4782 }
4783
4784 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
4785 {
4786 if (IsChildAgent || IsInTransit)
4787 return;
4788
4789 SceneObjectPart[] origparts = sog.Parts;
4790 SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
4791 PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
4792
4793 SceneObjectPart rootpart = sog.RootPart;
4794 UpdateRequired rootreq = sog.RootPart.UpdateFlag;
4795
4796 int j = 0;
4797 bool allterse = true;
4798 for (int i = 0; i < origparts.Length; i++)
4799 {
4800 if (origparts[i] != rootpart)
4801 {
4802 switch (origparts[i].UpdateFlag)
4803 {
4804 case UpdateRequired.NONE:
4805 break;
4806
4807 case UpdateRequired.TERSE:
4808 flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4809 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4810 parts[j] = origparts[i];
4811 j++;
4812 break;
4813
4814 case UpdateRequired.FULL:
4815 flags[j] = PrimUpdateFlags.FullUpdate;
4816 allterse = false;
4817 parts[j] = origparts[i];
4818 j++;
4819 break;
4820 }
4821 }
4822 origparts[i].UpdateFlag = 0;
4823 }
4824
4825 if (j == 0 && rootreq == UpdateRequired.NONE)
4826 return;
4827
4828 PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
4829
4830 if (rootreq != UpdateRequired.FULL && allterse)
4831 {
4832 rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4833 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4834 }
4835
4836 int nparts = j;
4837
4838 ControllingClient.SendEntityUpdate(rootpart, rootflag);
4839
4840 for (int i = 0; i < nparts; i++)
4841 {
4842 ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4843 }
4844
4845 if (sog.HasPrivateAttachmentPoint)
4846 return;
4847
4848 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4849 foreach (ScenePresence p in allPresences)
4850 {
4851 if (p == this)
4852 continue;
4853
4854 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4855 continue;
4856
4857 p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
4858
4859 for (int i = 0; i < nparts; i++)
4860 {
4861 p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4862 }
4863 }
4864 }
4865
4866 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
4867 {
4868 if (IsChildAgent || IsInTransit)
4869 return;
4870
4871 PrimUpdateFlags flag;
4872 switch (UpdateFlag)
4873 {
4874 case UpdateRequired.TERSE:
4875 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4876 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4877 break;
4878
4879 case UpdateRequired.FULL:
4880 flag = PrimUpdateFlags.FullUpdate;
4881 break;
4882
4883 default:
4884 return;
4885 }
4886
4887 SceneObjectPart[] parts = sog.Parts;
4888 SceneObjectPart rootpart = sog.RootPart;
4889
4890// rootpart.UpdateFlag = 0;
4891
4892 ControllingClient.SendEntityUpdate(rootpart, flag);
4893
4894 for (int i = 0; i < parts.Length; i++)
4895 {
4896 SceneObjectPart part = parts[i];
4897 if (part == rootpart)
4898 continue;
4899 ControllingClient.SendEntityUpdate(part, flag);
4900// part.UpdateFlag = 0;
4901 }
4902
4903 if (sog.HasPrivateAttachmentPoint)
4904 return;
4905
4906
4907 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4908 foreach (ScenePresence p in allPresences)
4909 {
4910 if (p == this)
4911 continue;
4912
4913 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4914 continue;
4915
4916 p.ControllingClient.SendEntityUpdate(rootpart, flag);
4917
4918 for (int i = 0; i < parts.Length; i++)
4919 {
4920 SceneObjectPart part = parts[i];
4921 if (part == rootpart)
4922 continue;
4923 p.ControllingClient.SendEntityUpdate(part, flag);
4924 }
4925 }
4926 }
4927
4928 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
4929 {
4930 if (IsChildAgent || IsInTransit)
4931 return;
4932
4933
4934 PrimUpdateFlags flag;
4935 switch (part.UpdateFlag)
4936 {
4937 case UpdateRequired.TERSE:
4938 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4939 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4940 break;
4941
4942 case UpdateRequired.FULL:
4943 flag = PrimUpdateFlags.FullUpdate;
4944 break;
4945
4946 default:
4947 return;
4948 }
4949
4950 part.UpdateFlag = 0;
4951
4952 ControllingClient.SendEntityUpdate(part, flag);
4953
4954 if (part.ParentGroup.HasPrivateAttachmentPoint)
4955 return;
4956
4957 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4958 foreach (ScenePresence p in allPresences)
4959 {
4960 if (p == this)
4961 continue;
4962
4963 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4964 continue;
4965
4966 p.ControllingClient.SendEntityUpdate(part, flag);
4967 }
4968 }
4969
4970
4971 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
4972 {
4973 if (IsChildAgent || IsInTransit)
4974 return;
4975
4976 PrimUpdateFlags flag;
4977 switch (UpdateFlag)
4978 {
4979 case UpdateRequired.TERSE:
4980 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4981 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4982 break;
4983
4984 case UpdateRequired.FULL:
4985 flag = PrimUpdateFlags.FullUpdate;
4986 break;
4987
4988 default:
4989 return;
4990 }
4991
4992// part.UpdateFlag = 0;
4993
4994 ControllingClient.SendEntityUpdate(part, flag);
4995
4996 if (part.ParentGroup.HasPrivateAttachmentPoint)
4997 return;
4998
4999 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5000 foreach (ScenePresence p in allPresences)
5001 {
5002 if (p == this)
5003 continue;
5004 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5005 continue;
5006
5007 p.ControllingClient.SendEntityUpdate(part, flag);
5008 }
5009 }
5010
4036 /// <summary> 5011 /// <summary>
4037 /// Send a script event to this scene presence's attachments 5012 /// Send a script event to this scene presence's attachments
4038 /// </summary> 5013 /// </summary>
@@ -4151,6 +5126,15 @@ namespace OpenSim.Region.Framework.Scenes
4151 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5126 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4152 } 5127 }
4153 5128
5129 public void ClearControls()
5130 {
5131 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5132 lock (scriptedcontrols)
5133 {
5134 scriptedcontrols.Clear();
5135 }
5136 }
5137
4154 private void UnRegisterSeatControls(UUID obj) 5138 private void UnRegisterSeatControls(UUID obj)
4155 { 5139 {
4156 List<UUID> takers = new List<UUID>(); 5140 List<UUID> takers = new List<UUID>();
@@ -4540,8 +5524,8 @@ namespace OpenSim.Region.Framework.Scenes
4540 pos = land.LandData.UserLocation; 5524 pos = land.LandData.UserLocation;
4541 } 5525 }
4542 } 5526 }
4543 5527// this is now done in completeMovement for all cases and not just this
4544 land.SendLandUpdateToClient(ControllingClient); 5528// land.SendLandUpdateToClient(ControllingClient);
4545 } 5529 }
4546 } 5530 }
4547 5531
@@ -4556,6 +5540,7 @@ namespace OpenSim.Region.Framework.Scenes
4556 detobj.velVector = obj.Velocity; 5540 detobj.velVector = obj.Velocity;
4557 detobj.colliderType = 0; 5541 detobj.colliderType = 0;
4558 detobj.groupUUID = obj.GroupID; 5542 detobj.groupUUID = obj.GroupID;
5543 detobj.linkNumber = 0;
4559 5544
4560 return detobj; 5545 return detobj;
4561 } 5546 }
@@ -4571,6 +5556,7 @@ namespace OpenSim.Region.Framework.Scenes
4571 detobj.velVector = av.Velocity; 5556 detobj.velVector = av.Velocity;
4572 detobj.colliderType = 0; 5557 detobj.colliderType = 0;
4573 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 5558 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5559 detobj.linkNumber = 0;
4574 5560
4575 return detobj; 5561 return detobj;
4576 } 5562 }
@@ -4586,7 +5572,7 @@ namespace OpenSim.Region.Framework.Scenes
4586 detobj.velVector = Vector3.Zero; 5572 detobj.velVector = Vector3.Zero;
4587 detobj.colliderType = 0; 5573 detobj.colliderType = 0;
4588 detobj.groupUUID = UUID.Zero; 5574 detobj.groupUUID = UUID.Zero;
4589 5575 detobj.linkNumber = 0;
4590 return detobj; 5576 return detobj;
4591 } 5577 }
4592 5578
@@ -4678,6 +5664,8 @@ namespace OpenSim.Region.Framework.Scenes
4678 5664
4679 else 5665 else
4680 { 5666 {
5667 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5668
4681 foreach (uint id in coldata.Keys) 5669 foreach (uint id in coldata.Keys)
4682 { 5670 {
4683 thisHitColliders.Add(id); 5671 thisHitColliders.Add(id);
@@ -4685,7 +5673,7 @@ namespace OpenSim.Region.Framework.Scenes
4685 { 5673 {
4686 startedColliders.Add(id); 5674 startedColliders.Add(id);
4687 curcontact = coldata[id]; 5675 curcontact = coldata[id];
4688 if (Math.Abs(curcontact.RelativeSpeed) > 0.2) 5676 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
4689 { 5677 {
4690 soundinfo = new CollisionForSoundInfo(); 5678 soundinfo = new CollisionForSoundInfo();
4691 soundinfo.colliderID = id; 5679 soundinfo.colliderID = id;
@@ -4764,5 +5752,282 @@ namespace OpenSim.Region.Framework.Scenes
4764 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5752 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4765 5753
4766 } 5754 }
5755
5756 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5757 {
5758 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5759
5760 foreach (ScenePresence p in allpresences)
5761 {
5762 if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5763 continue;
5764
5765 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5766 {
5767 if (isGod)
5768 p.SendViewTo(this);
5769 else
5770 p.SendKillTo(this);
5771 }
5772 }
5773 }
5774
5775 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5776 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5777 {
5778 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5779 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5780 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5781 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5782 List<ScenePresence> allpresences = null;
5783
5784 if (IsInTransit || IsChildAgent)
5785 return;
5786
5787 if (check)
5788 {
5789 // check is relative to current parcel only
5790 if (currentParcelUUID == null || oldhide == currentParcelHide)
5791 return;
5792
5793 allpresences = m_scene.GetScenePresences();
5794
5795 if (oldhide)
5796 { // where private
5797 foreach (ScenePresence p in allpresences)
5798 {
5799 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5800 continue;
5801
5802 // those on not on parcel see me
5803 if (currentParcelID != p.currentParcelUUID)
5804 {
5805 viewsToSendto.Add(p); // they see me
5806 }
5807 }
5808 } // where private end
5809
5810 else
5811 { // where public
5812 foreach (ScenePresence p in allpresences)
5813 {
5814 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5815 continue;
5816
5817 // those not on parcel dont see me
5818 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5819 {
5820 killsToSendto.Add(p); // they dont see me
5821 }
5822 }
5823 } // where public end
5824
5825 allpresences.Clear();
5826 }
5827 else
5828 {
5829 if (currentParcelHide)
5830 {
5831 // now on a private parcel
5832 allpresences = m_scene.GetScenePresences();
5833
5834 if (previusParcelHide && previusParcelID != UUID.Zero)
5835 {
5836 foreach (ScenePresence p in allpresences)
5837 {
5838 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5839 continue;
5840
5841 // only those on previus parcel need receive kills
5842 if (previusParcelID == p.currentParcelUUID)
5843 {
5844 if(p.GodLevel < 200)
5845 killsToSendto.Add(p); // they dont see me
5846 if(GodLevel < 200)
5847 killsToSendme.Add(p); // i dont see them
5848 }
5849 // only those on new parcel need see
5850 if (currentParcelID == p.currentParcelUUID)
5851 {
5852 viewsToSendto.Add(p); // they see me
5853 viewsToSendme.Add(p); // i see them
5854 }
5855 }
5856 }
5857 else
5858 {
5859 //was on a public area
5860 allpresences = m_scene.GetScenePresences();
5861
5862 foreach (ScenePresence p in allpresences)
5863 {
5864 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5865 continue;
5866
5867 // those not on new parcel dont see me
5868 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5869 {
5870 killsToSendto.Add(p); // they dont see me
5871 }
5872 else
5873 {
5874 viewsToSendme.Add(p); // i see those on it
5875 }
5876 }
5877 }
5878 allpresences.Clear();
5879 } // now on a private parcel end
5880
5881 else
5882 {
5883 // now on public parcel
5884 if (previusParcelHide && previusParcelID != UUID.Zero)
5885 {
5886 // was on private area
5887 allpresences = m_scene.GetScenePresences();
5888
5889 foreach (ScenePresence p in allpresences)
5890 {
5891 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5892 continue;
5893 // only those old parcel need kills
5894 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
5895 {
5896 killsToSendme.Add(p); // i dont see them
5897 }
5898 else
5899 {
5900 viewsToSendto.Add(p); // they see me
5901 }
5902 }
5903 }
5904 else
5905 return; // was on a public area also
5906 } // now on public parcel end
5907 }
5908
5909 // send the things
5910
5911 if (killsToSendto.Count > 0)
5912 {
5913 foreach (ScenePresence p in killsToSendto)
5914 {
5915 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
5916 SendKillTo(p);
5917 }
5918 }
5919
5920 if (killsToSendme.Count > 0)
5921 {
5922 foreach (ScenePresence p in killsToSendme)
5923 {
5924 m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
5925 p.SendKillTo(this);
5926 }
5927 }
5928
5929 if (viewsToSendto.Count > 0)
5930 {
5931 foreach (ScenePresence p in viewsToSendto)
5932 {
5933 SendViewTo(p);
5934 }
5935 }
5936
5937 if (viewsToSendme.Count > 0 )
5938 {
5939 foreach (ScenePresence p in viewsToSendme)
5940 {
5941 if (p.IsChildAgent)
5942 continue;
5943// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
5944 p.SendViewTo(this);
5945 }
5946 }
5947 }
5948
5949 public void HasMovedAway(bool nearRegion)
5950 {
5951
5952 if (nearRegion)
5953 {
5954 if (Scene.AttachmentsModule != null)
5955 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
5956
5957 if (!ParcelHideThisAvatar || GodLevel >= 200)
5958 return;
5959
5960 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5961 foreach (ScenePresence p in allpresences)
5962 {
5963 if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
5964 continue;
5965
5966 if (p.currentParcelUUID == m_currentParcelUUID)
5967 {
5968 p.SendKillTo(this);
5969 }
5970 }
5971 }
5972 else
5973 {
5974 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5975 foreach (ScenePresence p in allpresences)
5976 {
5977 if (p == this)
5978 continue;
5979 SendKillTo(p);
5980 if (!p.IsChildAgent)
5981 p.SendKillTo(this);
5982 }
5983
5984 if (Scene.AttachmentsModule != null)
5985 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
5986 }
5987 }
5988
5989
5990// kill with attachs root kills
5991 public void SendKillTo(ScenePresence p)
5992 {
5993 List<uint> ids = new List<uint>(m_attachments.Count + 1);
5994 foreach (SceneObjectGroup sog in m_attachments)
5995 {
5996 ids.Add(sog.RootPart.LocalId);
5997 }
5998
5999 ids.Add(LocalId);
6000 p.ControllingClient.SendKillObject(ids);
6001 }
6002
6003/*
6004// kill with hack
6005 public void SendKillTo(ScenePresence p)
6006 {
6007 foreach (SceneObjectGroup sog in m_attachments)
6008 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6009 p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6010 }
6011*/
6012 public void SendViewTo(ScenePresence p)
6013 {
6014 SendAvatarDataToAgentNF(p);
6015 SendAppearanceToAgent(p);
6016 if (Animator != null)
6017 Animator.SendAnimPackToClient(p.ControllingClient);
6018 SendAttachmentsToAgentNF(p);
6019 }
6020
6021 public void SetAnimationOverride(string animState, UUID animID)
6022 {
6023 Overrides.SetOverride(animState, animID);
6024// Animator.SendAnimPack();
6025 Animator.ForceUpdateMovementAnimations();
6026 }
6027
6028 public UUID GetAnimationOverride(string animState)
6029 {
6030 return Overrides.GetOverriddenAnimation(animState);
6031 }
4767 } 6032 }
4768} 6033}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
new file mode 100644
index 0000000..cae7fe5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Region.Framework.Scenes
31{
32 /// <summary>
33 /// The possible states that a scene presence can be in. This is currently orthagonal to whether a scene presence
34 /// is root or child.
35 /// </summary>
36 /// <remarks>
37 /// This is a state machine.
38 ///
39 /// [Entry] => Running
40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
42 /// Removing => Removed
43 ///
44 /// All other methods should only see the scene presence in running state - this is the normal operational state
45 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
46 /// </remarks>
47 public enum ScenePresenceState
48 {
49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
52 Removed, // The presence has been removed from the scene and is effectively dead.
53 // There is no exit from this state.
54 }
55
56 internal class ScenePresenceStateMachine
57 {
58 private ScenePresence m_sp;
59 private ScenePresenceState m_state;
60
61 internal ScenePresenceStateMachine(ScenePresence sp)
62 {
63 m_sp = sp;
64 m_state = ScenePresenceState.Running;
65 }
66
67 internal ScenePresenceState GetState()
68 {
69 return m_state;
70 }
71
72 /// <summary>
73 /// Updates the state of an agent that is already in transit.
74 /// </summary>
75 /// <param name='id'></param>
76 /// <param name='newState'></param>
77 /// <returns></returns>
78 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
79 internal void SetState(ScenePresenceState newState)
80 {
81 bool transitionOkay = false;
82
83 lock (this)
84 {
85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
97 transitionOkay = true;
98 }
99
100 if (!transitionOkay)
101 {
102 throw new Exception(
103 string.Format(
104 "Scene presence {0} is not allowed to move from state {1} to new state {2} in {3}",
105 m_sp.Name, m_state, newState, m_sp.Scene.Name));
106 }
107 else
108 {
109 m_state = newState;
110 }
111 }
112 }
113} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index ce4fb40..52bd5c9 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -271,7 +271,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
271 // Script state may, or may not, exist. Not having any, is NOT 271 // Script state may, or may not, exist. Not having any, is NOT
272 // ever a problem. 272 // ever a problem.
273 sceneObject.LoadScriptState(doc); 273 sceneObject.LoadScriptState(doc);
274 274
275 return sceneObject; 275 return sceneObject;
276 } 276 }
277 catch (Exception e) 277 catch (Exception e)
@@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); 365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound);
366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); 366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume);
367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); 367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
368 m_SOPXmlProcessors.Add("AttachedPos", ProcessAttachedPos);
368 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); 369 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
369 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); 370 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
370 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); 371 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
@@ -390,6 +391,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
390 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset); 391 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset);
391 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset); 392 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset);
392 393
394 m_SOPXmlProcessors.Add("SoundID", ProcessSoundID);
395 m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain);
396 m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags);
397 m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius);
398 m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing);
399
393 #endregion 400 #endregion
394 401
395 #region TaskInventoryXmlProcessors initialization 402 #region TaskInventoryXmlProcessors initialization
@@ -443,6 +450,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
443 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); 450 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
444 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); 451 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
445 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); 452 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
453 m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
446 m_ShapeXmlProcessors.Add("State", ProcessShpState); 454 m_ShapeXmlProcessors.Add("State", ProcessShpState);
447 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); 455 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
448 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); 456 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@@ -652,6 +660,30 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
652 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset")); 660 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset"));
653 } 661 }
654 662
663 private static void ProcessSoundID(SceneObjectPart obj, XmlTextReader reader)
664 {
665 obj.Sound = Util.ReadUUID(reader, "SoundID");
666 }
667
668 private static void ProcessSoundGain(SceneObjectPart obj, XmlTextReader reader)
669 {
670 obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty);
671 }
672
673 private static void ProcessSoundFlags(SceneObjectPart obj, XmlTextReader reader)
674 {
675 obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty);
676 }
677
678 private static void ProcessSoundRadius(SceneObjectPart obj, XmlTextReader reader)
679 {
680 obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty);
681 }
682
683 private static void ProcessSoundQueueing(SceneObjectPart obj, XmlTextReader reader)
684 {
685 obj.SoundQueueing = Util.ReadBoolean(reader);
686 }
655 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader) 687 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
656 { 688 {
657 SOPVehicle vehicle = SOPVehicle.FromXml2(reader); 689 SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
@@ -798,6 +830,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 830 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
799 } 831 }
800 832
833 private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
834 {
835 obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
836 }
837
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) 838 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 { 839 {
803 obj.DynAttrs.ReadXml(reader); 840 obj.DynAttrs.ReadXml(reader);
@@ -1099,6 +1136,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1099 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); 1136 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
1100 } 1137 }
1101 1138
1139 private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
1140 {
1141 shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
1142 }
1143
1102 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) 1144 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
1103 { 1145 {
1104 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); 1146 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@@ -1253,6 +1295,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1253 writer.WriteBase64(data, 0, data.Length); 1295 writer.WriteBase64(data, 0, data.Length);
1254 writer.WriteEndElement(); 1296 writer.WriteEndElement();
1255 } 1297 }
1298
1256 1299
1257 writer.WriteEndElement(); 1300 writer.WriteEndElement();
1258 } 1301 }
@@ -1267,7 +1310,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1267 1310
1268 WriteUUID(writer, "CreatorID", sop.CreatorID, options); 1311 WriteUUID(writer, "CreatorID", sop.CreatorID, options);
1269 1312
1270 if (sop.CreatorData != null && sop.CreatorData != string.Empty) 1313 if (!string.IsNullOrEmpty(sop.CreatorData))
1271 writer.WriteElementString("CreatorData", sop.CreatorData); 1314 writer.WriteElementString("CreatorData", sop.CreatorData);
1272 else if (options.ContainsKey("home")) 1315 else if (options.ContainsKey("home"))
1273 { 1316 {
@@ -1345,8 +1388,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1388 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1346 if (sop.MediaUrl != null) 1389 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1390 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1391 WriteVector(writer, "AttachedPos", sop.AttachedPos);
1348 1392
1349 if (sop.DynAttrs.Count > 0) 1393 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1394 {
1351 writer.WriteStartElement("DynAttrs"); 1395 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer); 1396 sop.DynAttrs.WriteXml(writer);
@@ -1384,6 +1428,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1384 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); 1428 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1385 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); 1429 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1386 1430
1431 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1432 {
1433 WriteUUID(writer, "SoundID", sop.Sound, options);
1434 writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower());
1435 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1436 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower());
1437 }
1438 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1439
1387 writer.WriteEndElement(); 1440 writer.WriteEndElement();
1388 } 1441 }
1389 1442
@@ -1451,7 +1504,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1451 1504
1452 WriteUUID(writer, "CreatorID", item.CreatorID, options); 1505 WriteUUID(writer, "CreatorID", item.CreatorID, options);
1453 1506
1454 if (item.CreatorData != null && item.CreatorData != string.Empty) 1507 if (!string.IsNullOrEmpty(item.CreatorData))
1455 writer.WriteElementString("CreatorData", item.CreatorData); 1508 writer.WriteElementString("CreatorData", item.CreatorData);
1456 else if (options.ContainsKey("home")) 1509 else if (options.ContainsKey("home"))
1457 { 1510 {
@@ -1539,6 +1592,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1592 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1593 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1594 writer.WriteElementString("State", shp.State.ToString());
1595 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1596
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1597 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1598 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options);
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 5398ab9..bf32251 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -290,6 +290,9 @@ namespace OpenSim.Region.Framework.Scenes
290 290
291 private void statsHeartBeat(object sender, EventArgs e) 291 private void statsHeartBeat(object sender, EventArgs e)
292 { 292 {
293 if (!m_scene.Active)
294 return;
295
293 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; 296 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23];
294 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 297 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
295 298
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 9557cd0..95b30d5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,7 +33,9 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Framework.EntityTransfer;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess; 37using OpenSim.Region.CoreModules.Framework.InventoryAccess;
38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
37using OpenSim.Region.CoreModules.World.Permissions; 39using OpenSim.Region.CoreModules.World.Permissions;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
@@ -52,6 +54,24 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 [TestFixture] 54 [TestFixture]
53 public class SceneObjectDeRezTests : OpenSimTestCase 55 public class SceneObjectDeRezTests : OpenSimTestCase
54 { 56 {
57 [TestFixtureSetUp]
58 public void FixtureInit()
59 {
60 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
61 // This facility was added after the original async delete tests were written, so it may be possible now
62 // to not bother explicitly disabling their async (since everything will be running sync).
63 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
64 }
65
66 [TestFixtureTearDown]
67 public void TearDown()
68 {
69 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
70 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
71 // tests really shouldn't).
72 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
73 }
74
55 /// <summary> 75 /// <summary>
56 /// Test deleting an object from a scene. 76 /// Test deleting an object from a scene.
57 /// </summary> 77 /// </summary>
@@ -59,7 +79,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
59 public void TestDeRezSceneObject() 79 public void TestDeRezSceneObject()
60 { 80 {
61 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
62// log4net.Config.XmlConfigurator.Configure();
63 82
64 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 83 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
65 84
@@ -73,32 +92,77 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 92 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
74 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 93 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
75 sogd.Enabled = false; 94 sogd.Enabled = false;
76 95
77 SceneObjectPart part 96 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId);
78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 97 uint soLocalId = so.LocalId;
79 part.Name = "obj1";
80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81 98
82 List<uint> localIds = new List<uint>(); 99 List<uint> localIds = new List<uint>();
83 localIds.Add(part.LocalId); 100 localIds.Add(so.LocalId);
84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 101 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85 102
86 // Check that object isn't deleted until we crank the sogd handle. 103 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 104 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null); 105 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); 106 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90 107
91 sogd.InventoryDeQueueAndDelete(); 108 sogd.InventoryDeQueueAndDelete();
92 109
93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId); 110 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
94 Assert.That(retrievedPart2, Is.Null); 111 Assert.That(retrievedPart2, Is.Null);
112 }
113
114 /// <summary>
115 /// Test that child and root agents correctly receive KillObject notifications.
116 /// </summary>
117 [Test]
118 public void TestDeRezSceneObjectToAgents()
119 {
120 TestHelpers.InMethod();
121// TestHelpers.EnableLogging();
122
123 SceneHelpers sh = new SceneHelpers();
124 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
125 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
126
127 // We need this so that the creation of the root client for userB in sceneB can trigger the creation of a child client in sceneA
128 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
129 EntityTransferModule etmB = new EntityTransferModule();
130 IConfigSource config = new IniConfigSource();
131 IConfig modulesConfig = config.AddConfig("Modules");
132 modulesConfig.Set("EntityTransferModule", etmB.Name);
133 modulesConfig.Set("SimulationServices", lscm.Name);
134 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
135 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
136
137 // We need this for derez
138 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
139
140 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
141 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
142
143 TestClient clientA = (TestClient)SceneHelpers.AddScenePresence(sceneA, uaA).ControllingClient;
144
145 // This is the more long-winded route we have to take to get a child client created for userB in sceneA
146 // rather than just calling AddScenePresence() as for userA
147 AgentCircuitData acd = SceneHelpers.GenerateAgentData(uaB);
148 TestClient clientB = new TestClient(acd, sceneB);
149 List<TestClient> childClientsB = new List<TestClient>();
150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(clientB, childClientsB);
151
152 SceneHelpers.AddScenePresence(sceneB, clientB, acd);
153
154 SceneObjectGroup so = SceneHelpers.AddSceneObject(sceneA);
155 uint soLocalId = so.LocalId;
156
157 sceneA.DeleteSceneObject(so, false);
95 } 158 }
96 159
97 /// <summary> 160 /// <summary>
98 /// Test deleting an object from a scene where the deleter is not the owner 161 /// Test deleting an object from a scene where the deleter is not the owner
99 /// </summary> 162 /// </summary>
100 /// 163 /// <remarks>
101 /// This test assumes that the deleter is not a god. 164 /// This test assumes that the deleter is not a god.
165 /// </remarks>
102 [Test] 166 [Test]
103 public void TestDeRezSceneObjectNotOwner() 167 public void TestDeRezSceneObjectNotOwner()
104 { 168 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index bbfbbfc..1ff1329 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -111,6 +111,45 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); 111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
112 } 112 }
113 113
114 /// <summary>
115 /// Test that duplicate complete movement calls are ignored.
116 /// </summary>
117 /// <remarks>
118 /// If duplicate calls are not ignored then there is a risk of race conditions or other unexpected effects.
119 /// </remarks>
120 [Test]
121 public void TestDupeCompleteMovementCalls()
122 {
123 TestHelpers.InMethod();
124// TestHelpers.EnableLogging();
125
126 UUID spUuid = TestHelpers.ParseTail(0x1);
127
128 TestScene scene = new SceneHelpers().SetupScene();
129
130 int makeRootAgentEvents = 0;
131 scene.EventManager.OnMakeRootAgent += spi => makeRootAgentEvents++;
132
133 ScenePresence sp = SceneHelpers.AddScenePresence(scene, spUuid);
134
135 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
136
137 // Normally these would be invoked by a CompleteMovement message coming in to the UDP stack. But for
138 // convenience, here we will invoke it manually.
139 sp.CompleteMovement(sp.ControllingClient, true);
140
141 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
142
143 // Check rest of exepcted parameters.
144 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
145 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
146
147 Assert.That(sp.IsChildAgent, Is.False);
148 Assert.That(sp.UUID, Is.EqualTo(spUuid));
149
150 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
151 }
152
114 [Test] 153 [Test]
115 public void TestCreateDuplicateRootScenePresence() 154 public void TestCreateDuplicateRootScenePresence()
116 { 155 {
@@ -119,7 +158,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
119 158
120 UUID spUuid = TestHelpers.ParseTail(0x1); 159 UUID spUuid = TestHelpers.ParseTail(0x1);
121 160
161 // The etm is only invoked by this test to check whether an agent is still in transit if there is a dupe
162 EntityTransferModule etm = new EntityTransferModule();
163
164 IConfigSource config = new IniConfigSource();
165 IConfig modulesConfig = config.AddConfig("Modules");
166 modulesConfig.Set("EntityTransferModule", etm.Name);
167 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
168
169 // In order to run a single threaded regression test we do not want the entity transfer module waiting
170 // for a callback from the destination scene before removing its avatar data.
171 entityTransferConfig.Set("wait_for_callback", false);
172
122 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
174 SceneHelpers.SetupSceneModules(scene, config, etm);
123 SceneHelpers.AddScenePresence(scene, spUuid); 175 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid); 176 SceneHelpers.AddScenePresence(scene, spUuid);
125 177
@@ -133,7 +185,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 } 185 }
134 186
135 [Test] 187 [Test]
136 public void TestCloseAgent() 188 public void TestCloseClient()
137 { 189 {
138 TestHelpers.InMethod(); 190 TestHelpers.InMethod();
139// TestHelpers.EnableLogging(); 191// TestHelpers.EnableLogging();
@@ -141,7 +193,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 193 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 194 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 195
144 scene.IncomingCloseAgent(sp.UUID, false); 196 scene.CloseAgent(sp.UUID, false);
145 197
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 198 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 199 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
@@ -187,7 +239,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
187 // *** This is the second stage, where the client established a child agent/scene presence using the 239 // *** This is the second stage, where the client established a child agent/scene presence using the
188 // circuit code given to the scene in stage 1 *** 240 // circuit code given to the scene in stage 1 ***
189 TestClient client = new TestClient(acd, scene); 241 TestClient client = new TestClient(acd, scene);
190 scene.AddNewClient(client, PresenceType.User); 242 scene.AddNewAgent(client, PresenceType.User);
191 243
192 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 244 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
193 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 245 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -236,58 +288,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
236// Assert.That(childPresence, Is.Not.Null); 288// Assert.That(childPresence, Is.Not.Null);
237// Assert.That(childPresence.IsChildAgent, Is.True); 289// Assert.That(childPresence.IsChildAgent, Is.True);
238 } 290 }
239
240// /// <summary>
241// /// Test adding a root agent to a scene. Doesn't yet actually complete crossing the agent into the scene.
242// /// </summary>
243// [Test]
244// public void T010_TestAddRootAgent()
245// {
246// TestHelpers.InMethod();
247//
248// string firstName = "testfirstname";
249//
250// AgentCircuitData agent = new AgentCircuitData();
251// agent.AgentID = agent1;
252// agent.firstname = firstName;
253// agent.lastname = "testlastname";
254// agent.SessionID = UUID.Random();
255// agent.SecureSessionID = UUID.Random();
256// agent.circuitcode = 123;
257// agent.BaseFolder = UUID.Zero;
258// agent.InventoryFolder = UUID.Zero;
259// agent.startpos = Vector3.Zero;
260// agent.CapsPath = GetRandomCapsObjectPath();
261// agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
262// agent.child = true;
263//
264// scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
265//
266// string reason;
267// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
268// testclient = new TestClient(agent, scene);
269// scene.AddNewClient(testclient);
270//
271// ScenePresence presence = scene.GetScenePresence(agent1);
272//
273// Assert.That(presence, Is.Not.Null, "presence is null");
274// Assert.That(presence.Firstname, Is.EqualTo(firstName), "First name not same");
275// acd1 = agent;
276// }
277//
278// /// <summary>
279// /// Test removing an uncrossed root agent from a scene.
280// /// </summary>
281// [Test]
282// public void T011_TestRemoveRootAgent()
283// {
284// TestHelpers.InMethod();
285//
286// scene.RemoveClient(agent1);
287//
288// ScenePresence presence = scene.GetScenePresence(agent1);
289//
290// Assert.That(presence, Is.Null, "presence is not null");
291// }
292 } 291 }
293} \ No newline at end of file 292} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
new file mode 100644
index 0000000..9fa0a71
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using Nini.Config;
36using NUnit.Framework;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Framework;
44using OpenSim.Region.CoreModules.Framework.EntityTransfer;
45using OpenSim.Region.CoreModules.World.Serialiser;
46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces;
49using OpenSim.Tests.Common;
50using OpenSim.Tests.Common.Mock;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52
53namespace OpenSim.Region.Framework.Scenes.Tests
54{
55 [TestFixture]
56 public class ScenePresenceCapabilityTests : OpenSimTestCase
57 {
58 [Test]
59 public void TestChildAgentSingleRegionCapabilities()
60 {
61 TestHelpers.InMethod();
62// TestHelpers.EnableLogging();
63
64 UUID spUuid = TestHelpers.ParseTail(0x1);
65
66 // XXX: This is not great since the use of statics will mean that this has to be manually cleaned up for
67 // any subsequent test.
68 // XXX: May replace with a mock IHttpServer later.
69 BaseHttpServer httpServer = new BaseHttpServer(99999);
70 MainServer.AddHttpServer(httpServer);
71 MainServer.Instance = httpServer;
72
73 CapabilitiesModule capsMod = new CapabilitiesModule();
74 TestScene scene = new SceneHelpers().SetupScene();
75 SceneHelpers.SetupSceneModules(scene, capsMod);
76
77 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
78 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
79
80 // TODO: Need to add tests for other ICapabiltiesModule methods.
81
82// scene.IncomingCloseAgent(sp.UUID, false);
83// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
84 scene.CloseAgent(sp.UUID, false);
85// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
86
87 // TODO: Need to add tests for other ICapabiltiesModule methods.
88 }
89 }
90}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 8775949..b806a97 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.CoreModules.Framework; 38using OpenSim.Region.CoreModules.Framework;
39using OpenSim.Region.CoreModules.Framework.EntityTransfer; 39using OpenSim.Region.CoreModules.Framework.EntityTransfer;
40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.CoreModules.World.Permissions;
41using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
43 44
@@ -95,11 +96,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
95 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 96 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
96 97
97 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 98 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
98 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 99 TestClient tc = new TestClient(acd, sceneA);
99 List<TestClient> destinationTestClients = new List<TestClient>(); 100 List<TestClient> destinationTestClients = new List<TestClient>();
100 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 101 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
101 102
102 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 103 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
103 originalSp.AbsolutePosition = new Vector3(128, 32, 10); 104 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
104 105
105// originalSp.Flying = true; 106// originalSp.Flying = true;
@@ -112,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
112 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); 113 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
113 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); 114 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
114 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 115 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
116 moveArgs.SessionID = acd.SessionID;
115 117
116 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); 118 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
117 119
@@ -158,5 +160,90 @@ namespace OpenSim.Region.Framework.Scenes.Tests
158 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); 160 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
159 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); 161 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
160 } 162 }
163
164 /// <summary>
165 /// Test a cross attempt where the user can see into the neighbour but does not have permission to become
166 /// root there.
167 /// </summary>
168 [Test]
169 public void TestCrossOnSameSimulatorNoRootDestPerm()
170 {
171 TestHelpers.InMethod();
172// TestHelpers.EnableLogging();
173
174 UUID userId = TestHelpers.ParseTail(0x1);
175
176 EntityTransferModule etmA = new EntityTransferModule();
177 EntityTransferModule etmB = new EntityTransferModule();
178 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
179
180 IConfigSource config = new IniConfigSource();
181 IConfig modulesConfig = config.AddConfig("Modules");
182 modulesConfig.Set("EntityTransferModule", etmA.Name);
183 modulesConfig.Set("SimulationServices", lscm.Name);
184
185 SceneHelpers sh = new SceneHelpers();
186 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
187 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
188
189 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
190 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
191
192 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
193 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
194 // IsAdministrator if no permissions module is present is true.
195// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
196
197 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
198 TestClient tc = new TestClient(acd, sceneA);
199 List<TestClient> destinationTestClients = new List<TestClient>();
200 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
201
202 // Make sure sceneB will not accept this avatar.
203 sceneB.RegionInfo.EstateSettings.PublicAccess = false;
204
205 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
206 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
207
208 AgentUpdateArgs moveArgs = new AgentUpdateArgs();
209 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
210 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
211 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
212 moveArgs.SessionID = acd.SessionID;
213
214 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
215
216 sceneA.Update(1);
217
218// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);
219
220 // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
221 // But really we want to do this in a more robust way.
222 for (int i = 0; i < 100; i++)
223 {
224 sceneA.Update(1);
225// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
226 }
227
228 // sceneA agent should still be root
229 ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
230 Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);
231
232 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
233
234 // sceneB agent should also still be root
235 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
236
237 // sceneB should ignore unauthorized attempt to upgrade agent to root
238 TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);
239
240 int agentMovementCompleteReceived = 0;
241 sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;
242
243 sceneBTc.CompleteMovement();
244
245 Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
246 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
247 }
161 } 248 }
162} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index acaeb90..0911f00 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -111,15 +111,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 111
112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
113 113
114 // We need to preserve this here because phys actor is removed by the sit.
115 Vector3 spPhysActorSize = m_sp.PhysicsActor.Size;
114 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 116 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
115 117
116 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
117 // default avatar.
118 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
119 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
120 Assert.That( 118 Assert.That(
121 m_sp.AbsolutePosition, 119 m_sp.AbsolutePosition,
122 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 120 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2)));
123 121
124 m_sp.StandUp(); 122 m_sp.StandUp();
125 123
@@ -147,9 +145,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
147 145
148 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); 146 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID));
149 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 147 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
150 Assert.That( 148// Assert.That(
151 m_sp.AbsolutePosition, 149// m_sp.AbsolutePosition,
152 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 150// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
153 Assert.That(m_sp.PhysicsActor, Is.Null); 151 Assert.That(m_sp.PhysicsActor, Is.Null);
154 152
155 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 153 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 8d94d29..fff542b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Text; 32using System.Text;
33using System.Threading;
33using Nini.Config; 34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -107,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
107 } 108 }
108 109
109 [Test] 110 [Test]
110 public void TestSameSimulatorIsolatedRegions() 111 public void TestSameSimulatorIsolatedRegionsV1()
111 { 112 {
112 TestHelpers.InMethod(); 113 TestHelpers.InMethod();
113// TestHelpers.EnableLogging(); 114// TestHelpers.EnableLogging();
@@ -136,14 +137,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
136 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 137 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
137 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 138 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
138 139
140 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
141 lscm.ServiceVersion = "SIMULATION/0.1";
142
139 Vector3 teleportPosition = new Vector3(10, 11, 12); 143 Vector3 teleportPosition = new Vector3(10, 11, 12);
140 Vector3 teleportLookAt = new Vector3(20, 21, 22); 144 Vector3 teleportLookAt = new Vector3(20, 21, 22);
141 145
142 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 146 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
143 sp.AbsolutePosition = new Vector3(30, 31, 32); 147 sp.AbsolutePosition = new Vector3(30, 31, 32);
144 148
145 List<TestClient> destinationTestClients = new List<TestClient>(); 149 List<TestClient> destinationTestClients = new List<TestClient>();
146 EntityTransferHelpers.SetUpInformClientOfNeighbour((TestClient)sp.ControllingClient, destinationTestClients); 150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(
151 (TestClient)sp.ControllingClient, destinationTestClients);
147 152
148 sceneA.RequestTeleportLocation( 153 sceneA.RequestTeleportLocation(
149 sp.ControllingClient, 154 sp.ControllingClient,
@@ -176,6 +181,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
176// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); 181// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
177 } 182 }
178 183
184 [Test]
185 public void TestSameSimulatorIsolatedRegionsV2()
186 {
187 TestHelpers.InMethod();
188// TestHelpers.EnableLogging();
189
190 UUID userId = TestHelpers.ParseTail(0x1);
191
192 EntityTransferModule etmA = new EntityTransferModule();
193 EntityTransferModule etmB = new EntityTransferModule();
194 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
195
196 IConfigSource config = new IniConfigSource();
197 IConfig modulesConfig = config.AddConfig("Modules");
198 modulesConfig.Set("EntityTransferModule", etmA.Name);
199 modulesConfig.Set("SimulationServices", lscm.Name);
200
201 SceneHelpers sh = new SceneHelpers();
202 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
203 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
204
205 SceneHelpers.SetupSceneModules(sceneA, config, etmA);
206 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
207 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
208
209 Vector3 teleportPosition = new Vector3(10, 11, 12);
210 Vector3 teleportLookAt = new Vector3(20, 21, 22);
211
212 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
213 sp.AbsolutePosition = new Vector3(30, 31, 32);
214
215 List<TestClient> destinationTestClients = new List<TestClient>();
216 EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement(
217 (TestClient)sp.ControllingClient, destinationTestClients);
218
219 sceneA.RequestTeleportLocation(
220 sp.ControllingClient,
221 sceneB.RegionInfo.RegionHandle,
222 teleportPosition,
223 teleportLookAt,
224 (uint)TeleportFlags.ViaLocation);
225
226 Assert.That(sceneA.GetScenePresence(userId), Is.Null);
227
228 ScenePresence sceneBSp = sceneB.GetScenePresence(userId);
229 Assert.That(sceneBSp, Is.Not.Null);
230 Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
231 Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
232
233 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
234 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
235 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
236 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
237
238 // TODO: Add assertions to check correct circuit details in both scenes.
239
240 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
241 // position instead).
242// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
243 }
244
179 /// <summary> 245 /// <summary>
180 /// Test teleport procedures when the target simulator returns false when queried about access. 246 /// Test teleport procedures when the target simulator returns false when queried about access.
181 /// </summary> 247 /// </summary>
@@ -224,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
224 Vector3 teleportPosition = new Vector3(10, 11, 12); 290 Vector3 teleportPosition = new Vector3(10, 11, 12);
225 Vector3 teleportLookAt = new Vector3(20, 21, 22); 291 Vector3 teleportLookAt = new Vector3(20, 21, 22);
226 292
227 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 293 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
228 sp.AbsolutePosition = preTeleportPosition; 294 sp.AbsolutePosition = preTeleportPosition;
229 295
230 // Make sceneB return false on query access 296 // Make sceneB return false on query access
@@ -300,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
300 Vector3 teleportPosition = new Vector3(10, 11, 12); 366 Vector3 teleportPosition = new Vector3(10, 11, 12);
301 Vector3 teleportLookAt = new Vector3(20, 21, 22); 367 Vector3 teleportLookAt = new Vector3(20, 21, 22);
302 368
303 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 369 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
304 sp.AbsolutePosition = preTeleportPosition; 370 sp.AbsolutePosition = preTeleportPosition;
305 371
306 // Make sceneB refuse CreateAgent 372 // Make sceneB refuse CreateAgent
@@ -389,7 +455,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
389 Vector3 teleportPosition = new Vector3(10, 11, 12); 455 Vector3 teleportPosition = new Vector3(10, 11, 12);
390 Vector3 teleportLookAt = new Vector3(20, 21, 22); 456 Vector3 teleportLookAt = new Vector3(20, 21, 22);
391 457
392 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 458 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
393 sp.AbsolutePosition = preTeleportPosition; 459 sp.AbsolutePosition = preTeleportPosition;
394 460
395 sceneA.RequestTeleportLocation( 461 sceneA.RequestTeleportLocation(
@@ -425,10 +491,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
425 } 491 }
426 492
427 [Test] 493 [Test]
428 public void TestSameSimulatorNeighbouringRegions() 494 public void TestSameSimulatorNeighbouringRegionsV1()
429 { 495 {
430 TestHelpers.InMethod(); 496 TestHelpers.InMethod();
431 TestHelpers.EnableLogging(); 497// TestHelpers.EnableLogging();
432 498
433 UUID userId = TestHelpers.ParseTail(0x1); 499 UUID userId = TestHelpers.ParseTail(0x1);
434 500
@@ -454,15 +520,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
454 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); 520 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
455 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 521 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
456 522
523 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
524 lscm.ServiceVersion = "SIMULATION/0.1";
525
457 Vector3 teleportPosition = new Vector3(10, 11, 12); 526 Vector3 teleportPosition = new Vector3(10, 11, 12);
458 Vector3 teleportLookAt = new Vector3(20, 21, 22); 527 Vector3 teleportLookAt = new Vector3(20, 21, 22);
459 528
460 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 529 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
461 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 530 TestClient tc = new TestClient(acd, sceneA);
462 List<TestClient> destinationTestClients = new List<TestClient>(); 531 List<TestClient> destinationTestClients = new List<TestClient>();
463 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 532 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
464 533
465 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 534 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
466 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); 535 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
467 536
468 Assert.That(beforeSceneASp, Is.Not.Null); 537 Assert.That(beforeSceneASp, Is.Not.Null);
@@ -506,5 +575,89 @@ namespace OpenSim.Region.Framework.Scenes.Tests
506 575
507// TestHelpers.DisableLogging(); 576// TestHelpers.DisableLogging();
508 } 577 }
578
579 [Test]
580 public void TestSameSimulatorNeighbouringRegionsV2()
581 {
582 TestHelpers.InMethod();
583// TestHelpers.EnableLogging();
584
585 UUID userId = TestHelpers.ParseTail(0x1);
586
587 EntityTransferModule etmA = new EntityTransferModule();
588 EntityTransferModule etmB = new EntityTransferModule();
589 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
590
591 IConfigSource config = new IniConfigSource();
592 IConfig modulesConfig = config.AddConfig("Modules");
593 modulesConfig.Set("EntityTransferModule", etmA.Name);
594 modulesConfig.Set("SimulationServices", lscm.Name);
595
596 SceneHelpers sh = new SceneHelpers();
597 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
598 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
599
600 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
601 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
602 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
603
604 Vector3 teleportPosition = new Vector3(10, 11, 12);
605 Vector3 teleportLookAt = new Vector3(20, 21, 22);
606
607 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
608 TestClient tc = new TestClient(acd, sceneA);
609 List<TestClient> destinationTestClients = new List<TestClient>();
610 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
611
612 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
613 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
614
615 Assert.That(beforeSceneASp, Is.Not.Null);
616 Assert.That(beforeSceneASp.IsChildAgent, Is.False);
617
618 ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId);
619 Assert.That(beforeSceneBSp, Is.Not.Null);
620 Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
621
622 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
623 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
624 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
625 // Both these operations will occur on different threads and will wait for each other.
626 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
627 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
628 tc.OnTestClientSendRegionTeleport
629 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
630 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
631
632 sceneA.RequestTeleportLocation(
633 beforeSceneASp.ControllingClient,
634 sceneB.RegionInfo.RegionHandle,
635 teleportPosition,
636 teleportLookAt,
637 (uint)TeleportFlags.ViaLocation);
638
639 ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
640 Assert.That(afterSceneASp, Is.Not.Null);
641 Assert.That(afterSceneASp.IsChildAgent, Is.True);
642
643 ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId);
644 Assert.That(afterSceneBSp, Is.Not.Null);
645 Assert.That(afterSceneBSp.IsChildAgent, Is.False);
646 Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
647 Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
648
649 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
650 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1));
651 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
652 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
653
654 // TODO: Add assertions to check correct circuit details in both scenes.
655
656 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
657 // position instead).
658// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
659
660// TestHelpers.DisableLogging();
661 }
509 } 662 }
510} 663}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
new file mode 100644
index 0000000..1667002
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.Framework.Scenes.Tests
40{
41 [TestFixture]
42 public class SceneStatisticsTests : OpenSimTestCase
43 {
44 private TestScene m_scene;
45
46 [SetUp]
47 public void Init()
48 {
49 m_scene = new SceneHelpers().SetupScene();
50 }
51
52 [Test]
53 public void TestAddRemovePhysicalLinkset()
54 {
55 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
56
57 UUID ownerId = TestHelpers.ParseTail(0x1);
58 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
59 so1.ScriptSetPhysicsStatus(true);
60 m_scene.AddSceneObject(so1);
61
62 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
63 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));
64
65 m_scene.DeleteSceneObject(so1, false);
66
67 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(0));
68 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
69 }
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
new file mode 100644
index 0000000..9a97acc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
@@ -0,0 +1,119 @@
1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are met:
4 * * Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer.
6 * * Redistributions in binary form must reproduce the above copyright
7 * notice, this list of conditions and the following disclaimer in the
8 * documentation and/or other materials provided with the distribution.
9 * * Neither the name of the OpenSimulator Project nor the
10 * names of its contributors may be used to endorse or promote products
11 * derived from this software without specific prior written permission.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25using System;
26using Nini.Config;
27using NUnit.Framework;
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.CoreModules.World.Estate;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Services.Interfaces;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.Framework.Scenes.Tests
38{
39 /// <summary>
40 /// Scene telehub tests
41 /// </summary>
42 /// <remarks>
43 /// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour
44 /// in the case of an error condition
45 /// </remarks>
46 [TestFixture]
47 public class SceneTelehubTests : OpenSimTestCase
48 {
49 /// <summary>
50 /// Test for desired behaviour when a telehub has no spawn points
51 /// </summary>
52 [Test]
53 public void TestNoTelehubSpawnPoints()
54 {
55 TestHelpers.InMethod();
56// TestHelpers.EnableLogging();
57
58 EstateManagementModule emm = new EstateManagementModule();
59
60 SceneHelpers sh = new SceneHelpers();
61 Scene scene = sh.SetupScene();
62 SceneHelpers.SetupSceneModules(scene, emm);
63
64 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
65
66 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
67
68 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
69 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
70
71 // Must still be possible to successfully log in
72 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
73
74 UserAccount ua
75 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
76
77 SceneHelpers.AddScenePresence(scene, ua);
78
79 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
80 }
81
82 /// <summary>
83 /// Test for desired behaviour when the scene object nominated as a telehub object does not exist.
84 /// </summary>
85 [Test]
86 public void TestNoTelehubSceneObject()
87 {
88 TestHelpers.InMethod();
89// TestHelpers.EnableLogging();
90
91 EstateManagementModule emm = new EstateManagementModule();
92
93 SceneHelpers sh = new SceneHelpers();
94 Scene scene = sh.SetupScene();
95 SceneHelpers.SetupSceneModules(scene, emm);
96
97 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
98
99 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
100 SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner);
101
102 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
103 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId);
104 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
105
106 scene.DeleteSceneObject(telehubSo, false);
107
108 // Must still be possible to successfully log in
109 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
110
111 UserAccount ua
112 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
113
114 SceneHelpers.AddScenePresence(scene, ua);
115
116 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
117 }
118 }
119} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index b09ae39..67655d6 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -34,9 +34,11 @@ using System.Threading;
34using log4net; 34using log4net;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.Assets; 36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
39using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
40 42
41namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
42{ 44{
@@ -82,29 +84,33 @@ namespace OpenSim.Region.Framework.Scenes
82 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
83 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
84 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
85 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
86 { 88 {
87 try 89 try
88 { 90 {
89 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;
90 92
91 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 93 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
92 { 94 {
93 GetWearableAssetUuids(assetUuid, assetUuids); 95 GetWearableAssetUuids(assetUuid, assetUuids);
94 } 96 }
95 else if (AssetType.Gesture == assetType) 97 else if ((sbyte)AssetType.Gesture == assetType)
96 { 98 {
97 GetGestureAssetUuids(assetUuid, assetUuids); 99 GetGestureAssetUuids(assetUuid, assetUuids);
98 } 100 }
99 else if (AssetType.Notecard == assetType) 101 else if ((sbyte)AssetType.Notecard == assetType)
100 { 102 {
101 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 103 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
102 } 104 }
103 else if (AssetType.LSLText == assetType) 105 else if ((sbyte)AssetType.LSLText == assetType)
104 { 106 {
105 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
106 } 108 }
107 else if (AssetType.Object == assetType) 109 else if ((sbyte)OpenSimAssetType.Material == assetType)
110 {
111 GetMaterialAssetUuids(assetUuid, assetUuids);
112 }
113 else if ((sbyte)AssetType.Object == assetType)
108 { 114 {
109 GetSceneObjectAssetUuids(assetUuid, assetUuids); 115 GetSceneObjectAssetUuids(assetUuid, assetUuids);
110 } 116 }
@@ -131,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 137 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
132 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. 138 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
133 /// </param> 139 /// </param>
134 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 140 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
135 { 141 {
136// m_log.DebugFormat( 142// m_log.DebugFormat(
137// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 143// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -151,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
151 { 157 {
152 // Get the prim's default texture. This will be used for faces which don't have their own texture 158 // Get the prim's default texture. This will be used for faces which don't have their own texture
153 if (textureEntry.DefaultTexture != null) 159 if (textureEntry.DefaultTexture != null)
154 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 160 assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
155 161
156 if (textureEntry.FaceTextures != null) 162 if (textureEntry.FaceTextures != null)
157 { 163 {
@@ -159,15 +165,37 @@ namespace OpenSim.Region.Framework.Scenes
159 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 165 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
160 { 166 {
161 if (texture != null) 167 if (texture != null)
162 assetUuids[texture.TextureID] = AssetType.Texture; 168 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
163 } 169 }
164 } 170 }
165 } 171 }
166 172
167 // If the prim is a sculpt then preserve this information too 173 // If the prim is a sculpt then preserve this information too
168 if (part.Shape.SculptTexture != UUID.Zero) 174 if (part.Shape.SculptTexture != UUID.Zero)
169 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 175 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
170 176
177 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
178 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
179
180 if (part.CollisionSound != UUID.Zero)
181 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
182
183 if (part.ParticleSystem.Length > 0)
184 {
185 try
186 {
187 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
188 if (ps.Texture != UUID.Zero)
189 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
190 }
191 catch (Exception e)
192 {
193 m_log.WarnFormat(
194 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
195 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
196 }
197 }
198
171 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 199 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
172 200
173 // Now analyze this prim's inventory items to preserve all the uuids that they reference 201 // Now analyze this prim's inventory items to preserve all the uuids that they reference
@@ -178,8 +206,18 @@ namespace OpenSim.Region.Framework.Scenes
178// tii.Name, tii.Type, part.Name, part.UUID); 206// tii.Name, tii.Type, part.Name, part.UUID);
179 207
180 if (!assetUuids.ContainsKey(tii.AssetID)) 208 if (!assetUuids.ContainsKey(tii.AssetID))
181 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 209 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
182 } 210 }
211
212 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
213 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
214 // inventory transfer. There needs to be a way for a module to register a method without assuming a
215 // Scene.EventManager is present.
216// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
217
218
219 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
220 GatherMaterialsUuids(part, assetUuids);
183 } 221 }
184 catch (Exception e) 222 catch (Exception e)
185 { 223 {
@@ -190,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
190 } 228 }
191 } 229 }
192 } 230 }
193 231
194// /// <summary> 232// /// <summary>
195// /// The callback made when we request the asset for an object from the asset service. 233// /// The callback made when we request the asset for an object from the asset service.
196// /// </summary> 234// /// </summary>
@@ -205,6 +243,75 @@ namespace OpenSim.Region.Framework.Scenes
205// } 243// }
206 244
207 /// <summary> 245 /// <summary>
246 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
247 /// stored in legacy format in part.DynAttrs
248 /// </summary>
249 /// <param name="part"></param>
250 /// <param name="assetUuids"></param>
251 //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
252 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
253 {
254 // scan thru the dynAttrs map of this part for any textures used as materials
255 OSD osdMaterials = null;
256
257 lock (part.DynAttrs)
258 {
259 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
260 {
261 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
262
263 if (materialsStore == null)
264 return;
265
266 materialsStore.TryGetValue("Materials", out osdMaterials);
267 }
268
269 if (osdMaterials != null)
270 {
271 //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
272
273 if (osdMaterials is OSDArray)
274 {
275 OSDArray matsArr = osdMaterials as OSDArray;
276 foreach (OSDMap matMap in matsArr)
277 {
278 try
279 {
280 if (matMap.ContainsKey("Material"))
281 {
282 OSDMap mat = matMap["Material"] as OSDMap;
283 if (mat.ContainsKey("NormMap"))
284 {
285 UUID normalMapId = mat["NormMap"].AsUUID();
286 if (normalMapId != UUID.Zero)
287 {
288 assetUuids[normalMapId] = (sbyte)AssetType.Texture;
289 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
290 }
291 }
292 if (mat.ContainsKey("SpecMap"))
293 {
294 UUID specularMapId = mat["SpecMap"].AsUUID();
295 if (specularMapId != UUID.Zero)
296 {
297 assetUuids[specularMapId] = (sbyte)AssetType.Texture;
298 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
299 }
300 }
301 }
302
303 }
304 catch (Exception e)
305 {
306 m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message);
307 }
308 }
309 }
310 }
311 }
312 }
313
314 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 315 /// Get an asset synchronously, potentially using an asynchronous callback. If the
209 /// asynchronous callback is used, we will wait for it to complete. 316 /// asynchronous callback is used, we will wait for it to complete.
210 /// </summary> 317 /// </summary>
@@ -242,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
242 /// </summary> 349 /// </summary>
243 /// <param name="scriptUuid"></param> 350 /// <param name="scriptUuid"></param>
244 /// <param name="assetUuids">Dictionary in which to record the references</param> 351 /// <param name="assetUuids">Dictionary in which to record the references</param>
245 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 352 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
246 { 353 {
247// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 354// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
248 355
@@ -262,7 +369,7 @@ namespace OpenSim.Region.Framework.Scenes
262 369
263 // Embedded asset references (if not false positives) could be for many types of asset, so we will 370 // Embedded asset references (if not false positives) could be for many types of asset, so we will
264 // label these as unknown. 371 // label these as unknown.
265 assetUuids[uuid] = AssetType.Unknown; 372 assetUuids[uuid] = (sbyte)AssetType.Unknown;
266 } 373 }
267 } 374 }
268 } 375 }
@@ -272,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
272 /// </summary> 379 /// </summary>
273 /// <param name="wearableAssetUuid"></param> 380 /// <param name="wearableAssetUuid"></param>
274 /// <param name="assetUuids">Dictionary in which to record the references</param> 381 /// <param name="assetUuids">Dictionary in which to record the references</param>
275 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 382 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
276 { 383 {
277 AssetBase assetBase = GetAsset(wearableAssetUuid); 384 AssetBase assetBase = GetAsset(wearableAssetUuid);
278 385
@@ -287,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes
287 394
288 foreach (UUID uuid in wearableAsset.Textures.Values) 395 foreach (UUID uuid in wearableAsset.Textures.Values)
289 { 396 {
290 assetUuids[uuid] = AssetType.Texture; 397 assetUuids[uuid] = (sbyte)AssetType.Texture;
291 } 398 }
292 } 399 }
293 } 400 }
@@ -299,7 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
299 /// </summary> 406 /// </summary>
300 /// <param name="sceneObject"></param> 407 /// <param name="sceneObject"></param>
301 /// <param name="assetUuids"></param> 408 /// <param name="assetUuids"></param>
302 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 409 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
303 { 410 {
304 AssetBase objectAsset = GetAsset(sceneObjectUuid); 411 AssetBase objectAsset = GetAsset(sceneObjectUuid);
305 412
@@ -328,7 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
328 /// </summary> 435 /// </summary>
329 /// <param name="gestureUuid"></param> 436 /// <param name="gestureUuid"></param>
330 /// <param name="assetUuids"></param> 437 /// <param name="assetUuids"></param>
331 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 438 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
332 { 439 {
333 AssetBase assetBase = GetAsset(gestureUuid); 440 AssetBase assetBase = GetAsset(gestureUuid);
334 if (null == assetBase) 441 if (null == assetBase)
@@ -362,9 +469,29 @@ namespace OpenSim.Region.Framework.Scenes
362 // If it can be parsed as a UUID, it is an asset ID 469 // If it can be parsed as a UUID, it is an asset ID
363 UUID uuid; 470 UUID uuid;
364 if (UUID.TryParse(id, out uuid)) 471 if (UUID.TryParse(id, out uuid))
365 assetUuids[uuid] = AssetType.Animation; 472 assetUuids[uuid] = (sbyte)AssetType.Animation;
366 } 473 }
367 } 474 }
475
476 /// <summary>
477 /// Get the asset uuid's referenced in a material.
478 /// </summary>
479 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
480 {
481 AssetBase assetBase = GetAsset(materialUuid);
482 if (null == assetBase)
483 return;
484
485 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
486
487 UUID normMap = mat["NormMap"].AsUUID();
488 if (normMap != UUID.Zero)
489 assetUuids[normMap] = (sbyte)AssetType.Texture;
490
491 UUID specMap = mat["SpecMap"].AsUUID();
492 if (specMap != UUID.Zero)
493 assetUuids[specMap] = (sbyte)AssetType.Texture;
494 }
368 } 495 }
369 496
370 public class HGUuidGatherer : UuidGatherer 497 public class HGUuidGatherer : UuidGatherer