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.cs203
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs43
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs930
-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.cs678
-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.cs2701
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs65
-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, 6288 insertions, 2817 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index af4b23d..3d2e083 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..746a5ce 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;
@@ -2068,9 +2096,6 @@ namespace OpenSim.Region.Framework.Scenes
2068 // If child prims have invalid perms, fix them 2096 // If child prims have invalid perms, fix them
2069 grp.AdjustChildPrimPermissions(); 2097 grp.AdjustChildPrimPermissions();
2070 2098
2071 // If child prims have invalid perms, fix them
2072 grp.AdjustChildPrimPermissions();
2073
2074 if (remoteClient == null) 2099 if (remoteClient == null)
2075 { 2100 {
2076 // Autoreturn has a null client. Nothing else does. So 2101 // Autoreturn has a null client. Nothing else does. So
@@ -2124,7 +2149,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2149 {
2125 // If we don't have permission, stop right here 2150 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2151 if (!permissionToTakeCopy)
2152 {
2153 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2154 return;
2155 }
2128 2156
2129 permissionToTake = true; 2157 permissionToTake = true;
2130 // Don't delete 2158 // Don't delete
@@ -2277,6 +2305,88 @@ namespace OpenSim.Region.Framework.Scenes
2277 } 2305 }
2278 2306
2279 /// <summary> 2307 /// <summary>
2308 /// Returns the list of Scene Objects in an asset.
2309 /// </summary>
2310 /// <remarks>
2311 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2312 /// </remarks>
2313 /// <param name="assetData">Asset data</param>
2314 /// <param name="attachment">Whether the item is an attachment</param>
2315 /// <param name="objlist">The objects included in the asset</param>
2316 /// <param name="veclist">Relative positions of the objects</param>
2317 /// <param name="bbox">Bounding box of all the objects</param>
2318 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2319 /// to the centre of the root prim (relevant only when returning a single object)</param>
2320 /// <returns>true = returning a single object; false = multiple objects</returns>
2321 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2322 out Vector3 bbox, out float offsetHeight)
2323 {
2324 objlist = new List<SceneObjectGroup>();
2325 veclist = new List<Vector3>();
2326
2327 XmlDocument doc = new XmlDocument();
2328 string xmlData = Utils.BytesToString(assetData);
2329 doc.LoadXml(xmlData);
2330 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2331
2332 if (e == null || attachment) // Single
2333 {
2334 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2335/*
2336 if (!attachment)
2337 {
2338 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2339 g.RootPart.AttachedPos = g.AbsolutePosition;
2340 g.RootPart.AttachRotation = g.GroupRotation;
2341 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2342 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2343 g.RootPart.Shape.State = 0;
2344 }
2345*/
2346 objlist.Add(g);
2347 veclist.Add(new Vector3(0, 0, 0));
2348 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2349 return true;
2350 }
2351 else
2352 {
2353 XmlElement coll = (XmlElement)e;
2354 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2355 float by = Convert.ToSingle(coll.GetAttribute("y"));
2356 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2357 bbox = new Vector3(bx, by, bz);
2358 offsetHeight = 0;
2359
2360 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2361 foreach (XmlNode n in groups)
2362 {
2363 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2364/*
2365 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2366 g.RootPart.AttachedPos = g.AbsolutePosition;
2367 g.RootPart.AttachRotation = g.GroupRotation;
2368 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2369 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2370 g.RootPart.Shape.State = 0;
2371*/
2372 objlist.Add(g);
2373
2374 XmlElement el = (XmlElement)n;
2375 string rawX = el.GetAttribute("offsetx");
2376 string rawY = el.GetAttribute("offsety");
2377 string rawZ = el.GetAttribute("offsetz");
2378
2379 float x = Convert.ToSingle(rawX);
2380 float y = Convert.ToSingle(rawY);
2381 float z = Convert.ToSingle(rawZ);
2382 veclist.Add(new Vector3(x, y, z));
2383 }
2384 }
2385
2386 return false;
2387 }
2388
2389 /// <summary>
2280 /// Event Handler Rez an object into a scene 2390 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler 2391 /// Calls the non-void event handler
2282 /// </summary> 2392 /// </summary>
@@ -2351,19 +2461,25 @@ namespace OpenSim.Region.Framework.Scenes
2351 /// will be used if it exists.</param> 2461 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param> 2462 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param> 2463 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2464 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual SceneObjectGroup RezObject( 2465 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2466 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 { 2467 {
2358 if (null == item) 2468 if (null == item)
2359 return null; 2469 return null;
2470
2471 List<SceneObjectGroup> objlist;
2472 List<Vector3> veclist;
2360 2473
2361 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2474 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2362 2475 if (!success)
2363 if (null == group)
2364 return null; 2476 return null;
2365 2477
2366 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2478 int totalPrims = 0;
2479 foreach (SceneObjectGroup group in objlist)
2480 totalPrims += group.PrimCount;
2481
2482 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2367 return null; 2483 return null;
2368 2484
2369 if (!Permissions.BypassPermissions()) 2485 if (!Permissions.BypassPermissions())
@@ -2372,16 +2488,28 @@ namespace OpenSim.Region.Framework.Scenes
2372 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2488 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2373 } 2489 }
2374 2490
2375 group.FromPartID = sourcePart.UUID; 2491 for (int i = 0; i < objlist.Count; i++)
2376 AddNewSceneObject(group, true, pos, rot, vel); 2492 {
2377 2493 SceneObjectGroup group = objlist[i];
2378 // We can only call this after adding the scene object, since the scene object references the scene 2494 Vector3 curpos = pos + veclist[i];
2379 // to find out if scripts should be activated at all. 2495
2380 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2496 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2381 2497 {
2382 group.ScheduleGroupForFullUpdate(); 2498 group.RootPart.AttachedPos = group.AbsolutePosition;
2383 2499 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2384 return group; 2500 }
2501
2502 group.FromPartID = sourcePart.UUID;
2503 AddNewSceneObject(group, true, curpos, rot, vel);
2504
2505 // We can only call this after adding the scene object, since the scene object references the scene
2506 // to find out if scripts should be activated at all.
2507 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2508
2509 group.ScheduleGroupForFullUpdate();
2510 }
2511
2512 return objlist;
2385 } 2513 }
2386 2514
2387 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2515 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
@@ -2576,12 +2704,17 @@ namespace OpenSim.Region.Framework.Scenes
2576 return; 2704 return;
2577 } 2705 }
2578 2706
2707 bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0;
2579 m_sceneGraph.LinkObjects(root, children); 2708 m_sceneGraph.LinkObjects(root, children);
2580 2709
2581 ScenePresence sp; 2710 ScenePresence sp;
2582 if (TryGetScenePresence(agentId, out sp)) 2711 if (TryGetScenePresence(agentId, out sp))
2583 { 2712 {
2584 root.SendPropertiesToClient(sp.ControllingClient); 2713 root.SendPropertiesToClient(sp.ControllingClient);
2714 if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0)
2715 {
2716 sp.ControllingClient.SendAlertMessage("Object physics canceled");
2717 }
2585 } 2718 }
2586 } 2719 }
2587 2720
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..eb34f55 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;
@@ -221,6 +227,13 @@ namespace OpenSim.Region.Framework.Scenes
221 get { return m_defaultDrawDistance; } 227 get { return m_defaultDrawDistance; }
222 } 228 }
223 229
230// protected float m_maxDrawDistance = 512.0f;
231 protected float m_maxDrawDistance = 256.0f;
232 public float MaxDrawDistance
233 {
234 get { return m_maxDrawDistance; }
235 }
236
224 private List<string> m_AllowedViewers = new List<string>(); 237 private List<string> m_AllowedViewers = new List<string>();
225 private List<string> m_BannedViewers = new List<string>(); 238 private List<string> m_BannedViewers = new List<string>();
226 239
@@ -230,6 +243,8 @@ namespace OpenSim.Region.Framework.Scenes
230 public bool m_seeIntoBannedRegion = false; 243 public bool m_seeIntoBannedRegion = false;
231 public int MaxUndoCount = 5; 244 public int MaxUndoCount = 5;
232 245
246 public bool SeeIntoRegion { get; set; }
247
233 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 248 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
234 public bool LoginLock = false; 249 public bool LoginLock = false;
235 250
@@ -396,10 +411,12 @@ namespace OpenSim.Region.Framework.Scenes
396 if (value) 411 if (value)
397 { 412 {
398 if (!m_active) 413 if (!m_active)
399 Start(); 414 Start(false);
400 } 415 }
401 else 416 else
402 { 417 {
418 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
419 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
403 m_active = false; 420 m_active = false;
404 } 421 }
405 } 422 }
@@ -747,6 +764,7 @@ namespace OpenSim.Region.Framework.Scenes
747 m_config = config; 764 m_config = config;
748 MinFrameTime = 0.089f; 765 MinFrameTime = 0.089f;
749 MinMaintenanceTime = 1; 766 MinMaintenanceTime = 1;
767 SeeIntoRegion = true;
750 768
751 Random random = new Random(); 769 Random random = new Random();
752 770
@@ -851,7 +869,8 @@ namespace OpenSim.Region.Framework.Scenes
851 869
852 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 870 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
853 871
854 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); 872 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
873 m_defaultDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
855 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 874 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
856 if (!UseBackup) 875 if (!UseBackup)
857 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 876 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -859,9 +878,12 @@ namespace OpenSim.Region.Framework.Scenes
859 //Animation states 878 //Animation states
860 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 879 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
861 880
881 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
882
883 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
884
862 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 885 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
863 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 886 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
864
865 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 887 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
866 if (RegionInfo.NonphysPrimMin > 0) 888 if (RegionInfo.NonphysPrimMin > 0)
867 { 889 {
@@ -893,6 +915,9 @@ namespace OpenSim.Region.Framework.Scenes
893 m_linksetCapacity = RegionInfo.LinksetCapacity; 915 m_linksetCapacity = RegionInfo.LinksetCapacity;
894 } 916 }
895 917
918 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
919
920
896 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 921 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
897 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 922 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
898 923
@@ -1052,7 +1077,7 @@ namespace OpenSim.Region.Framework.Scenes
1052 1077
1053 BordersLocked = true; 1078 BordersLocked = true;
1054 Border northBorder = new Border(); 1079 Border northBorder = new Border();
1055 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1080 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeY); //<---
1056 northBorder.CrossDirection = Cardinals.N; 1081 northBorder.CrossDirection = Cardinals.N;
1057 NorthBorders.Add(northBorder); 1082 NorthBorders.Add(northBorder);
1058 1083
@@ -1062,7 +1087,7 @@ namespace OpenSim.Region.Framework.Scenes
1062 SouthBorders.Add(southBorder); 1087 SouthBorders.Add(southBorder);
1063 1088
1064 Border eastBorder = new Border(); 1089 Border eastBorder = new Border();
1065 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1090 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeX); //<---
1066 eastBorder.CrossDirection = Cardinals.E; 1091 eastBorder.CrossDirection = Cardinals.E;
1067 EastBorders.Add(eastBorder); 1092 EastBorders.Add(eastBorder);
1068 1093
@@ -1075,6 +1100,7 @@ namespace OpenSim.Region.Framework.Scenes
1075 m_eventManager = new EventManager(); 1100 m_eventManager = new EventManager();
1076 1101
1077 m_permissions = new ScenePermissions(this); 1102 m_permissions = new ScenePermissions(this);
1103
1078 } 1104 }
1079 1105
1080 #endregion 1106 #endregion
@@ -1332,7 +1358,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 Thread.Sleep(500); 1358 Thread.Sleep(500);
1333 1359
1334 // Stop all client threads. 1360 // Stop all client threads.
1335 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1361 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1336 1362
1337 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1363 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1338 EventManager.TriggerSceneShuttingDown(this); 1364 EventManager.TriggerSceneShuttingDown(this);
@@ -1361,10 +1387,18 @@ namespace OpenSim.Region.Framework.Scenes
1361 } 1387 }
1362 } 1388 }
1363 1389
1390 public override void Start()
1391 {
1392 Start(true);
1393 }
1394
1364 /// <summary> 1395 /// <summary>
1365 /// Start the scene 1396 /// Start the scene
1366 /// </summary> 1397 /// </summary>
1367 public void Start() 1398 /// <param name='startScripts'>
1399 /// Start the scripts within the scene.
1400 /// </param>
1401 public void Start(bool startScripts)
1368 { 1402 {
1369 m_active = true; 1403 m_active = true;
1370 1404
@@ -1401,6 +1435,8 @@ namespace OpenSim.Region.Framework.Scenes
1401 m_heartbeatThread 1435 m_heartbeatThread
1402 = Watchdog.StartThread( 1436 = Watchdog.StartThread(
1403 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1437 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1438
1439 StartScripts();
1404 } 1440 }
1405 1441
1406 /// <summary> 1442 /// <summary>
@@ -1557,6 +1593,8 @@ namespace OpenSim.Region.Framework.Scenes
1557 1593
1558 try 1594 try
1559 { 1595 {
1596 EventManager.TriggerRegionHeartbeatStart(this);
1597
1560 // Apply taints in terrain module to terrain in physics scene 1598 // Apply taints in terrain module to terrain in physics scene
1561 if (Frame % m_update_terrain == 0) 1599 if (Frame % m_update_terrain == 0)
1562 { 1600 {
@@ -1996,6 +2034,11 @@ namespace OpenSim.Region.Framework.Scenes
1996 2034
1997 GridRegion region = new GridRegion(RegionInfo); 2035 GridRegion region = new GridRegion(RegionInfo);
1998 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2036 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2037 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
2038 LogHeader, m_regionName,
2039 RegionInfo.RegionID,
2040 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2041 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1999 if (error != String.Empty) 2042 if (error != String.Empty)
2000 throw new Exception(error); 2043 throw new Exception(error);
2001 } 2044 }
@@ -2444,7 +2487,7 @@ namespace OpenSim.Region.Framework.Scenes
2444 foreach (UUID av in avatars) 2487 foreach (UUID av in avatars)
2445 { 2488 {
2446 ScenePresence p = GetScenePresence(av); 2489 ScenePresence p = GetScenePresence(av);
2447 if (p != null) 2490 if (p != null && p.ParentUUID == UUID.Zero)
2448 p.StandUp(); 2491 p.StandUp();
2449 } 2492 }
2450 2493
@@ -2514,6 +2557,11 @@ namespace OpenSim.Region.Framework.Scenes
2514 return false; 2557 return false;
2515 } 2558 }
2516 2559
2560
2561 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2562 {
2563 m_sceneGraph.updateScenePartGroup(part, grp);
2564 }
2517 /// <summary> 2565 /// <summary>
2518 /// Move the given scene object into a new region depending on which region its absolute position has moved 2566 /// Move the given scene object into a new region depending on which region its absolute position has moved
2519 /// into. 2567 /// into.
@@ -2935,14 +2983,15 @@ namespace OpenSim.Region.Framework.Scenes
2935 2983
2936 #region Add/Remove Avatar Methods 2984 #region Add/Remove Avatar Methods
2937 2985
2938 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2986 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2939 { 2987 {
2940 ScenePresence sp; 2988 ScenePresence sp;
2941 bool vialogin; 2989 bool vialogin;
2990 bool reallyNew = true;
2942 2991
2943 // Validation occurs in LLUDPServer 2992 // Validation occurs in LLUDPServer
2944 // 2993 //
2945 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2994 // 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. 2995 // each other. In practice, this does not currently occur in the code.
2947 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2996 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2948 2997
@@ -2950,9 +2999,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 2999 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2951 // whilst connecting). 3000 // whilst connecting).
2952 // 3001 //
2953 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 3002 // 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 3003 // 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. 3004 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2956 // 3005 //
2957 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 3006 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2958 // AddNewClient() operations (though not other ops). 3007 // AddNewClient() operations (though not other ops).
@@ -2969,18 +3018,23 @@ namespace OpenSim.Region.Framework.Scenes
2969 3018
2970 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 3019 // 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 3020 // 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 3021 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2973 // connected. 3022 // connected.
2974 if (sp == null) 3023 if (sp == null)
2975 { 3024 {
2976 m_log.DebugFormat( 3025 m_log.DebugFormat(
2977 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3026 "[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); 3027 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
3028 ((TPFlags)aCircuit.teleportFlags).ToString());
2979 3029
2980 m_clientManager.Add(client); 3030 m_clientManager.Add(client);
2981 SubscribeToClientEvents(client); 3031 SubscribeToClientEvents(client);
2982 3032
2983 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 3033 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3034
3035 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3036
3037/* done in completMovement
2984 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46); 3038 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
2985 if (cof == null) 3039 if (cof == null)
2986 sp.COF = UUID.Zero; 3040 sp.COF = UUID.Zero;
@@ -2988,25 +3042,33 @@ namespace OpenSim.Region.Framework.Scenes
2988 sp.COF = cof.ID; 3042 sp.COF = cof.ID;
2989 3043
2990 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF); 3044 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
3045 */
2991 m_eventManager.TriggerOnNewPresence(sp); 3046 m_eventManager.TriggerOnNewPresence(sp);
2992 3047
2993 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2994 } 3048 }
2995 else 3049 else
2996 { 3050 {
2997 m_log.WarnFormat( 3051 m_log.WarnFormat(
2998 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3052 "[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); 3053 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3054 reallyNew = false;
3000 } 3055 }
3001 3056
3002 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3057 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3003 // client is for a root or child agent. 3058 // client is for a root or child agent.
3059 // XXX: This may be better set for a new client before that client is added to the client manager.
3060 // But need to know what happens in the case where a ScenePresence is already present (and if this
3061 // actually occurs).
3004 client.SceneAgent = sp; 3062 client.SceneAgent = sp;
3005 3063
3006 // Cache the user's name 3064 // This is currently also being done earlier in NewUserConnection for real users to see if this
3065 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3066 // places. However, we still need to do it here for NPCs.
3007 CacheUserName(sp, aCircuit); 3067 CacheUserName(sp, aCircuit);
3008 3068
3009 EventManager.TriggerOnNewClient(client); 3069 if (reallyNew)
3070 EventManager.TriggerOnNewClient(client);
3071
3010 if (vialogin) 3072 if (vialogin)
3011 EventManager.TriggerOnClientLogin(client); 3073 EventManager.TriggerOnClientLogin(client);
3012 } 3074 }
@@ -3027,7 +3089,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3089 {
3028 string first = aCircuit.firstname, last = aCircuit.lastname; 3090 string first = aCircuit.firstname, last = aCircuit.lastname;
3029 3091
3030 if (sp.PresenceType == PresenceType.Npc) 3092 if (sp != null && sp.PresenceType == PresenceType.Npc)
3031 { 3093 {
3032 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3094 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
3033 } 3095 }
@@ -3100,12 +3162,13 @@ namespace OpenSim.Region.Framework.Scenes
3100 // and the scene presence and the client, if they exist 3162 // and the scene presence and the client, if they exist
3101 try 3163 try
3102 { 3164 {
3103 ScenePresence sp = GetScenePresence(agentID); 3165 ScenePresence sp = WaitGetScenePresence(agentID);
3104 3166
3105 if (sp != null) 3167 if (sp != null)
3106 { 3168 {
3107 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3169 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3108 sp.ControllingClient.Close(); 3170
3171 CloseAgent(sp.UUID, false);
3109 } 3172 }
3110 3173
3111 // BANG! SLASH! 3174 // BANG! SLASH!
@@ -3244,8 +3307,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 { 3307 {
3245 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3308 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3246 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3309 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3247 client.OnSetStartLocationRequest += SetHomeRezPoint;
3248 client.OnRegionHandleRequest += RegionHandleRequest;
3249 } 3310 }
3250 3311
3251 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3312 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
@@ -3371,8 +3432,6 @@ namespace OpenSim.Region.Framework.Scenes
3371 { 3432 {
3372 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3433 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3373 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3434 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3374 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3375 client.OnRegionHandleRequest -= RegionHandleRequest;
3376 } 3435 }
3377 3436
3378 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3437 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3498,33 +3557,6 @@ namespace OpenSim.Region.Framework.Scenes
3498 } 3557 }
3499 3558
3500 /// <summary> 3559 /// <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. 3560 /// Get the avatar apperance for the given client.
3529 /// </summary> 3561 /// </summary>
3530 /// <param name="client"></param> 3562 /// <param name="client"></param>
@@ -3548,63 +3580,73 @@ namespace OpenSim.Region.Framework.Scenes
3548 } 3580 }
3549 } 3581 }
3550 3582
3551 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3583 /// <summary>
3584 /// Remove the given client from the scene.
3585 /// </summary>
3586 /// <remarks>
3587 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3588 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3589 /// from viewers).
3590 /// </remarks>
3591 /// <param name='agentID'>ID of agent to close</param>
3592 /// <param name='closeChildAgents'>
3593 /// Close the neighbour child agents associated with this client.
3594 /// </param>
3595 ///
3596
3597 private object m_removeClientPrivLock = new Object();
3598
3599 public void RemoveClient(UUID agentID, bool closeChildAgents)
3552 { 3600 {
3553// CheckHeartbeat(); 3601 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3554 bool isChildAgent = false;
3555 AgentCircuitData acd;
3556 3602
3557 lock (m_removeClientLock) 3603 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3604 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3605 // However, will keep for now just in case.
3606 if (acd == null)
3558 { 3607 {
3559 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3608 m_log.ErrorFormat(
3609 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3560 3610
3561 if (acd == null) 3611 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 } 3612 }
3574 3613 else
3575 lock (acd)
3576 { 3614 {
3615 m_authenticateHandler.RemoveCircuit(agentID);
3616 }
3617
3618 // TODO: Can we now remove this lock?
3619 lock (m_removeClientPrivLock)
3620 {
3621 bool isChildAgent = false;
3622
3577 ScenePresence avatar = GetScenePresence(agentID); 3623 ScenePresence avatar = GetScenePresence(agentID);
3578 3624
3625 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3626 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3627 // However, will keep for now just in case.
3579 if (avatar == null) 3628 if (avatar == null)
3580 { 3629 {
3581 m_log.WarnFormat( 3630 m_log.ErrorFormat(
3582 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3631 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3583 3632
3584 return; 3633 return;
3585 } 3634 }
3586 3635
3587 try 3636 try
3588 { 3637 {
3589 isChildAgent = avatar.IsChildAgent; 3638 isChildAgent = avatar.IsChildAgent;
3590 3639
3591 m_log.DebugFormat( 3640 m_log.DebugFormat(
3592 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3641 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3593 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3642 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3594 3643
3595 // Don't do this to root agents, it's not nice for the viewer 3644 // Don't do this to root agents, it's not nice for the viewer
3596 if (closeChildAgents && isChildAgent) 3645 if (closeChildAgents && isChildAgent)
3597 { 3646 {
3598 // Tell a single agent to disconnect from the region. 3647 // Tell a single agent to disconnect from the region.
3599 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3648 // Let's do this via UDP
3600 if (eq != null) 3649 avatar.ControllingClient.SendShutdownConnectionNotice();
3601 {
3602 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3603 }
3604 else
3605 {
3606 avatar.ControllingClient.SendShutdownConnectionNotice();
3607 }
3608 } 3650 }
3609 3651
3610 // Only applies to root agents. 3652 // Only applies to root agents.
@@ -3620,40 +3662,44 @@ namespace OpenSim.Region.Framework.Scenes
3620 if (closeChildAgents && CapsModule != null) 3662 if (closeChildAgents && CapsModule != null)
3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); 3663 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3622 3664
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) 3665 if (closeChildAgents && !isChildAgent)
3629 { 3666 {
3630 List<ulong> regions = avatar.KnownRegionHandles; 3667 List<ulong> regions = avatar.KnownRegionHandles;
3631 regions.Remove(RegionInfo.RegionHandle); 3668 regions.Remove(RegionInfo.RegionHandle);
3632 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3669
3670 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3671 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3633 } 3672 }
3634 3673
3635 m_eventManager.TriggerClientClosed(agentID, this); 3674 m_eventManager.TriggerClientClosed(agentID, this);
3675// m_log.Debug("[Scene]TriggerClientClosed done");
3636 m_eventManager.TriggerOnRemovePresence(agentID); 3676 m_eventManager.TriggerOnRemovePresence(agentID);
3677// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3637 3678
3638 if (!isChildAgent) 3679 if (!isChildAgent)
3639 { 3680 {
3640 if (AttachmentsModule != null) 3681 if (AttachmentsModule != null)
3641 { 3682 {
3683// m_log.Debug("[Scene]DeRezAttachments");
3642 AttachmentsModule.DeRezAttachments(avatar); 3684 AttachmentsModule.DeRezAttachments(avatar);
3685// m_log.Debug("[Scene]DeRezAttachments done");
3643 } 3686 }
3644 3687
3645 ForEachClient( 3688 ForEachClient(
3646 delegate(IClientAPI client) 3689 delegate(IClientAPI client)
3647 { 3690 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3691 //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 }); } 3692 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3693 catch (NullReferenceException) { }
3651 }); 3694 });
3652 } 3695 }
3653 3696
3654 // It's possible for child agents to have transactions if changes are being made cross-border. 3697 // It's possible for child agents to have transactions if changes are being made cross-border.
3655 if (AgentTransactionsModule != null) 3698 if (AgentTransactionsModule != null)
3699 {
3700// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3656 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3701 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3702 }
3657 m_log.Debug("[Scene] The avatar has left the building"); 3703 m_log.Debug("[Scene] The avatar has left the building");
3658 } 3704 }
3659 catch (Exception e) 3705 catch (Exception e)
@@ -3727,7 +3773,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3773 }
3728 deleteIDs.Add(localID); 3774 deleteIDs.Add(localID);
3729 } 3775 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3776
3777 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3778 }
3732 3779
3733 #endregion 3780 #endregion
@@ -3763,13 +3810,16 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3810 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3811 /// the LLUDP stack).
3765 /// </remarks> 3812 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3813 /// <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> 3814 /// <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 3815 /// <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> 3816 /// 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 3817 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3818 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3819 ///
3820 private object m_newUserConnLock = new object();
3821
3822 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3823 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3824 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3825 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,17 +3839,19 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3839 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})", 3840 "[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, 3841 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3842 (acd.child ? "child" : "root"),
3793 agent.firstname, 3843 acd.firstname,
3794 agent.lastname, 3844 acd.lastname,
3795 agent.AgentID, 3845 acd.AgentID,
3796 agent.circuitcode, 3846 acd.circuitcode,
3797 agent.IPAddress, 3847 acd.IPAddress,
3798 agent.Viewer, 3848 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3849 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3850 acd.startpos
3801 ); 3851 );
3802 3852
3853// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3854
3803 if (!LoginsEnabled) 3855 if (!LoginsEnabled)
3804 { 3856 {
3805 reason = "Logins Disabled"; 3857 reason = "Logins Disabled";
@@ -3815,7 +3867,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3867 {
3816 foreach (string viewer in m_AllowedViewers) 3868 foreach (string viewer in m_AllowedViewers)
3817 { 3869 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3870 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3871 {
3820 ViewerDenied = false; 3872 ViewerDenied = false;
3821 break; 3873 break;
@@ -3832,7 +3884,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3884 {
3833 foreach (string viewer in m_BannedViewers) 3885 foreach (string viewer in m_BannedViewers)
3834 { 3886 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3887 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3888 {
3837 ViewerDenied = true; 3889 ViewerDenied = true;
3838 break; 3890 break;
@@ -3844,54 +3896,135 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3896 {
3845 m_log.DebugFormat( 3897 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3898 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3899 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3900 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3901 return false;
3850 } 3902 }
3851 3903
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3904 ILandObject land;
3905 ScenePresence sp;
3853 3906
3854 // If we have noo presence here or if that presence is a zombie root 3907 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3908 {
3858 if (CapsModule != null) 3909 sp = GetScenePresence(acd.AgentID);
3910
3911 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3912 // closed.
3913 if (sp != null && sp.IsChildAgent
3914 && (sp.LifecycleState == ScenePresenceState.Running
3915 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3916 {
3860 lock (agent) 3917 m_log.DebugFormat(
3918 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3919 sp.Name, sp.LifecycleState, Name);
3920
3921 // In the case where, for example, an A B C D region layout, an avatar may
3922 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3923 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3924 //
3925 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3926 // teleport, since realistically, the close request should always be processed before any other
3927 // region tried to re-establish a child agent. This is much simpler since the logic below is
3928 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3929 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3930 // flag when no teleport had taken place (and hence no close was going to come).
3931// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3932// {
3933// m_log.DebugFormat(
3934// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3935// sp.Name, Name);
3936//
3937// sp.DoNotCloseAfterTeleport = true;
3938// }
3939// else if (EntityTransferModule.IsInTransit(sp.UUID))
3940
3941 sp.LifecycleState = ScenePresenceState.Running;
3942
3943 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3944 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3945 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3946
3947 m_log.DebugFormat(
3948 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3949 sp.Name, Name);
3864 } 3950 }
3865 } 3951 }
3866 } 3952 }
3867 3953
3954 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3955 // allow unpredictable things to happen.
3868 if (sp != null) 3956 if (sp != null)
3869 { 3957 {
3870 if (!sp.IsChildAgent) 3958 const int polls = 10;
3959 const int pollInterval = 1000;
3960 int pollsLeft = polls;
3961
3962 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3963 Thread.Sleep(pollInterval);
3964
3965 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3966 {
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( 3967 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3968 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3969 sp.Name, Name, polls * pollInterval / 1000);
3878 3970
3879 sp.ControllingClient.Close(true, true); 3971 return false;
3880 sp = null; 3972 }
3973 else if (polls != pollsLeft)
3974 {
3975 m_log.DebugFormat(
3976 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3977 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3978 }
3882 } 3979 }
3883 3980
3884 lock (agent) 3981 // TODO: can we remove this lock?
3982 lock (m_newUserConnLock)
3885 { 3983 {
3886 //On login test land permisions 3984 if (sp != null && !sp.IsChildAgent)
3985 {
3986 // We have a root agent. Is it in transit?
3987 if (!EntityTransferModule.IsInTransit(sp.UUID))
3988 {
3989 // We have a zombie from a crashed session.
3990 // Or the same user is trying to be root twice here, won't work.
3991 // Kill it.
3992 m_log.WarnFormat(
3993 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3994 sp.Name, sp.UUID, RegionInfo.RegionName);
3995
3996 if (sp.ControllingClient != null)
3997 CloseAgent(sp.UUID, true);
3998
3999 sp = null;
4000 }
4001 //else
4002 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
4003 }
4004
4005 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
4006 // We need the circuit data here for some of the subsequent checks. (groups, for example)
4007 // If the checks fail, we remove the circuit.
4008 acd.teleportFlags = teleportFlags;
4009
4010 // Remove any preexisting circuit - we don't want duplicates
4011 // This is a stab at preventing avatar "ghosting"
4012 if (vialogin)
4013 m_authenticateHandler.RemoveCircuit(acd.AgentID);
4014
4015 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
4016
4017 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
4018
4019 // On login test land permisions
3887 if (vialogin) 4020 if (vialogin)
3888 { 4021 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 4022 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 4023 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 4024 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 4025 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 4026 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 4027 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 4028 return false;
3896 } 4029 }
3897 } 4030 }
@@ -3902,84 +4035,97 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 4035 {
3903 try 4036 try
3904 { 4037 {
3905 if (!VerifyUserPresence(agent, out reason)) 4038 if (!VerifyUserPresence(acd, out reason))
4039 {
4040 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 4041 return false;
3907 } catch (Exception e) 4042 }
4043 }
4044 catch (Exception e)
3908 { 4045 {
3909 m_log.ErrorFormat( 4046 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 4047 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
4048
4049 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 4050 return false;
3912 } 4051 }
3913 } 4052 }
3914 4053
3915 try 4054 try
3916 { 4055 {
3917 // Always check estate if this is a login. Always 4056 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 4057 {
3921 if (!AuthorizeUser(agent, out reason)) 4058 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 4059 return false;
3923 return false;
3924 }
3925 } 4060 }
3926 } 4061 }
3927 catch (Exception e) 4062 catch (Exception e)
3928 { 4063 {
3929 m_log.ErrorFormat( 4064 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4065 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4066
4067 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4068 return false;
3932 } 4069 }
3933 4070
3934 m_log.InfoFormat( 4071 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4072 "[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, 4073 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4074 acd.AgentID, acd.circuitcode);
3938 4075
4076 if (CapsModule != null)
4077 {
4078 CapsModule.SetAgentCapsSeeds(acd);
4079 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4080 }
3939 } 4081 }
3940 else 4082 else
3941 { 4083 {
3942 // Let the SP know how we got here. This has a lot of interesting 4084 // Let the SP know how we got here. This has a lot of interesting
3943 // uses down the line. 4085 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4086 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4087
3946 if (sp.IsChildAgent) 4088 if (sp.IsChildAgent)
3947 { 4089 {
3948 m_log.DebugFormat( 4090 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4091 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4092 acd.AgentID, RegionInfo.RegionName);
3951
3952 sp.AdjustKnownSeeds();
3953 4093
3954 if (CapsModule != null) 4094 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4095 {
4096 CapsModule.SetAgentCapsSeeds(acd);
4097 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4098 }
4099
4100 sp.AdjustKnownSeeds();
3956 } 4101 }
3957 } 4102 }
3958 }
3959 4103
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4104 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4105 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4106 // request for the HG avatar appears to trigger before the user name is cached.
4107 CacheUserName(null, acd);
4108 }
3963 4109
3964 if (CapsModule != null) 4110 if (CapsModule != null)
3965 { 4111 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4112 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4113 }
3968 4114
3969 if (vialogin) 4115 if (vialogin)
3970 { 4116 {
3971// CleanDroppedAttachments(); 4117// CleanDroppedAttachments();
3972 4118
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4119 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4120 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4121 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4122 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4123 }
3978 4124
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4125 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4126 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4127 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4128 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4129 }
3984 4130
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4131 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,68 +4135,88 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4135 {
3990 lock (EastBorders) 4136 lock (EastBorders)
3991 { 4137 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4138 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4139 {
3994 m_log.Warn("FIX AGENT POSITION"); 4140 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4141 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4142 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4143 acd.startpos.Z = 720;
3998 } 4144 }
3999 } 4145 }
4000 lock (NorthBorders) 4146 lock (NorthBorders)
4001 { 4147 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4148 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4149 {
4004 m_log.Warn("FIX Agent POSITION"); 4150 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4151 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4152 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4153 acd.startpos.Z = 720;
4008 } 4154 }
4009 } 4155 }
4010 } else 4156 } else
4011 { 4157 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4158 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4159 {
4014 m_log.Warn("FIX AGENT POSITION"); 4160 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4161 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4162 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4163 acd.startpos.Z = 720;
4018 } 4164 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4165 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4166 {
4021 m_log.Warn("FIX Agent POSITION"); 4167 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4168 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4169 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4170 acd.startpos.Z = 720;
4025 } 4171 }
4026 } 4172 }
4027 4173
4174// m_log.DebugFormat(
4175// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4176// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4177
4028 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4178 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4029 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4179 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4030 RegionInfo.EstateSettings.AllowDirectTeleport == false && 4180 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4031 !viahome && !godlike) 4181 !viahome && !godlike)
4032 { 4182 {
4033 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4183 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4034 // Can have multiple SpawnPoints 4184
4035 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4185 if (telehub != null)
4036 if (spawnpoints.Count > 1)
4037 { 4186 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4187 // Can have multiple SpawnPoints
4039 if (SpawnPointRouting == "random") 4188 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4189 if (spawnpoints.Count > 1)
4041 telehub.AbsolutePosition, 4190 {
4042 telehub.GroupRotation 4191 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4043 ); 4192 if (SpawnPointRouting == "random")
4193 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4194 telehub.AbsolutePosition,
4195 telehub.GroupRotation
4196 );
4197 else
4198 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4199 telehub.AbsolutePosition,
4200 telehub.GroupRotation
4201 );
4202 }
4203 else if (spawnpoints.Count == 1)
4204 {
4205 // We have a single SpawnPoint and will route the agent to it
4206 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4207 }
4044 else 4208 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4209 {
4046 telehub.AbsolutePosition, 4210 m_log.DebugFormat(
4047 telehub.GroupRotation 4211 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4048 ); 4212 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4213 }
4049 } 4214 }
4050 else 4215 else
4051 { 4216 {
4052 // We have a single SpawnPoint and will route the agent to it 4217 m_log.DebugFormat(
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4218 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4219 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4054 } 4220 }
4055 4221
4056 return true; 4222 return true;
@@ -4063,7 +4229,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4229 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4230 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4231 {
4066 agent.startpos = land.LandData.UserLocation; 4232 acd.startpos = land.LandData.UserLocation;
4067 } 4233 }
4068 } 4234 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4235 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4324,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4324 /// <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 4325 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4326 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4327 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4328 {
4163 reason = String.Empty; 4329 reason = String.Empty;
4164 4330
@@ -4177,67 +4343,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4343 }
4178 } 4344 }
4179 4345
4180 if (RegionInfo.EstateSettings != null) 4346 // We only test the things below when we want to cut off
4347 // child agents from being present in the scene for which their root
4348 // agent isn't allowed. Otherwise, we allow child agents. The test for
4349 // the root is done elsewhere (QueryAccess)
4350 if (!bypassAccessControl)
4181 { 4351 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4352 if (RegionInfo.EstateSettings != null)
4183 { 4353 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4354 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4355 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4356 {
4187 RegionInfo.RegionName); 4357 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4358 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4359 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4360 RegionInfo.RegionName);
4361 return false;
4362 }
4189 } 4363 }
4190 } 4364 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 { 4365 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4366 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4367 }
4207 else 4368
4369 List<UUID> agentGroups = new List<UUID>();
4370
4371 if (m_groupsModule != null)
4208 { 4372 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4373 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4374
4375 if (GroupMembership != null)
4376 {
4377 for (int i = 0; i < GroupMembership.Length; i++)
4378 agentGroups.Add(GroupMembership[i].GroupID);
4379 }
4380 else
4381 {
4382 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4383 }
4210 } 4384 }
4211 }
4212 4385
4213 bool groupAccess = false; 4386 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4387 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4388
4216 if (estateGroups != null) 4389 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4390 {
4220 if (agentGroups.Contains(group)) 4391 foreach (UUID group in estateGroups)
4221 { 4392 {
4222 groupAccess = true; 4393 if (agentGroups.Contains(group))
4223 break; 4394 {
4395 groupAccess = true;
4396 break;
4397 }
4224 } 4398 }
4225 } 4399 }
4226 } 4400 else
4227 else 4401 {
4228 { 4402 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4403 }
4230 }
4231 4404
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4405 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4406 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4407 !groupAccess)
4235 { 4408 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4409 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); 4410 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.", 4411 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4412 RegionInfo.RegionName);
4240 return false; 4413 return false;
4414 }
4241 } 4415 }
4242 4416
4243 // TODO: estate/region settings are not properly hooked up 4417 // TODO: estate/region settings are not properly hooked up
@@ -4362,13 +4536,18 @@ namespace OpenSim.Region.Framework.Scenes
4362 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4536 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4363 /// Appearance, animations, position, etc.</param> 4537 /// Appearance, animations, position, etc.</param>
4364 /// <returns>true if we handled it.</returns> 4538 /// <returns>true if we handled it.</returns>
4365 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4539 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4366 { 4540 {
4367 m_log.DebugFormat( 4541 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4542 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4543
4370 // XPTO: if this agent is not allowed here as root, always return false 4544 if (!LoginsEnabled)
4371 4545 {
4546// reason = "Logins Disabled";
4547 m_log.DebugFormat(
4548 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4549 return false;
4550 }
4372 // We have to wait until the viewer contacts this region after receiving EAC. 4551 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4552 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4553 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4382,7 +4561,7 @@ namespace OpenSim.Region.Framework.Scenes
4382 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4561 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4383 if (nearestParcel == null) 4562 if (nearestParcel == null)
4384 { 4563 {
4385 m_log.DebugFormat( 4564 m_log.InfoFormat(
4386 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4565 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4387 cAgentData.AgentID, RegionInfo.RegionName); 4566 cAgentData.AgentID, RegionInfo.RegionName);
4388 4567
@@ -4390,13 +4569,50 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4569 }
4391 4570
4392 // We have to wait until the viewer contacts this region 4571 // 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 4572 // 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. 4573 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4574 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4575 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4576
4397 if (childAgentUpdate != null) 4577 if (sp != null)
4398 { 4578 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4579 if (!sp.IsChildAgent)
4580 {
4581 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4582 sp.Name, sp.UUID, Name);
4583 return false;
4584 }
4585 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4586 {
4587 m_log.WarnFormat(
4588 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4589 sp.UUID, cAgentData.SessionID);
4590
4591 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4592 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4593 }
4594
4595 sp.UpdateChildAgent(cAgentData);
4596
4597 int ntimes = 20;
4598 if (cAgentData.SenderWantsToWaitForRoot)
4599 {
4600 while (sp.IsChildAgent && ntimes-- > 0)
4601 Thread.Sleep(1000);
4602
4603 if (sp.IsChildAgent)
4604 m_log.WarnFormat(
4605 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4606 sp.Name, sp.UUID, Name);
4607 else
4608 m_log.InfoFormat(
4609 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4610 sp.Name, sp.UUID, Name, 20 - ntimes);
4611
4612 if (sp.IsChildAgent)
4613 return false;
4614 }
4615
4400 return true; 4616 return true;
4401 } 4617 }
4402 4618
@@ -4409,12 +4625,17 @@ namespace OpenSim.Region.Framework.Scenes
4409 /// </summary> 4625 /// </summary>
4410 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4626 /// <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> 4627 /// <returns>true if we handled it.</returns>
4412 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4628 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4413 { 4629 {
4414 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4630 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4631 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4632 if (childAgentUpdate != null)
4417 { 4633 {
4634// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4635// // Only warn for now
4636// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4637// childAgentUpdate.UUID, cAgentData.SessionID);
4638
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4639 // 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.. 4640 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4641 if (childAgentUpdate.IsChildAgent)
@@ -4424,7 +4645,7 @@ namespace OpenSim.Region.Framework.Scenes
4424 uint tRegionX = RegionInfo.RegionLocX; 4645 uint tRegionX = RegionInfo.RegionLocX;
4425 uint tRegionY = RegionInfo.RegionLocY; 4646 uint tRegionY = RegionInfo.RegionLocY;
4426 //Send Data to ScenePresence 4647 //Send Data to ScenePresence
4427 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4648 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4428 // Not Implemented: 4649 // Not Implemented:
4429 //TODO: Do we need to pass the message on to one of our neighbors? 4650 //TODO: Do we need to pass the message on to one of our neighbors?
4430 } 4651 }
@@ -4451,35 +4672,99 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4672 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4673 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4674 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 4675
4459 return sp; 4676 return sp;
4460 } 4677 }
4461 4678
4462 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4679 /// <summary>
4680 /// Authenticated close (via network)
4681 /// </summary>
4682 /// <param name="agentID"></param>
4683 /// <param name="force"></param>
4684 /// <param name="auth_token"></param>
4685 /// <returns></returns>
4686 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4463 { 4687 {
4464 agent = null; 4688 //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); 4689
4466 if ((sp != null) && (!sp.IsChildAgent)) 4690 // Check that the auth_token is valid
4691 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4692
4693 if (acd == null)
4694 {
4695 m_log.DebugFormat(
4696 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4697 agentID, Name);
4698
4699 return false;
4700 }
4701
4702 if (acd.SessionID.ToString() == auth_token)
4703 {
4704 return CloseAgent(agentID, force);
4705 }
4706 else
4467 { 4707 {
4468 sp.IsChildAgent = true; 4708 m_log.WarnFormat(
4469 return sp.CopyAgent(out agent); 4709 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4710 agentID, auth_token, Name);
4470 } 4711 }
4471 4712
4472 return false; 4713 return false;
4473 } 4714 }
4474 4715
4475 public bool IncomingCloseAgent(UUID agentID) 4716// public bool IncomingCloseAgent(UUID agentID)
4476 { 4717// {
4477 return IncomingCloseAgent(agentID, false); 4718// return IncomingCloseAgent(agentID, false);
4478 } 4719// }
4479 4720
4480 public bool IncomingCloseChildAgent(UUID agentID) 4721// public bool IncomingCloseChildAgent(UUID agentID)
4722// {
4723// return IncomingCloseAgent(agentID, true);
4724// }
4725
4726 /// <summary>
4727 /// Tell a single client to prepare to close.
4728 /// </summary>
4729 /// <remarks>
4730 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4731 /// internal use - other callers should almost certainly called CloseClient().
4732 /// </remarks>
4733 /// <param name="sp"></param>
4734 /// <returns>true if pre-close state notification was successful. false if the agent
4735 /// was not in a state where it could transition to pre-close.</returns>
4736 public bool IncomingPreCloseClient(ScenePresence sp)
4481 { 4737 {
4482 return IncomingCloseAgent(agentID, true); 4738 lock (m_removeClientLock)
4739 {
4740 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4741 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4742 // want to obey this close since C may have renewed the child agent lease on B.
4743 if (sp.DoNotCloseAfterTeleport)
4744 {
4745 m_log.DebugFormat(
4746 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4747 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4748
4749 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4750 sp.DoNotCloseAfterTeleport = false;
4751
4752 return false;
4753 }
4754
4755 if (sp.LifecycleState != ScenePresenceState.Running)
4756 {
4757 m_log.DebugFormat(
4758 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4759 sp.Name, Name, sp.LifecycleState);
4760
4761 return false;
4762 }
4763
4764 sp.LifecycleState = ScenePresenceState.PreRemove;
4765
4766 return true;
4767 }
4483 } 4768 }
4484 4769
4485 /// <summary> 4770 /// <summary>
@@ -4490,18 +4775,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 4775 /// 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. 4776 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4492 /// </param> 4777 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4778 public override bool CloseAgent(UUID agentID, bool force)
4494 { 4779 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4780 ScenePresence sp;
4496 4781
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4782 lock (m_removeClientLock)
4498 if (presence != null) 4783 {
4784 sp = GetScenePresence(agentID);
4785
4786 if (sp == null)
4787 {
4788 // If there is no scene presence, we may be handling a dead
4789 // client. These can keep an avatar from reentering a region
4790 // and since they don't get cleaned up they will stick
4791 // around until region restart. So, if there is no SP,
4792 // remove the client as well.
4793 IClientAPI client = null;
4794 if (m_clientManager.TryGetValue(agentID, out client))
4795 {
4796 m_clientManager.Remove(agentID);
4797 if (CapsModule != null)
4798 CapsModule.RemoveCaps(agentID, 0);
4799 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4800 return true;
4801 }
4802 m_log.DebugFormat(
4803 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4804 agentID, Name);
4805
4806 return false;
4807 }
4808
4809 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4810 {
4811 m_log.DebugFormat(
4812 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4813 sp.Name, Name, sp.LifecycleState);
4814
4815 return false;
4816 }
4817
4818 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4819 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4820 // want to obey this close since C may have renewed the child agent lease on B.
4821 if (sp.DoNotCloseAfterTeleport)
4822 {
4823 m_log.DebugFormat(
4824 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4825 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4826
4827 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4828 sp.DoNotCloseAfterTeleport = false;
4829
4830 return false;
4831 }
4832
4833 sp.LifecycleState = ScenePresenceState.Removing;
4834 }
4835
4836 if (sp != null)
4499 { 4837 {
4500 presence.ControllingClient.Close(force, force); 4838 sp.ControllingClient.Close(force, force);
4501 return true; 4839 return true;
4502 } 4840 }
4503 4841
4504 // Agent not here 4842 // Agent not here
4505 return false; 4843 return false;
4506 } 4844 }
4507 4845
@@ -4700,7 +5038,10 @@ namespace OpenSim.Region.Framework.Scenes
4700 5038
4701 public LandData GetLandData(float x, float y) 5039 public LandData GetLandData(float x, float y)
4702 { 5040 {
4703 return LandChannel.GetLandObject(x, y).LandData; 5041 ILandObject parcel = LandChannel.GetLandObject(x, y);
5042 if (parcel == null)
5043 return null;
5044 return parcel.LandData;
4704 } 5045 }
4705 5046
4706 /// <summary> 5047 /// <summary>
@@ -4716,7 +5057,10 @@ namespace OpenSim.Region.Framework.Scenes
4716 public LandData GetLandData(uint x, uint y) 5057 public LandData GetLandData(uint x, uint y)
4717 { 5058 {
4718 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5059 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4719 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5060 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5061 if (parcel == null)
5062 return null;
5063 return parcel.LandData;
4720 } 5064 }
4721 5065
4722 #endregion 5066 #endregion
@@ -5091,21 +5435,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5435
5092 #endregion 5436 #endregion
5093 5437
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 5438
5110// Commented pending deletion since this method no longer appears to do anything at all 5439// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5440// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5986,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5986 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5987 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5988 {
5660 minX = 256; 5989 minX = float.MaxValue;
5661 maxX = -256; 5990 maxX = float.MinValue;
5662 minY = 256; 5991 minY = float.MaxValue;
5663 maxY = -256; 5992 maxY = float.MinValue;
5664 minZ = 8192; 5993 minZ = float.MaxValue;
5665 maxZ = -256; 5994 maxZ = float.MinValue;
5666 5995
5667 List<Vector3> offsets = new List<Vector3>(); 5996 List<Vector3> offsets = new List<Vector3>();
5668 5997
@@ -5802,17 +6131,6 @@ Environment.Exit(1);
5802 { 6131 {
5803 reason = "You are banned from the region"; 6132 reason = "You are banned from the region";
5804 6133
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)) 6134 if (Permissions.IsGod(agentID))
5817 { 6135 {
5818 reason = String.Empty; 6136 reason = String.Empty;
@@ -5862,9 +6180,9 @@ Environment.Exit(1);
5862 6180
5863 try 6181 try
5864 { 6182 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6183 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6184 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6185 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6186 return false;
5869 } 6187 }
5870 } 6188 }
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..9a2707b 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>
@@ -524,214 +529,257 @@ namespace OpenSim.Region.Framework.Scenes
524 set 529 set
525 { 530 {
526 Vector3 val = value; 531 Vector3 val = value;
527 532 if (Scene != null && !IsAttachmentCheckFull()
528 if (Scene != null) 533 && !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 { 541 {
545 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 542 inTransit = true;
546 uint x = 0; 543 SOGCrossDelegate d = CrossAsync;
547 uint y = 0; 544 d.BeginInvoke(this, val, CrossAsyncCompleted, d);
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 {
648 if (m_rootPart.KeyframeMotion != null)
649 m_rootPart.KeyframeMotion.CrossingFailure();
650
651 if (RootPart.PhysActor != null)
652 {
653 RootPart.PhysActor.CrossingFailure();
654 }
655 }
656 Vector3 oldp = AbsolutePosition;
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 } 545 }
546 return;
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
586 // now that position is changed tell it to scripts
587 if (triggerScriptEvent)
588 {
589 foreach (SceneObjectPart part in parts)
590 {
693 part.TriggerScriptChangedEvent(Changed.POSITION); 591 part.TriggerScriptChangedEvent(Changed.POSITION);
592 }
694 } 593 }
695 594
696/* 595 if (Scene != null)
697 This seems not needed and should not be needed: 596 Scene.EventManager.TriggerParcelPrimCountTainted();
698 sp absolute position depends on sit part absolute position fixed above. 597
699 sp ParentPosition is not used anywhere. 598 }
700 Since presence is sitting, viewer considers it 'linked' to root prim, so it will move/rotate it 599 }
701 Sending a extra packet with avatar position is not only bandwidth waste, but may cause jitter in viewers due to UPD nature. 600
702 601 public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
703 if (!m_dupeInProgress) 602 {
603 Scene sogScene = sog.m_scene;
604 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
605
606 Vector3 newpos = Vector3.Zero;
607 OpenSim.Services.Interfaces.GridRegion destination = null;
608
609 if (sog.RootPart.DIE_AT_EDGE)
610 {
611 try
612 {
613 sogScene.DeleteSceneObject(sog, false);
614 }
615 catch (Exception)
616 {
617 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
618 }
619 return sog;
620 }
621
622 if (sog.RootPart.RETURN_AT_EDGE)
623 {
624 // We remove the object here
625 try
626 {
627 List<uint> localIDs = new List<uint>();
628 localIDs.Add(sog.RootPart.LocalId);
629 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
630 "Returned at region cross");
631 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
632 }
633 catch (Exception)
704 { 634 {
705 foreach (ScenePresence av in m_linkedAvatars) 635 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
636 }
637 return sog;
638 }
639
640 if (sog.m_rootPart.KeyframeMotion != null)
641 sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
642
643 if (entityTransfer == null)
644 return sog;
645
646 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
647 if (destination == null)
648 return sog;
649
650 if (sog.m_linkedAvatars.Count == 0)
651 {
652 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true);
653 return sog;
654 }
655
656 string reason = String.Empty;
657 string version = String.Empty;
658
659 foreach (ScenePresence av in sog.m_linkedAvatars)
660 {
661 // We need to cross these agents. First, let's find
662 // out if any of them can't cross for some reason.
663 // We have to deny the crossing entirely if any
664 // of them are banned. Alternatively, we could
665 // unsit banned agents....
666
667 // We set the avatar position as being the object
668 // position to get the region to send to
669 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason))
670 {
671 return sog;
672 }
673 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
674 }
675
676 // We unparent the SP quietly so that it won't
677 // be made to stand up
678
679 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
680
681 foreach (ScenePresence av in sog.m_linkedAvatars)
682 {
683 avtocrossInfo avinfo = new avtocrossInfo();
684 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
685 if (parentPart != null)
686 av.ParentUUID = parentPart.UUID;
687
688 avinfo.av = av;
689 avinfo.ParentID = av.ParentID;
690 avsToCross.Add(avinfo);
691
692 av.PrevSitOffset = av.OffsetPosition;
693 av.ParentID = 0;
694 }
695
696 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true))
697 {
698 foreach (avtocrossInfo avinfo in avsToCross)
699 {
700 ScenePresence av = avinfo.av;
701 if (!av.IsInTransit) // just in case...
706 { 702 {
707 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID); 703 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
708 if (p != null && m_parts.TryGetValue(p.UUID, out p)) 704
705 av.IsInTransit = true;
706
707// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
708// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
709 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version);
710 if(av.IsChildAgent)
709 { 711 {
710 Vector3 offset = p.GetWorldPosition() - av.ParentPosition; 712 if (av.ParentUUID != UUID.Zero)
711 av.AbsolutePosition += offset; 713 {
712// av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition 714 av.ClearControls();
713 av.SendAvatarDataToAllAgents(); 715 av.ParentPart = null;
716 }
714 } 717 }
718 av.ParentUUID = UUID.Zero;
719 // In any case
720 av.IsInTransit = false;
721
722 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
715 } 723 }
724 else
725 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
726 }
727 avsToCross.Clear();
728 return sog;
729 }
730 else // cross failed, put avas back ??
731 {
732 foreach (avtocrossInfo avinfo in avsToCross)
733 {
734 ScenePresence av = avinfo.av;
735 av.ParentUUID = UUID.Zero;
736 av.ParentID = avinfo.ParentID;
716 } 737 }
717*/
718 //if (m_rootPart.PhysActor != null)
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 } 738 }
739 avsToCross.Clear();
740
741 return sog;
729 } 742 }
730 743
731 public override Vector3 Velocity 744 public void CrossAsyncCompleted(IAsyncResult iar)
732 { 745 {
733 get { return RootPart.Velocity; } 746 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
734 set { RootPart.Velocity = value; } 747 SceneObjectGroup sog = icon.EndInvoke(iar);
748
749 if (!sog.IsDeleted)
750 {
751 SceneObjectPart rootp = sog.m_rootPart;
752 Vector3 oldp = rootp.GroupPosition;
753 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
754 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
755 rootp.GroupPosition = oldp;
756
757 SceneObjectPart[] parts = sog.m_parts.GetArray();
758
759 foreach (SceneObjectPart part in parts)
760 {
761 if (part != rootp)
762 part.GroupPosition = oldp;
763 }
764
765 foreach (ScenePresence av in sog.m_linkedAvatars)
766 {
767 av.sitSOGmoved();
768 }
769
770 sog.Velocity = Vector3.Zero;
771
772 if (sog.m_rootPart.KeyframeMotion != null)
773 sog.m_rootPart.KeyframeMotion.CrossingFailure();
774
775 if (sog.RootPart.PhysActor != null)
776 {
777 sog.RootPart.PhysActor.CrossingFailure();
778 }
779
780 sog.inTransit = false;
781 sog.ScheduleGroupForFullUpdate();
782 }
735 } 783 }
736 784
737 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 785 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
@@ -744,6 +792,7 @@ namespace OpenSim.Region.Framework.Scenes
744 { 792 {
745 if (agent.ParentUUID != UUID.Zero) 793 if (agent.ParentUUID != UUID.Zero)
746 { 794 {
795 agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID);
747 agent.ParentPart = null; 796 agent.ParentPart = null;
748// agent.ParentPosition = Vector3.Zero; 797// agent.ParentPosition = Vector3.Zero;
749// agent.ParentUUID = UUID.Zero; 798// agent.ParentUUID = UUID.Zero;
@@ -751,7 +800,6 @@ namespace OpenSim.Region.Framework.Scenes
751 } 800 }
752 801
753 agent.ParentUUID = UUID.Zero; 802 agent.ParentUUID = UUID.Zero;
754
755// agent.Reset(); 803// agent.Reset();
756// else // Not successful 804// else // Not successful
757// agent.RestoreInCurrentScene(); 805// agent.RestoreInCurrentScene();
@@ -762,6 +810,12 @@ namespace OpenSim.Region.Framework.Scenes
762 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 810 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
763 } 811 }
764 812
813 public override Vector3 Velocity
814 {
815 get { return RootPart.Velocity; }
816 set { RootPart.Velocity = value; }
817 }
818
765 public override uint LocalId 819 public override uint LocalId
766 { 820 {
767 get { return m_rootPart.LocalId; } 821 get { return m_rootPart.LocalId; }
@@ -885,20 +939,20 @@ namespace OpenSim.Region.Framework.Scenes
885 return; 939 return;
886 } 940 }
887 IsSelected = partSelect; 941 IsSelected = partSelect;
888 if (!IsAttachment) 942// if (!IsAttachment)
889 { 943// {
890 ScheduleGroupForFullUpdate(); 944// ScheduleGroupForFullUpdate();
891 } 945// }
892 } 946 }
893 } 947 }
894 948 // PlaySoundMasterPrim no longer in use to remove
895 private SceneObjectPart m_PlaySoundMasterPrim = null; 949 private SceneObjectPart m_PlaySoundMasterPrim = null;
896 public SceneObjectPart PlaySoundMasterPrim 950 public SceneObjectPart PlaySoundMasterPrim
897 { 951 {
898 get { return m_PlaySoundMasterPrim; } 952 get { return m_PlaySoundMasterPrim; }
899 set { m_PlaySoundMasterPrim = value; } 953 set { m_PlaySoundMasterPrim = value; }
900 } 954 }
901 955 // PlaySoundSlavePrims no longer in use to remove
902 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 956 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
903 public List<SceneObjectPart> PlaySoundSlavePrims 957 public List<SceneObjectPart> PlaySoundSlavePrims
904 { 958 {
@@ -906,6 +960,7 @@ namespace OpenSim.Region.Framework.Scenes
906 set { m_PlaySoundSlavePrims = value; } 960 set { m_PlaySoundSlavePrims = value; }
907 } 961 }
908 962
963 // LoopSoundMasterPrim no longer in use to remove
909 private SceneObjectPart m_LoopSoundMasterPrim = null; 964 private SceneObjectPart m_LoopSoundMasterPrim = null;
910 public SceneObjectPart LoopSoundMasterPrim 965 public SceneObjectPart LoopSoundMasterPrim
911 { 966 {
@@ -913,6 +968,7 @@ namespace OpenSim.Region.Framework.Scenes
913 set { m_LoopSoundMasterPrim = value; } 968 set { m_LoopSoundMasterPrim = value; }
914 } 969 }
915 970
971 // m_LoopSoundSlavePrims no longer in use to remove
916 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 972 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
917 public List<SceneObjectPart> LoopSoundSlavePrims 973 public List<SceneObjectPart> LoopSoundSlavePrims
918 { 974 {
@@ -1667,7 +1723,8 @@ namespace OpenSim.Region.Framework.Scenes
1667 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1723 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1668 if (avatar == null) 1724 if (avatar == null)
1669 return; 1725 return;
1670 1726 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1727 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1671 avatar.RemoveAttachment(this); 1728 avatar.RemoveAttachment(this);
1672 1729
1673 Vector3 detachedpos = new Vector3(127f,127f,127f); 1730 Vector3 detachedpos = new Vector3(127f,127f,127f);
@@ -1687,7 +1744,9 @@ namespace OpenSim.Region.Framework.Scenes
1687 m_rootPart.SetParentLocalId(0); 1744 m_rootPart.SetParentLocalId(0);
1688 AttachmentPoint = (byte)0; 1745 AttachmentPoint = (byte)0;
1689 // must check if buildind should be true or false here 1746 // must check if buildind should be true or false here
1690 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false); 1747// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1748 ApplyPhysics();
1749
1691 HasGroupChanged = true; 1750 HasGroupChanged = true;
1692 RootPart.Rezzed = DateTime.Now; 1751 RootPart.Rezzed = DateTime.Now;
1693 RootPart.RemFlag(PrimFlags.TemporaryOnRez); 1752 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
@@ -1820,11 +1879,21 @@ namespace OpenSim.Region.Framework.Scenes
1820 // Setting this SOG's absolute position also loops through and sets the positions 1879 // 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 1880 // 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. 1881 // the physics world matches the simulated world.
1823 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1882 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1824 1883
1825 // teravus: AbsolutePosition is NOT a normal property! 1884 // teravus: AbsolutePosition is NOT a normal property!
1826 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1885 // 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? 1886 // jhurliman: Then why is it a property instead of two methods?
1887
1888 // do only what is supposed to do
1889 Vector3 groupPosition = m_rootPart.GroupPosition;
1890 SceneObjectPart[] parts = m_parts.GetArray();
1891
1892 foreach (SceneObjectPart part in parts)
1893 {
1894 if (part != m_rootPart)
1895 part.GroupPosition = groupPosition;
1896 }
1828 } 1897 }
1829 1898
1830 public UUID GetPartsFullID(uint localID) 1899 public UUID GetPartsFullID(uint localID)
@@ -1868,11 +1937,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1937 /// <summary>
1869 /// Delete this group from its scene. 1938 /// Delete this group from its scene.
1870 /// </summary> 1939 /// </summary>
1871 /// 1940 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1941 /// 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 1942 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1943 /// must be handled by the caller.
1875 /// 1944 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1945 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1946 public void DeleteGroupFromScene(bool silent)
1878 { 1947 {
@@ -1901,7 +1970,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 if (!IsAttachment 1970 if (!IsAttachment
1902 || AttachedAvatar == avatar.ControllingClient.AgentId 1971 || AttachedAvatar == avatar.ControllingClient.AgentId
1903 || !HasPrivateAttachmentPoint) 1972 || !HasPrivateAttachmentPoint)
1904 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1973 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1905 } 1974 }
1906 } 1975 }
1907 }); 1976 });
@@ -2037,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes
2037 return; 2106 return;
2038 } 2107 }
2039 2108
2040 if (IsDeleted || UUID == UUID.Zero) 2109 if (IsDeleted || inTransit || UUID == UUID.Zero)
2041 { 2110 {
2042// m_log.DebugFormat( 2111// m_log.DebugFormat(
2043// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2112// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
@@ -2109,6 +2178,7 @@ namespace OpenSim.Region.Framework.Scenes
2109 2178
2110 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) 2179 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2111 { 2180 {
2181 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2112 RootPart.Shape.State = 0; 2182 RootPart.Shape.State = 0;
2113 ScheduleGroupForFullUpdate(); 2183 ScheduleGroupForFullUpdate();
2114 } 2184 }
@@ -2122,23 +2192,22 @@ namespace OpenSim.Region.Framework.Scenes
2122 HasGroupChangedDueToDelink = false; 2192 HasGroupChangedDueToDelink = false;
2123 2193
2124 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2194 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2125/* 2195
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); 2196 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
2136 2197
2137 backup_group.ForEachPart(delegate(SceneObjectPart part) 2198 backup_group.ForEachPart(delegate(SceneObjectPart part)
2138 { 2199 {
2139 part.Inventory.ProcessInventoryBackup(datastore); 2200 part.Inventory.ProcessInventoryBackup(datastore);
2201
2202 // take the change to delete things
2203 if(part.KeyframeMotion != null)
2204 {
2205 part.KeyframeMotion.Delete();
2206 part.KeyframeMotion = null;
2207 }
2140 }); 2208 });
2141 2209
2210
2142 backup_group = null; 2211 backup_group = null;
2143 } 2212 }
2144// else 2213// else
@@ -2193,29 +2262,11 @@ namespace OpenSim.Region.Framework.Scenes
2193 dupe.m_isBackedUp = false; 2262 dupe.m_isBackedUp = false;
2194 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2263 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
2195 2264
2265 dupe.inTransit = inTransit; // this shouldn't be needed TEST
2266
2196 // new group as no sitting avatars 2267 // new group as no sitting avatars
2197 dupe.m_linkedAvatars = new List<ScenePresence>(); 2268 dupe.m_linkedAvatars = new List<ScenePresence>();
2198 2269 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 2270
2220 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2271 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
2221 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2272 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
@@ -2239,7 +2290,7 @@ namespace OpenSim.Region.Framework.Scenes
2239 { 2290 {
2240 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2291 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
2241 newPart.LinkNum = part.LinkNum; 2292 newPart.LinkNum = part.LinkNum;
2242 if (userExposed) 2293// if (userExposed)
2243 newPart.ParentID = dupe.m_rootPart.LocalId; 2294 newPart.ParentID = dupe.m_rootPart.LocalId;
2244 } 2295 }
2245 else 2296 else
@@ -2300,10 +2351,9 @@ namespace OpenSim.Region.Framework.Scenes
2300 /// <param name="cGroupID"></param> 2351 /// <param name="cGroupID"></param>
2301 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2352 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2302 { 2353 {
2303 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2354 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2304 // give newpart a new local ID lettng old part keep same 2355// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2305 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed); 2356// newpart.LocalId = m_scene.AllocateLocalId();
2306 newpart.LocalId = m_scene.AllocateLocalId();
2307 2357
2308 SetRootPart(newpart); 2358 SetRootPart(newpart);
2309 if (userExposed) 2359 if (userExposed)
@@ -2522,11 +2572,9 @@ namespace OpenSim.Region.Framework.Scenes
2522 /// <param name="cGroupID"></param> 2572 /// <param name="cGroupID"></param>
2523 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2573 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2524 { 2574 {
2525 // give new ID to the new part, letting old keep original 2575 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); 2576// 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); 2577// newPart.LocalId = m_scene.AllocateLocalId();
2528 newPart.LocalId = m_scene.AllocateLocalId();
2529 newPart.SetParent(this);
2530 2578
2531 AddPart(newPart); 2579 AddPart(newPart);
2532 2580
@@ -2585,7 +2633,7 @@ namespace OpenSim.Region.Framework.Scenes
2585 // an object has been deleted from a scene before update was processed. 2633 // 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 2634 // A more fundamental overhaul of the update mechanism is required to eliminate all
2587 // the race conditions. 2635 // the race conditions.
2588 if (IsDeleted) 2636 if (IsDeleted || inTransit)
2589 return; 2637 return;
2590 2638
2591 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2639 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2600,6 +2648,16 @@ namespace OpenSim.Region.Framework.Scenes
2600 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 2648 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2601 } 2649 }
2602 2650
2651 if (IsAttachment)
2652 {
2653 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2654 if (sp != null)
2655 {
2656 sp.SendAttachmentScheduleUpdate(this);
2657 return;
2658 }
2659 }
2660
2603 SceneObjectPart[] parts = m_parts.GetArray(); 2661 SceneObjectPart[] parts = m_parts.GetArray();
2604 for (int i = 0; i < parts.Length; i++) 2662 for (int i = 0; i < parts.Length; i++)
2605 { 2663 {
@@ -2661,15 +2719,25 @@ namespace OpenSim.Region.Framework.Scenes
2661 return; 2719 return;
2662 2720
2663// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2721// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2664 2722
2665 RootPart.SendFullUpdateToAllClients(); 2723 if (IsAttachment)
2724 {
2725 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2726 if (sp != null)
2727 {
2728 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
2729 return;
2730 }
2731 }
2732
2733 RootPart.SendFullUpdateToAllClientsInternal();
2666 2734
2667 SceneObjectPart[] parts = m_parts.GetArray(); 2735 SceneObjectPart[] parts = m_parts.GetArray();
2668 for (int i = 0; i < parts.Length; i++) 2736 for (int i = 0; i < parts.Length; i++)
2669 { 2737 {
2670 SceneObjectPart part = parts[i]; 2738 SceneObjectPart part = parts[i];
2671 if (part != RootPart) 2739 if (part != RootPart)
2672 part.SendFullUpdateToAllClients(); 2740 part.SendFullUpdateToAllClientsInternal();
2673 } 2741 }
2674 } 2742 }
2675 2743
@@ -2681,7 +2749,7 @@ namespace OpenSim.Region.Framework.Scenes
2681 /// </summary> 2749 /// </summary>
2682 public void SendGroupRootTerseUpdate() 2750 public void SendGroupRootTerseUpdate()
2683 { 2751 {
2684 if (IsDeleted) 2752 if (IsDeleted || inTransit)
2685 return; 2753 return;
2686 2754
2687 RootPart.SendTerseUpdateToAllClients(); 2755 RootPart.SendTerseUpdateToAllClients();
@@ -2700,12 +2768,22 @@ namespace OpenSim.Region.Framework.Scenes
2700 /// </summary> 2768 /// </summary>
2701 public void SendGroupTerseUpdate() 2769 public void SendGroupTerseUpdate()
2702 { 2770 {
2703 if (IsDeleted) 2771 if (IsDeleted || inTransit)
2704 return; 2772 return;
2705 2773
2774 if (IsAttachment)
2775 {
2776 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2777 if (sp != null)
2778 {
2779 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
2780 return;
2781 }
2782 }
2783
2706 SceneObjectPart[] parts = m_parts.GetArray(); 2784 SceneObjectPart[] parts = m_parts.GetArray();
2707 for (int i = 0; i < parts.Length; i++) 2785 for (int i = 0; i < parts.Length; i++)
2708 parts[i].SendTerseUpdateToAllClients(); 2786 parts[i].SendTerseUpdateToAllClientsInternal();
2709 } 2787 }
2710 2788
2711 /// <summary> 2789 /// <summary>
@@ -2813,6 +2891,33 @@ namespace OpenSim.Region.Framework.Scenes
2813 return; 2891 return;
2814 } 2892 }
2815 2893
2894 // physical prims count limit
2895 // not very eficient :(
2896
2897 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
2898 m_scene.m_linksetPhysCapacity)
2899 {
2900 int cntr = 0;
2901 foreach (SceneObjectPart part in Parts)
2902 {
2903 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2904 cntr++;
2905 }
2906 foreach (SceneObjectPart part in objectGroup.Parts)
2907 {
2908 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2909 cntr++;
2910 }
2911
2912 if (cntr > m_scene.m_linksetPhysCapacity)
2913 {
2914 // cancel physics
2915 RootPart.Flags &= ~PrimFlags.Physics;
2916 ApplyPhysics();
2917 }
2918 }
2919
2920
2816 // 'linkPart' == the root of the group being linked into this group 2921 // 'linkPart' == the root of the group being linked into this group
2817 SceneObjectPart linkPart = objectGroup.m_rootPart; 2922 SceneObjectPart linkPart = objectGroup.m_rootPart;
2818 2923
@@ -2837,22 +2942,24 @@ namespace OpenSim.Region.Framework.Scenes
2837 // First move the new group's root SOP's position to be relative to ours 2942 // 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, 2943 // (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.) 2944 // this code can be reordered to have a more logical flow.)
2840 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 2945 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2841 // Assign the new parent to the root of the old group 2946 // Assign the new parent to the root of the old group
2842 linkPart.ParentID = m_rootPart.LocalId; 2947 linkPart.ParentID = m_rootPart.LocalId;
2843 // Now that it's a child, it's group position is our root position 2948 // Now that it's a child, it's group position is our root position
2844 linkPart.GroupPosition = AbsolutePosition; 2949 linkPart.setGroupPosition(AbsolutePosition);
2845 2950
2846 Vector3 axPos = linkPart.OffsetPosition;
2847 // Rotate the linking root SOP's position to be relative to the new root prim 2951 // Rotate the linking root SOP's position to be relative to the new root prim
2848 Quaternion parentRot = m_rootPart.RotationOffset; 2952 Quaternion parentRot = m_rootPart.RotationOffset;
2849 axPos *= Quaternion.Conjugate(parentRot);
2850 linkPart.OffsetPosition = axPos;
2851 2953
2852 // Make the linking root SOP's rotation relative to the new root prim 2954 // Make the linking root SOP's rotation relative to the new root prim
2853 Quaternion oldRot = linkPart.RotationOffset; 2955 Quaternion oldRot = linkPart.RotationOffset;
2854 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot; 2956 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2855 linkPart.RotationOffset = newRot; 2957 linkPart.setRotationOffset(newRot);
2958
2959 Vector3 axPos = linkPart.OffsetPosition;
2960 axPos *= Quaternion.Conjugate(parentRot);
2961 linkPart.OffsetPosition = axPos;
2962
2856 2963
2857 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 2964 // 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 2965 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2882,6 +2989,8 @@ namespace OpenSim.Region.Framework.Scenes
2882 m_parts.Add(linkPart.UUID, linkPart); 2989 m_parts.Add(linkPart.UUID, linkPart);
2883 2990
2884 linkPart.SetParent(this); 2991 linkPart.SetParent(this);
2992 m_scene.updateScenePartGroup(linkPart, this);
2993
2885 linkPart.CreateSelected = true; 2994 linkPart.CreateSelected = true;
2886 2995
2887 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 2996 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
@@ -3074,18 +3183,15 @@ namespace OpenSim.Region.Framework.Scenes
3074 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3183 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
3075 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3184 linkPart.OffsetPosition = new Vector3(0, 0, 0);
3076 */ 3185 */
3077 linkPart.GroupPosition = worldPos; 3186 linkPart.setGroupPosition(worldPos);
3078 linkPart.OffsetPosition = Vector3.Zero; 3187 linkPart.setOffsetPosition(Vector3.Zero);
3079 linkPart.RotationOffset = worldRot; 3188 linkPart.setRotationOffset(worldRot);
3080 3189
3081 // Create a new SOG to go around this unlinked and unattached SOP 3190 // Create a new SOG to go around this unlinked and unattached SOP
3082 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3191 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
3083 3192
3084 m_scene.AddNewSceneObject(objectGroup, true); 3193 m_scene.AddNewSceneObject(objectGroup, true);
3085 3194
3086 if (sendEvents)
3087 linkPart.TriggerScriptChangedEvent(Changed.LINK);
3088
3089 linkPart.Rezzed = RootPart.Rezzed; 3195 linkPart.Rezzed = RootPart.Rezzed;
3090 3196
3091 // When we delete a group, we currently have to force persist to the database if the object id has changed 3197 // When we delete a group, we currently have to force persist to the database if the object id has changed
@@ -3100,6 +3206,9 @@ namespace OpenSim.Region.Framework.Scenes
3100 3206
3101 objectGroup.HasGroupChangedDueToDelink = true; 3207 objectGroup.HasGroupChangedDueToDelink = true;
3102 3208
3209 if (sendEvents)
3210 linkPart.TriggerScriptChangedEvent(Changed.LINK);
3211
3103 return objectGroup; 3212 return objectGroup;
3104 } 3213 }
3105 3214
@@ -3127,15 +3236,14 @@ namespace OpenSim.Region.Framework.Scenes
3127 Quaternion parentRot = oldGroupRotation; 3236 Quaternion parentRot = oldGroupRotation;
3128 Quaternion oldRot = part.RotationOffset; 3237 Quaternion oldRot = part.RotationOffset;
3129 3238
3130 // Move our position to not be relative to the old parent 3239 // Move our position in world
3131 Vector3 axPos = part.OffsetPosition; 3240 Vector3 axPos = part.OffsetPosition;
3132 axPos *= parentRot; 3241 axPos *= parentRot;
3133 part.OffsetPosition = axPos; 3242 Vector3 newPos = oldGroupPosition + axPos;
3134 Vector3 newPos = oldGroupPosition + part.OffsetPosition; 3243 part.setGroupPosition(newPos);
3135 part.GroupPosition = newPos; 3244 part.setOffsetPosition(Vector3.Zero);
3136 part.OffsetPosition = Vector3.Zero;
3137 3245
3138 // Compution our rotation to be not relative to the old parent 3246 // Compution our rotation in world
3139 Quaternion worldRot = parentRot * oldRot; 3247 Quaternion worldRot = parentRot * oldRot;
3140 part.RotationOffset = worldRot; 3248 part.RotationOffset = worldRot;
3141 3249
@@ -3146,25 +3254,27 @@ namespace OpenSim.Region.Framework.Scenes
3146 3254
3147 part.LinkNum = linkNum; 3255 part.LinkNum = linkNum;
3148 3256
3257 m_scene.updateScenePartGroup(part, this);
3258
3149 // Compute the new position of this SOP relative to the group position 3259 // Compute the new position of this SOP relative to the group position
3150 part.OffsetPosition = newPos - AbsolutePosition; 3260 part.setOffsetPosition(newPos - AbsolutePosition);
3151 3261
3152 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3262 // (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 3263 // 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 3264 // 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.) 3265 // test to know that cleaning up this code wouldn't break things.)
3156 3266
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. 3267 // Compute the SOP's rotation relative to the rotation of the group.
3164 parentRot = m_rootPart.RotationOffset; 3268 parentRot = m_rootPart.RotationOffset;
3269
3165 oldRot = part.RotationOffset; 3270 oldRot = part.RotationOffset;
3166 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot; 3271 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
3167 part.RotationOffset = newRot; 3272 part.setRotationOffset(newRot);
3273
3274 Vector3 pos = part.OffsetPosition;
3275 pos *= Quaternion.Conjugate(parentRot);
3276
3277 part.OffsetPosition = pos; // update position and orientation on physics also
3168 3278
3169 // Since this SOP's state has changed, push those changes into the physics engine 3279 // Since this SOP's state has changed, push those changes into the physics engine
3170 // and the simulator. 3280 // and the simulator.
@@ -3411,8 +3521,12 @@ namespace OpenSim.Region.Framework.Scenes
3411 { 3521 {
3412 SceneObjectPart[] parts = m_parts.GetArray(); 3522 SceneObjectPart[] parts = m_parts.GetArray();
3413 3523
3414 if (Scene != null) 3524 if (Scene != null && UsePhysics)
3415 { 3525 {
3526 int maxprims = m_scene.m_linksetPhysCapacity;
3527 bool checkShape = (maxprims > 0 &&
3528 parts.Length > maxprims);
3529
3416 for (int i = 0; i < parts.Length; i++) 3530 for (int i = 0; i < parts.Length; i++)
3417 { 3531 {
3418 SceneObjectPart part = parts[i]; 3532 SceneObjectPart part = parts[i];
@@ -3423,6 +3537,15 @@ namespace OpenSim.Region.Framework.Scenes
3423 UsePhysics = false; // Reset physics 3537 UsePhysics = false; // Reset physics
3424 break; 3538 break;
3425 } 3539 }
3540
3541 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3542 {
3543 if (--maxprims < 0)
3544 {
3545 UsePhysics = false;
3546 break;
3547 }
3548 }
3426 } 3549 }
3427 } 3550 }
3428 3551
@@ -3813,20 +3936,20 @@ namespace OpenSim.Region.Framework.Scenes
3813 /// <summary> 3936 /// <summary>
3814 /// Update just the root prim position in a linkset 3937 /// Update just the root prim position in a linkset
3815 /// </summary> 3938 /// </summary>
3816 /// <param name="pos"></param> 3939 /// <param name="newPos"></param>
3817 public void UpdateRootPosition(Vector3 pos) 3940 public void UpdateRootPosition(Vector3 newPos)
3818 { 3941 {
3819 // needs to be called with phys building true 3942 // needs to be called with phys building true
3820 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3943 Vector3 oldPos;
3821 Vector3 oldPos = 3944
3822 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3945 if (IsAttachment)
3823 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3946 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); 3947 else
3948 oldPos = AbsolutePosition + m_rootPart.OffsetPosition;
3949
3825 Vector3 diff = oldPos - newPos; 3950 Vector3 diff = oldPos - newPos;
3826 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3827 Quaternion partRotation = m_rootPart.RotationOffset; 3951 Quaternion partRotation = m_rootPart.RotationOffset;
3828 axDiff *= Quaternion.Inverse(partRotation); 3952 diff *= Quaternion.Inverse(partRotation);
3829 diff = axDiff;
3830 3953
3831 SceneObjectPart[] parts = m_parts.GetArray(); 3954 SceneObjectPart[] parts = m_parts.GetArray();
3832 for (int i = 0; i < parts.Length; i++) 3955 for (int i = 0; i < parts.Length; i++)
@@ -3837,6 +3960,9 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 3960 }
3838 3961
3839 AbsolutePosition = newPos; 3962 AbsolutePosition = newPos;
3963
3964 if (IsAttachment)
3965 m_rootPart.AttachedPos = newPos;
3840 3966
3841 HasGroupChanged = true; 3967 HasGroupChanged = true;
3842 if (m_rootPart.Undoing) 3968 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 ba25d9b..5a3e554 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,22 +75,60 @@ namespace OpenSim.Region.Framework.Scenes
73 75
74 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
75 { 77 {
76 public bool Invisible = false; 78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 79
78// ~ScenePresence() 80// ~ScenePresence()
79// { 81// {
80// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
81// } 83// }
82 84
83 private void TriggerScenePresenceUpdated() 85 public void TriggerScenePresenceUpdated()
84 { 86 {
85 if (m_scene != null) 87 if (m_scene != null)
86 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
87 } 89 }
88 90
89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 91 public bool isNPC { get; private set; }
92
93 public bool Invisible { get; set; }
94 private PresenceType m_presenceType;
95 public PresenceType PresenceType {
96 get {return m_presenceType;}
97 private set
98 {
99 m_presenceType = value;
100 isNPC = (m_presenceType == PresenceType.Npc);
101 }
102 }
103
104 private ScenePresenceStateMachine m_stateMachine;
105
106 /// <summary>
107 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
108 /// for more details.
109 /// </summary>
110 public ScenePresenceState LifecycleState
111 {
112 get
113 {
114 return m_stateMachine.GetState();
115 }
116
117 set
118 {
119 m_stateMachine.SetState(value);
120 }
121 }
90 122
91 public PresenceType PresenceType { get; private set; } 123 /// <summary>
124 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
125 /// the viewer fires these in quick succession.
126 /// </summary>
127 /// <remarks>
128 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
129 /// regulation done there.
130 /// </remarks>
131 private object m_completeMovementLock = new object();
92 132
93// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 133// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
94 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 134 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
@@ -111,13 +151,100 @@ namespace OpenSim.Region.Framework.Scenes
111 /// </summary> 151 /// </summary>
112 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 152 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f;
113 153
114 public UUID currentParcelUUID = UUID.Zero; 154 private UUID m_previusParcelUUID = UUID.Zero;
155 private UUID m_currentParcelUUID = UUID.Zero;
156 private bool m_previusParcelHide = false;
157 private bool m_currentParcelHide = false;
158 private object parcelLock = new Object();
159
160 public UUID currentParcelUUID
161 {
162 get { return m_currentParcelUUID; }
163 set
164 {
165 lock (parcelLock)
166 {
167 bool oldhide = m_currentParcelHide;
168 bool checksame = true;
169 if (value != m_currentParcelUUID)
170 {
171 m_previusParcelHide = m_currentParcelHide;
172 m_previusParcelUUID = m_currentParcelUUID;
173 checksame = false;
174 }
175 m_currentParcelUUID = value;
176 m_currentParcelHide = false;
177
178 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
179 if (land != null && !land.LandData.SeeAVs)
180 m_currentParcelHide = true;
115 181
182 if (m_previusParcelUUID != UUID.Zero || checksame)
183 ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
184 }
185 }
186 }
187
188 public void sitSOGmoved()
189 {
190 if (IsDeleted || !IsSatOnObject)
191 //what me? nahh
192 return;
193 if (IsInTransit)
194 return;
195
196 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
197 if (land == null)
198 return; //??
199 UUID parcelID = land.LandData.GlobalID;
200 if (m_currentParcelUUID != parcelID)
201 currentParcelUUID = parcelID;
202 }
203
204
205 public bool ParcelAllowThisAvatarSounds
206 {
207 get
208 {
209 try
210 {
211 lock (parcelLock)
212 {
213 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
214 if (land == null)
215 return true;
216 if (land.LandData.AnyAVSounds)
217 return true;
218 if (!land.LandData.GroupAVSounds)
219 return false;
220 return land.LandData.GroupID == ControllingClient.ActiveGroupId;
221 }
222 }
223 catch
224 {
225 return true;
226 }
227 }
228 }
229
230 public bool ParcelHideThisAvatar
231 {
232 get
233 {
234 return m_currentParcelHide;
235 }
236 }
237
116 /// <value> 238 /// <value>
117 /// The animator for this avatar 239 /// The animator for this avatar
118 /// </value> 240 /// </value>
119 public ScenePresenceAnimator Animator { get; private set; } 241 public ScenePresenceAnimator Animator { get; private set; }
120 242
243 /// <value>
244 /// Server Side Animation Override
245 /// </value>
246 public MovementAnimationOverrides Overrides { get; private set; }
247 public String sitAnimation = "SIT";
121 /// <summary> 248 /// <summary>
122 /// Attachments recorded on this avatar. 249 /// Attachments recorded on this avatar.
123 /// </summary> 250 /// </summary>
@@ -144,6 +271,8 @@ namespace OpenSim.Region.Framework.Scenes
144 private Vector3 m_lastVelocity; 271 private Vector3 m_lastVelocity;
145 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 272 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
146 273
274 private bool m_followCamAuto = false;
275
147 276
148 private Vector3? m_forceToApply; 277 private Vector3? m_forceToApply;
149 private int m_userFlags; 278 private int m_userFlags;
@@ -159,14 +288,7 @@ namespace OpenSim.Region.Framework.Scenes
159 set { PhysicsActor.Flying = value; } 288 set { PhysicsActor.Flying = value; }
160 } 289 }
161 290
162 // add for fly velocity control 291 public bool IsColliding
163 private bool FlyingOld {get; set;}
164 public bool WasFlying
165 {
166 get; private set;
167 }
168
169 public bool IsColliding
170 { 292 {
171 get { return PhysicsActor != null && PhysicsActor.IsColliding; } 293 get { return PhysicsActor != null && PhysicsActor.IsColliding; }
172 // We would expect setting IsColliding to be private but it's used by a hack in Scene 294 // We would expect setting IsColliding to be private but it's used by a hack in Scene
@@ -202,7 +324,7 @@ namespace OpenSim.Region.Framework.Scenes
202 private float m_sitAvatarHeight = 2.0f; 324 private float m_sitAvatarHeight = 2.0f;
203 325
204 private Vector3 m_lastChildAgentUpdatePosition; 326 private Vector3 m_lastChildAgentUpdatePosition;
205 private Vector3 m_lastChildAgentUpdateCamPosition; 327// private Vector3 m_lastChildAgentUpdateCamPosition;
206 328
207 private const int LAND_VELOCITYMAG_MAX = 12; 329 private const int LAND_VELOCITYMAG_MAX = 12;
208 330
@@ -215,7 +337,7 @@ namespace OpenSim.Region.Framework.Scenes
215 337
216 protected ulong crossingFromRegion; 338 protected ulong crossingFromRegion;
217 339
218 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 340 private readonly Vector3[] Dir_Vectors = new Vector3[12];
219 341
220 protected Timer m_reprioritization_timer; 342 protected Timer m_reprioritization_timer;
221 protected bool m_reprioritizing; 343 protected bool m_reprioritizing;
@@ -272,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes
272 /// <summary> 394 /// <summary>
273 /// Implemented Control Flags 395 /// Implemented Control Flags
274 /// </summary> 396 /// </summary>
275 private enum Dir_ControlFlags 397 private enum Dir_ControlFlags:uint
276 { 398 {
277 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, 399 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
278 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, 400 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
@@ -284,6 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
284 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 406 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
285 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, 407 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
286 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, 408 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
409 DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS,
287 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 410 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
288 } 411 }
289 412
@@ -292,9 +415,37 @@ namespace OpenSim.Region.Framework.Scenes
292 /// </summary> 415 /// </summary>
293 private Vector3 posLastSignificantMove; 416 private Vector3 posLastSignificantMove;
294 417
295 // For teleports and crossings callbacks 418 #region For teleports and crossings callbacks
296 string m_callbackURI; 419
297 UUID m_originRegionID; 420 /// <summary>
421 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
422 /// </summary>
423 private string m_callbackURI;
424
425 /// <summary>
426 /// Records the region from which this presence originated, if not from login.
427 /// </summary>
428 /// <remarks>
429 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
430 /// CompleteMovement and made the previous child agent a root agent.
431 /// </remarks>
432 private UUID m_originRegionID;
433
434 /// <summary>
435 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
436 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
437 /// it is a value type.
438 /// </summary>
439 private object m_originRegionIDAccessLock = new object();
440
441 /// <summary>
442 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
443 /// teleport is reusing the connection.
444 /// </summary>
445 /// <remarks>May be refactored or move somewhere else soon.</remarks>
446 public bool DoNotCloseAfterTeleport { get; set; }
447
448 #endregion
298 449
299 /// <value> 450 /// <value>
300 /// Script engines present in the scene 451 /// Script engines present in the scene
@@ -311,15 +462,12 @@ namespace OpenSim.Region.Framework.Scenes
311 /// <summary> 462 /// <summary>
312 /// Record user movement inputs. 463 /// Record user movement inputs.
313 /// </summary> 464 /// </summary>
314 public byte MovementFlag { get; private set; } 465 public uint MovementFlag { get; private set; }
315
316 private bool m_updateflag;
317 466
318 public bool Updated 467 /// <summary>
319 { 468 /// Is the agent stop control flag currently active?
320 set { m_updateflag = value; } 469 /// </summary>
321 get { return m_updateflag; } 470 public bool AgentControlStopActive { get; private set; }
322 }
323 471
324 private bool m_invulnerable = true; 472 private bool m_invulnerable = true;
325 473
@@ -346,11 +494,18 @@ namespace OpenSim.Region.Framework.Scenes
346 } 494 }
347 495
348 private ulong m_rootRegionHandle; 496 private ulong m_rootRegionHandle;
497 private Vector3 m_rootRegionPosition = new Vector3();
349 498
350 public ulong RegionHandle 499 public ulong RegionHandle
351 { 500 {
352 get { return m_rootRegionHandle; } 501 get { return m_rootRegionHandle; }
353 private set { m_rootRegionHandle = value; } 502 private set
503 {
504 m_rootRegionHandle = value;
505 // position rounded to lower multiple of 256m
506 m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
507 m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
508 }
354 } 509 }
355 510
356 #region Client Camera 511 #region Client Camera
@@ -382,11 +537,8 @@ namespace OpenSim.Region.Framework.Scenes
382 get 537 get
383 { 538 {
384 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 539 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
385 540 a.Normalize();
386 if (a == Vector3.Zero) 541 return a;
387 return a;
388
389 return Util.GetNormalizedVector(a);
390 } 542 }
391 } 543 }
392 #endregion 544 #endregion
@@ -426,6 +578,7 @@ namespace OpenSim.Region.Framework.Scenes
426 } 578 }
427 } 579 }
428 580
581
429 public byte State { get; set; } 582 public byte State { get; set; }
430 583
431 private AgentManager.ControlFlags m_AgentControlFlags; 584 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -464,6 +617,7 @@ namespace OpenSim.Region.Framework.Scenes
464 } 617 }
465 else 618 else
466 { 619 {
620// m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
467 // Obtain the correct position of a seated avatar. 621 // Obtain the correct position of a seated avatar.
468 // In addition to providing the correct position while 622 // In addition to providing the correct position while
469 // the avatar is seated, this value will also 623 // the avatar is seated, this value will also
@@ -477,17 +631,21 @@ namespace OpenSim.Region.Framework.Scenes
477 // in the sim unless the avatar is on a sit target. While 631 // in the sim unless the avatar is on a sit target. While
478 // on a sit target, m_pos will contain the desired offset 632 // on a sit target, m_pos will contain the desired offset
479 // without the parent rotation applied. 633 // without the parent rotation applied.
480 SceneObjectPart sitPart = ParentPart; 634 if (ParentPart != null)
481 635 {
482 if (sitPart != null) 636 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
483 return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 637 // if (sitPart != null)
638 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
639 if (rootPart != null)
640 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
641 }
484 } 642 }
485 643
486 return m_pos; 644 return m_pos;
487 } 645 }
488 set 646 set
489 { 647 {
490// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 648// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
491// Util.PrintCallStack(); 649// Util.PrintCallStack();
492 650
493 if (PhysicsActor != null) 651 if (PhysicsActor != null)
@@ -504,10 +662,7 @@ namespace OpenSim.Region.Framework.Scenes
504 662
505 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 663 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
506 if (ParentID == 0) 664 if (ParentID == 0)
507 {
508 m_pos = value; 665 m_pos = value;
509// ParentPosition = Vector3.Zero;
510 }
511 666
512 //m_log.DebugFormat( 667 //m_log.DebugFormat(
513 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 668 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -575,24 +730,7 @@ namespace OpenSim.Region.Framework.Scenes
575// Scene.RegionInfo.RegionName, Name, m_velocity); 730// Scene.RegionInfo.RegionName, Name, m_velocity);
576 } 731 }
577 } 732 }
578/*
579 public override Vector3 AngularVelocity
580 {
581 get
582 {
583 if (PhysicsActor != null)
584 {
585 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
586
587 // m_log.DebugFormat(
588 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
589 // m_velocity, Name, Scene.RegionInfo.RegionName);
590 }
591 733
592 return m_rotationalvelocity;
593 }
594 }
595*/
596 private Quaternion m_bodyRot = Quaternion.Identity; 734 private Quaternion m_bodyRot = Quaternion.Identity;
597 735
598 /// <summary> 736 /// <summary>
@@ -762,6 +900,20 @@ namespace OpenSim.Region.Framework.Scenes
762 } 900 }
763 } 901 }
764 902
903
904 /// <summary>
905 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
906 /// </summary>
907 /// <remarks>
908 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
909 /// </remarks>
910 private const float AgentControlStopSlowVel = 0.2f;
911 // velocities
912 public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
913 public const float AgentControlNormalVel = 1.0f;
914
915 // old normal speed was tuned to match sl normal plus Fast modifiers
916 // so we need to rescale it
765 private float m_speedModifier = 1.0f; 917 private float m_speedModifier = 1.0f;
766 918
767 public float SpeedModifier 919 public float SpeedModifier
@@ -797,13 +949,15 @@ namespace OpenSim.Region.Framework.Scenes
797 949
798 public ScenePresence( 950 public ScenePresence(
799 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 951 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
800 { 952 {
953 Invisible = false;
801 AttachmentsSyncLock = new Object(); 954 AttachmentsSyncLock = new Object();
802 AllowMovement = true; 955 AllowMovement = true;
803 IsChildAgent = true; 956 IsChildAgent = true;
804 IsLoggingIn = false; 957 IsLoggingIn = false;
805 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 958 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
806 Animator = new ScenePresenceAnimator(this); 959 Animator = new ScenePresenceAnimator(this);
960 Overrides = new MovementAnimationOverrides();
807 PresenceType = type; 961 PresenceType = type;
808 DrawDistance = world.DefaultDrawDistance; 962 DrawDistance = world.DefaultDrawDistance;
809 RegionHandle = world.RegionInfo.RegionHandle; 963 RegionHandle = world.RegionInfo.RegionHandle;
@@ -813,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
813 m_name = String.Format("{0} {1}", Firstname, Lastname); 967 m_name = String.Format("{0} {1}", Firstname, Lastname);
814 m_scene = world; 968 m_scene = world;
815 m_uuid = client.AgentId; 969 m_uuid = client.AgentId;
816 LocalId = m_scene.AllocateLocalId(); 970 LocalId = m_scene.AllocatePresenceLocalId();
817 971
818 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 972 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
819 if (account != null) 973 if (account != null)
@@ -826,7 +980,7 @@ namespace OpenSim.Region.Framework.Scenes
826 980
827 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 981 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
828 if (gm != null) 982 if (gm != null)
829 Grouptitle = gm.GetGroupTitle(m_uuid); 983 Grouptitle = gm.GetGroupTitle(m_uuid);
830 984
831 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 985 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
832 986
@@ -843,6 +997,8 @@ namespace OpenSim.Region.Framework.Scenes
843 SetDirectionVectors(); 997 SetDirectionVectors();
844 998
845 Appearance = appearance; 999 Appearance = appearance;
1000
1001 m_stateMachine = new ScenePresenceStateMachine(this);
846 } 1002 }
847 1003
848 private void RegionHeartbeatEnd(Scene scene) 1004 private void RegionHeartbeatEnd(Scene scene)
@@ -876,6 +1032,7 @@ namespace OpenSim.Region.Framework.Scenes
876 { 1032 {
877 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 1033 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
878 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 1034 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
1035 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
879 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 1036 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
880 ControllingClient.OnAgentSit += HandleAgentSit; 1037 ControllingClient.OnAgentSit += HandleAgentSit;
881 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1038 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -892,22 +1049,24 @@ namespace OpenSim.Region.Framework.Scenes
892 1049
893 private void SetDirectionVectors() 1050 private void SetDirectionVectors()
894 { 1051 {
895 Dir_Vectors[0] = Vector3.UnitX; //FORWARD 1052 Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
896 Dir_Vectors[1] = -Vector3.UnitX; //BACK 1053 Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
897 Dir_Vectors[2] = Vector3.UnitY; //LEFT 1054 Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
898 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 1055 Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
899 Dir_Vectors[4] = Vector3.UnitZ; //UP 1056 Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
900 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 1057 Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
901 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE 1058 Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
902 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE 1059 Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
903 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE 1060 Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
904 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE 1061 Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
905 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1062 Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
906 } 1063 Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
907 1064 }
1065
1066/* dont see any use for this
908 private Vector3[] GetWalkDirectionVectors() 1067 private Vector3[] GetWalkDirectionVectors()
909 { 1068 {
910 Vector3[] vector = new Vector3[11]; 1069 Vector3[] vector = new Vector3[12];
911 vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD 1070 vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD
912 vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK 1071 vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK
913 vector[2] = Vector3.UnitY; //LEFT 1072 vector[2] = Vector3.UnitY; //LEFT
@@ -918,10 +1077,11 @@ namespace OpenSim.Region.Framework.Scenes
918 vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE 1077 vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE
919 vector[8] = Vector3.UnitY; //LEFT_NUDGE 1078 vector[8] = Vector3.UnitY; //LEFT_NUDGE
920 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE 1079 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
921 vector[10] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE 1080 vector[10] = new Vector3(CameraAtAxis.Z, 0f, CameraUpAxis.Z); //UP_NUDGE
1081 vector[11] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE
922 return vector; 1082 return vector;
923 } 1083 }
924 1084*/
925 #endregion 1085 #endregion
926 1086
927 #region Status Methods 1087 #region Status Methods
@@ -929,6 +1089,7 @@ namespace OpenSim.Region.Framework.Scenes
929 /// <summary> 1089 /// <summary>
930 /// Turns a child agent into a root agent. 1090 /// Turns a child agent into a root agent.
931 /// </summary> 1091 /// </summary>
1092 /// <remarks>
932 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 1093 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
933 /// avatar is actual in the sim. They can perform all actions. 1094 /// avatar is actual in the sim. They can perform all actions.
934 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1095 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -936,90 +1097,81 @@ namespace OpenSim.Region.Framework.Scenes
936 /// 1097 ///
937 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1098 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
938 /// delays that crossing. 1099 /// delays that crossing.
939 /// </summary> 1100 /// </remarks>
940 public void MakeRootAgent(Vector3 pos, bool isFlying) 1101
1102
1103 // only in use as part of completemovement
1104 // other uses need fix
1105 private bool MakeRootAgent(Vector3 pos, bool isFlying)
941 { 1106 {
942 m_log.DebugFormat( 1107 int ts = Util.EnvironmentTickCount();
943 "[SCENE]: Upgrading child to root agent for {0} in {1}",
944 Name, m_scene.RegionInfo.RegionName);
945 1108
946 if (ParentUUID != UUID.Zero) 1109 lock (m_completeMovementLock)
947 { 1110 {
948 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1111 if (!IsChildAgent)
949 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1112 return false;
950 if (part == null) 1113
1114 m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1115 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1116
1117 // m_log.InfoFormat(
1118 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1119 // Name, m_scene.RegionInfo.RegionName);
1120
1121 if (ParentUUID != UUID.Zero)
951 { 1122 {
952 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1123 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1124 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1125 if (part == null)
1126 {
1127 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1128 ParentID = 0;
1129 ParentPart = null;
1130 PrevSitOffset = Vector3.Zero;
1131 HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1132 IsLoggingIn = false;
1133 }
1134 else
1135 {
1136 part.ParentGroup.AddAvatar(UUID);
1137 if (part.SitTargetPosition != Vector3.Zero)
1138 part.SitTargetAvatar = UUID;
1139 ParentID = part.LocalId;
1140 ParentPart = part;
1141 m_pos = PrevSitOffset;
1142 pos = part.GetWorldPosition();
1143 }
1144 ParentUUID = UUID.Zero;
953 } 1145 }
954 else 1146 else
955 { 1147 {
956 part.ParentGroup.AddAvatar(UUID); 1148 IsLoggingIn = false;
957 if (part.SitTargetPosition != Vector3.Zero)
958 part.SitTargetAvatar = UUID;
959// ParentPosition = part.GetWorldPosition();
960 ParentID = part.LocalId;
961 ParentPart = part;
962 m_pos = PrevSitOffset;
963// pos = ParentPosition;
964 pos = part.GetWorldPosition();
965 } 1149 }
966 ParentUUID = UUID.Zero;
967 1150
968 IsChildAgent = false; 1151 IsChildAgent = false;
969
970// Animator.TrySetMovementAnimation("SIT");
971 }
972 else
973 {
974 IsChildAgent = false;
975 IsLoggingIn = false;
976 } 1152 }
977 1153
978 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1154 m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
979 1155
980 IsChildAgent = false; 1156 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1157 // set and prevent the close of the connection on a subsequent re-teleport.
1158 // Should not be needed if we are not trying to tell this region to close
1159 // DoNotCloseAfterTeleport = false;
981 1160
982 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1161 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
983 if (gm != null) 1162 if (gm != null)
984 Grouptitle = gm.GetGroupTitle(m_uuid); 1163 Grouptitle = gm.GetGroupTitle(m_uuid);
985 1164
1165 m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1166
986 RegionHandle = m_scene.RegionInfo.RegionHandle; 1167 RegionHandle = m_scene.RegionInfo.RegionHandle;
987 1168
988 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1169 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1170 m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
989 1171
990 UUID groupUUID = UUID.Zero;
991 string GroupName = string.Empty;
992 ulong groupPowers = 0;
993
994 // ----------------------------------
995 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
996 try
997 {
998 if (gm != null)
999 {
1000 groupUUID = ControllingClient.ActiveGroupId;
1001 GroupRecord record = gm.GetGroupRecord(groupUUID);
1002 if (record != null)
1003 GroupName = record.GroupName;
1004 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1005 if (groupMembershipData != null)
1006 groupPowers = groupMembershipData.GroupPowers;
1007 }
1008 ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName,
1009 Grouptitle);
1010 }
1011 catch (Exception e)
1012 {
1013 m_log.Debug("[AGENTUPDATE]: " + e.ToString());
1014 }
1015 // ------------------------------------
1016 1172
1017 if (ParentID == 0) 1173 if (ParentID == 0)
1018 { 1174 {
1019 // Moved this from SendInitialData to ensure that Appearance is initialized
1020 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1021 // related to the handling of attachments
1022 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1023 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1175 if (m_scene.TestBorderCross(pos, Cardinals.E))
1024 { 1176 {
1025 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1177 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
@@ -1053,7 +1205,7 @@ namespace OpenSim.Region.Framework.Scenes
1053 1205
1054 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1206 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
1055 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1207 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1056 1208
1057 float newPosZ = posZLimit + localAVHeight / 2; 1209 float newPosZ = posZLimit + localAVHeight / 2;
1058 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1210 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1059 { 1211 {
@@ -1061,6 +1213,7 @@ namespace OpenSim.Region.Framework.Scenes
1061 } 1213 }
1062 AbsolutePosition = pos; 1214 AbsolutePosition = pos;
1063 1215
1216
1064 if (m_teleportFlags == TeleportFlags.Default) 1217 if (m_teleportFlags == TeleportFlags.Default)
1065 { 1218 {
1066 Vector3 vel = Velocity; 1219 Vector3 vel = Velocity;
@@ -1071,12 +1224,6 @@ namespace OpenSim.Region.Framework.Scenes
1071 else 1224 else
1072 AddToPhysicalScene(isFlying); 1225 AddToPhysicalScene(isFlying);
1073 1226
1074 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1075 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1076 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1077 // the value to a negative position which does not trigger the border cross.
1078 // This may not be the best location for this.
1079 CheckForBorderCrossing();
1080 1227
1081 if (ForceFly) 1228 if (ForceFly)
1082 { 1229 {
@@ -1086,66 +1233,21 @@ namespace OpenSim.Region.Framework.Scenes
1086 { 1233 {
1087 Flying = false; 1234 Flying = false;
1088 } 1235 }
1089 }
1090 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
1091 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
1092 // elsewhere anyway
1093 // Animator.SendAnimPack();
1094 1236
1095 m_scene.SwapRootAgentCount(false); 1237 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1238 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1239 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1240 // the value to a negative position which does not trigger the border cross.
1241 // This may not be the best location for this.
1096 1242
1097 // The initial login scene presence is already root when it gets here
1098 // and it has already rezzed the attachments and started their scripts.
1099 // We do the following only for non-login agents, because their scripts
1100 // haven't started yet.
1101 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1102 {
1103 // Viewers which have a current outfit folder will actually rez their own attachments. However,
1104 // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
1105 if (Scene.AttachmentsModule != null)
1106 Util.FireAndForget(
1107 o =>
1108 {
1109// if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None)
1110// System.Threading.Thread.Sleep(7000);
1111 1243
1112 Scene.AttachmentsModule.RezAttachments(this); 1244 // its not
1113 }); 1245// CheckForBorderCrossing();
1114 } 1246 }
1115 else 1247
1116 { 1248 m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1117 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT 1249 m_scene.SwapRootAgentCount(false);
1118 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1119 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1120 // not transporting the required data.
1121 lock (m_attachments)
1122 {
1123 if (HasAttachments())
1124 {
1125 m_log.DebugFormat(
1126 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1127
1128 // Resume scripts
1129 Util.FireAndForget(delegate(object x) {
1130 foreach (SceneObjectGroup sog in m_attachments)
1131 {
1132 sog.ScheduleGroupForFullUpdate();
1133 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1134 sog.ResumeScripts();
1135 }
1136 });
1137 }
1138 }
1139 }
1140
1141 SendAvatarDataToAllAgents();
1142 1250
1143 // send the animations of the other presences to me
1144 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1145 {
1146 if (presence != this)
1147 presence.Animator.SendAnimPackToClient(ControllingClient);
1148 });
1149 1251
1150 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1252 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1151 // stall on the border crossing since the existing child agent will still have the last movement 1253 // stall on the border crossing since the existing child agent will still have the last movement
@@ -1154,8 +1256,9 @@ namespace OpenSim.Region.Framework.Scenes
1154 MovementFlag = 0; 1256 MovementFlag = 0;
1155 1257
1156 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1258 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1259 m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1157 1260
1158 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1261 return true;
1159 } 1262 }
1160 1263
1161 public int GetStateSource() 1264 public int GetStateSource()
@@ -1181,11 +1284,19 @@ namespace OpenSim.Region.Framework.Scenes
1181 /// It doesn't get called for a teleport. Reason being, an agent that 1284 /// It doesn't get called for a teleport. Reason being, an agent that
1182 /// teleports out may not end up anywhere near this region 1285 /// teleports out may not end up anywhere near this region
1183 /// </remarks> 1286 /// </remarks>
1184 public void MakeChildAgent() 1287 public void MakeChildAgent(ulong newRegionHandle)
1185 { 1288 {
1186 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1289 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1187 1290
1188 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1291 RegionHandle = newRegionHandle;
1292
1293 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1294 Name, Scene.RegionInfo.RegionName, newRegionHandle);
1295
1296 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1297 // from the source simulator has completed on a V2 teleport.
1298 lock (m_originRegionIDAccessLock)
1299 m_originRegionID = UUID.Zero;
1189 1300
1190 // Reset these so that teleporting in and walking out isn't seen 1301 // Reset these so that teleporting in and walking out isn't seen
1191 // as teleporting back 1302 // as teleporting back
@@ -1200,7 +1311,7 @@ namespace OpenSim.Region.Framework.Scenes
1200 else 1311 else
1201 Animator.ResetAnimations(); 1312 Animator.ResetAnimations();
1202 1313
1203 1314
1204// m_log.DebugFormat( 1315// m_log.DebugFormat(
1205// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1316// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1206// Name, UUID, m_scene.RegionInfo.RegionName); 1317// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1214,8 +1325,15 @@ namespace OpenSim.Region.Framework.Scenes
1214 RemoveFromPhysicalScene(); 1325 RemoveFromPhysicalScene();
1215 ParentID = 0; // Child agents can't be sitting 1326 ParentID = 0; // Child agents can't be sitting
1216 1327
1328// we dont have land information for child
1329 m_previusParcelHide = false;
1330 m_previusParcelUUID = UUID.Zero;
1331 m_currentParcelHide = false;
1332 m_currentParcelUUID = UUID.Zero;
1217 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1333 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1218 1334
1335 CollisionPlane = Vector4.UnitW;
1336
1219 m_scene.EventManager.TriggerOnMakeChildAgent(this); 1337 m_scene.EventManager.TriggerOnMakeChildAgent(this);
1220 } 1338 }
1221 1339
@@ -1308,7 +1426,29 @@ namespace OpenSim.Region.Framework.Scenes
1308 1426
1309 public void StopFlying() 1427 public void StopFlying()
1310 { 1428 {
1311 ControllingClient.StopFlying(this); 1429 if (IsInTransit)
1430 return;
1431
1432 Vector3 pos = AbsolutePosition;
1433 if (Appearance.AvatarHeight != 127.0f)
1434 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1435 else
1436 pos += new Vector3(0f, 0f, (1.56f / 6f));
1437
1438 AbsolutePosition = pos;
1439
1440 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1441 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1442 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1443 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1444
1445 // why are we still testing for this really old height value default???
1446 if (Appearance.AvatarHeight != 127.0f)
1447 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1448 else
1449 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1450
1451 SendAgentTerseUpdate(this);
1312 } 1452 }
1313 1453
1314 /// <summary> 1454 /// <summary>
@@ -1428,6 +1568,14 @@ namespace OpenSim.Region.Framework.Scenes
1428 } 1568 }
1429 } 1569 }
1430 1570
1571 public void DropThisRootRegionFromNeighbours()
1572 {
1573 ulong handle = m_scene.RegionInfo.RegionHandle;
1574 RemoveNeighbourRegion(handle);
1575 Scene.CapsModule.DropChildSeed(UUID, handle);
1576 }
1577
1578
1431 public Dictionary<ulong, string> KnownRegions 1579 public Dictionary<ulong, string> KnownRegions
1432 { 1580 {
1433 get 1581 get
@@ -1482,6 +1630,37 @@ namespace OpenSim.Region.Framework.Scenes
1482 1630
1483 } 1631 }
1484 1632
1633 private bool WaitForUpdateAgent(IClientAPI client)
1634 {
1635 // Before the source region executes UpdateAgent
1636 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1637 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1638 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1639 int count = 50;
1640 UUID originID;
1641
1642 lock (m_originRegionIDAccessLock)
1643 originID = m_originRegionID;
1644
1645 while (originID.Equals(UUID.Zero) && count-- > 0)
1646 {
1647 lock (m_originRegionIDAccessLock)
1648 originID = m_originRegionID;
1649
1650 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1651 Thread.Sleep(200);
1652 }
1653
1654 if (originID.Equals(UUID.Zero))
1655 {
1656 // Movement into region will fail
1657 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1658 return false;
1659 }
1660
1661 return true;
1662 }
1663
1485 /// <summary> 1664 /// <summary>
1486 /// Complete Avatar's movement into the region. 1665 /// Complete Avatar's movement into the region.
1487 /// </summary> 1666 /// </summary>
@@ -1493,53 +1672,88 @@ namespace OpenSim.Region.Framework.Scenes
1493 /// </param> 1672 /// </param>
1494 public void CompleteMovement(IClientAPI client, bool openChildAgents) 1673 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1495 { 1674 {
1496// DateTime startTime = DateTime.Now; 1675 int ts = Util.EnvironmentTickCount();
1497 1676
1498 m_log.DebugFormat( 1677 m_log.InfoFormat(
1499 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1678 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1500 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1679 client.Name, Scene.Name, AbsolutePosition);
1501 1680
1502 Vector3 look = Velocity; 1681 m_inTransit = true;
1503 1682
1504 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1683 try
1505 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1506 { 1684 {
1507 look = new Vector3(0.99f, 0.042f, 0); 1685 // Make sure it's not a login agent. We don't want to wait for updates during login
1508 } 1686 if (!isNPC && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1687 {
1509 1688
1510 // Prevent teleporting to an underground location 1689 // Let's wait until UpdateAgent (called by departing region) is done
1511 // (may crash client otherwise) 1690 if (!WaitForUpdateAgent(client))
1512 // 1691 // The sending region never sent the UpdateAgent data, we have to refuse
1513 Vector3 pos = AbsolutePosition; 1692 return;
1514 float ground = m_scene.GetGroundHeight(pos.X, pos.Y); 1693 }
1515 if (pos.Z < ground + 1.5f)
1516 {
1517 pos.Z = ground + 1.5f;
1518 AbsolutePosition = pos;
1519 }
1520 1694
1521 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1695 m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1522 MakeRootAgent(AbsolutePosition, flying);
1523 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1524 1696
1525// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1697 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1526 1698
1527 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1699 if (!MakeRootAgent(AbsolutePosition, flying))
1528 { 1700 {
1529 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1701 m_log.DebugFormat(
1530 // CompleteMovement() is executed synchronously. However, it might be better to delay the release 1702 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1531 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 1703 Name, Scene.Name);
1532 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this 1704
1533 // region as the current region, meaning that a close sent before then will fail the teleport. 1705 return;
1534// System.Threading.Thread.Sleep(2000); 1706 }
1535 1707
1536 m_log.DebugFormat( 1708 m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1537 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1538 client.Name, client.AgentId, m_callbackURI);
1539 1709
1540 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1710 Vector3 look = Lookat;
1541 m_callbackURI = null; 1711 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1542 } 1712 {
1713 look = Velocity;
1714 look.Z = 0;
1715 look.Normalize();
1716 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1717 look = new Vector3(0.99f, 0.042f, 0);
1718 }
1719
1720 if (!IsChildAgent && !isNPC)
1721 {
1722 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
1723 if (cof == null)
1724 COF = UUID.Zero;
1725 else
1726 COF = cof.ID;
1727
1728 m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1729 }
1730
1731 // Tell the client that we're totally ready
1732 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1733
1734 m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1735
1736 if (!string.IsNullOrEmpty(m_callbackURI))
1737 {
1738 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1739 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
1740 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1741 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1742 // region as the current region, meaning that a close sent before then will fail the teleport.
1743 // System.Threading.Thread.Sleep(2000);
1744
1745 m_log.DebugFormat(
1746 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1747 client.Name, client.AgentId, m_callbackURI);
1748
1749 UUID originID;
1750
1751 lock (m_originRegionIDAccessLock)
1752 originID = m_originRegionID;
1753
1754 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1755 m_callbackURI = null;
1756 }
1543// else 1757// else
1544// { 1758// {
1545// m_log.DebugFormat( 1759// m_log.DebugFormat(
@@ -1547,34 +1761,181 @@ namespace OpenSim.Region.Framework.Scenes
1547// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 1761// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1548// } 1762// }
1549 1763
1550 ValidateAndSendAppearanceAndAgentData(); 1764 m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1551 1765
1552 // Create child agents in neighbouring regions 1766 m_previusParcelHide = false;
1553 if (openChildAgents && !IsChildAgent) 1767 m_previusParcelUUID = UUID.Zero;
1554 { 1768 m_currentParcelHide = false;
1769 m_currentParcelUUID = UUID.Zero;
1555 1770
1556 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1771 // send initial land overlay and parcel
1557 if (m_agentTransfer != null) 1772 ILandChannel landch = m_scene.LandChannel;
1558 m_agentTransfer.EnableChildAgents(this); 1773 if (landch != null)
1774 landch.sendClientInitialLandInfo(client);
1559 1775
1560 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1776 if (!IsChildAgent)
1561 if (friendsModule != null) 1777 {
1562 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1563 1778
1564 } 1779 // ValidateAndSendAppearanceAndAgentData();
1565 1780
1566 // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region 1781 // do it here in line
1567 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. 1782 // so sequence is clear
1568 // This may be due to viewer code or it may be something we're not doing properly simulator side. 1783
1569 lock (m_attachments) 1784 // verify baked textures and cache
1785
1786
1787 bool cachedbaked = false;
1788
1789 if (isNPC)
1790 cachedbaked = true;
1791 else
1792 {
1793 if (m_scene.AvatarFactory != null)
1794 cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
1795
1796 // not sure we need this
1797 if (!cachedbaked)
1798 {
1799 if (m_scene.AvatarFactory != null)
1800 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
1801 }
1802 }
1803
1804 List<ScenePresence> allpresences = m_scene.GetScenePresences();
1805
1806 // send avatar object to all presences including us, so they cross it into region
1807 // then hide if necessary
1808 SendInitialAvatarDataToAllAgents(allpresences);
1809
1810 // send this look
1811 SendAppearanceToAgent(this);
1812
1813 // send this animations
1814
1815 UUID[] animIDs = null;
1816 int[] animseqs = null;
1817 UUID[] animsobjs = null;
1818
1819 if (Animator != null)
1820 Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
1821
1822 bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
1823
1824 if(haveAnims)
1825 SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
1826
1827 // we should be able to receive updates, etc
1828 // so release them
1829 m_inTransit = false;
1830
1831 // send look and animations to others
1832 // if not cached we send greys
1833 // uncomented if will wait till avatar does baking
1834 //if (cachedbaked)
1835 {
1836 foreach (ScenePresence p in allpresences)
1837 {
1838 if (p == this)
1839 continue;
1840
1841 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1842 continue;
1843
1844 SendAppearanceToAgentNF(p);
1845 if (haveAnims)
1846 SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
1847 }
1848 } // greys if
1849
1850 m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1851
1852 // attachments
1853
1854 if (isNPC || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1855 {
1856 if (Scene.AttachmentsModule != null)
1857 // Util.FireAndForget(
1858 // o =>
1859 // {
1860 Scene.AttachmentsModule.RezAttachments(this);
1861 // });
1862 }
1863 else
1864 {
1865 if (m_attachments.Count > 0)
1866 {
1867 m_log.DebugFormat(
1868 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1869
1870 foreach(SceneObjectGroup sog in m_attachments)
1871 {
1872 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1873 sog.ResumeScripts();
1874 }
1875
1876 foreach (ScenePresence p in allpresences)
1877 {
1878 if (p == this)
1879 {
1880 SendTerseUpdateToAgentNF(this);
1881 SendAttachmentsToAgentNF(this);
1882 continue;
1883 }
1884
1885 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1886 continue;
1887
1888 SendTerseUpdateToAgentNF(p);
1889 SendAttachmentsToAgentNF(p);
1890 }
1891 }
1892 }
1893
1894 m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1895
1896 // Create child agents in neighbouring regions
1897 if (openChildAgents)
1898 {
1899 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1900 if (m_agentTransfer != null)
1901 {
1902 m_agentTransfer.EnableChildAgents(this);
1903 }
1904 }
1905 }
1906
1907 m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1908
1909 // send the rest of the world
1910 if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
1911 SendInitialDataToMe();
1912
1913 m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1914
1915 if (!IsChildAgent && openChildAgents)
1916 {
1917 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1918 if (friendsModule != null)
1919 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1920
1921 m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1922
1923 }
1924 }
1925 finally
1570 { 1926 {
1571 foreach (SceneObjectGroup sog in m_attachments) 1927 m_inTransit = false;
1572 sog.ScheduleGroupForFullUpdate();
1573 } 1928 }
1929 // if hide force a check
1930 // if (!IsChildAgent && newhide)
1931 // {
1932 // ParcelLoginCheck(m_currentParcelUUID);
1933 // m_currentParcelHide = newhide;
1934 // }
1574 1935
1575// m_log.DebugFormat( 1936 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1576// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1937
1577// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1938 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1578 } 1939 }
1579 1940
1580 /// <summary> 1941 /// <summary>
@@ -1655,9 +2016,9 @@ namespace OpenSim.Region.Framework.Scenes
1655 /// </summary> 2016 /// </summary>
1656 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 2017 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1657 { 2018 {
1658// m_log.DebugFormat( 2019 //m_log.DebugFormat(
1659// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 2020 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1660// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 2021 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1661 2022
1662 if (IsChildAgent) 2023 if (IsChildAgent)
1663 { 2024 {
@@ -1665,9 +2026,8 @@ namespace OpenSim.Region.Framework.Scenes
1665 return; 2026 return;
1666 } 2027 }
1667 2028
1668 ++m_movementUpdateCount; 2029 if (IsInTransit)
1669 if (m_movementUpdateCount < 1) 2030 return;
1670 m_movementUpdateCount = 1;
1671 2031
1672 #region Sanity Checking 2032 #region Sanity Checking
1673 2033
@@ -1699,27 +2059,14 @@ namespace OpenSim.Region.Framework.Scenes
1699 2059
1700 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 2060 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1701 2061
1702 // Camera location in world. We'll need to raytrace
1703 // from this location from time to time.
1704 CameraPosition = agentData.CameraCenter;
1705 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
1706 {
1707 ReprioritizeUpdates();
1708 m_lastCameraPosition = CameraPosition;
1709 }
1710
1711 // Use these three vectors to figure out what the agent is looking at
1712 // Convert it to a Matrix and/or Quaternion
1713 CameraAtAxis = agentData.CameraAtAxis;
1714 CameraLeftAxis = agentData.CameraLeftAxis;
1715 CameraUpAxis = agentData.CameraUpAxis;
1716
1717 // The Agent's Draw distance setting 2062 // The Agent's Draw distance setting
1718 // When we get to the point of re-computing neighbors everytime this 2063 // When we get to the point of re-computing neighbors everytime this
1719 // changes, then start using the agent's drawdistance rather than the 2064 // changes, then start using the agent's drawdistance rather than the
1720 // region's draw distance. 2065 // region's draw distance.
1721 // DrawDistance = agentData.Far; 2066
1722 DrawDistance = Scene.DefaultDrawDistance; 2067 DrawDistance = Util.Clamp(agentData.Far, 32, m_scene.MaxDrawDistance);
2068
2069// DrawDistance = Scene.DefaultDrawDistance;
1723 2070
1724 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 2071 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1725 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 2072 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
@@ -1735,6 +2082,7 @@ namespace OpenSim.Region.Framework.Scenes
1735// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2082// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1736// m_updateCount = UPDATE_COUNT; 2083// m_updateCount = UPDATE_COUNT;
1737 2084
2085
1738 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2086 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1739 { 2087 {
1740 StandUp(); 2088 StandUp();
@@ -1785,9 +2133,16 @@ namespace OpenSim.Region.Framework.Scenes
1785 // Here's where you get them. 2133 // Here's where you get them.
1786 m_AgentControlFlags = flags; 2134 m_AgentControlFlags = flags;
1787 m_headrotation = agentData.HeadRotation; 2135 m_headrotation = agentData.HeadRotation;
2136 byte oldState = State;
1788 State = agentData.State; 2137 State = agentData.State;
1789 2138
2139 // We need to send this back to the client in order to stop the edit beams
2140 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2141 SendAgentTerseUpdate(this);
2142
1790 PhysicsActor actor = PhysicsActor; 2143 PhysicsActor actor = PhysicsActor;
2144
2145 // This will be the case if the agent is sitting on the groudn or on an object.
1791 if (actor == null) 2146 if (actor == null)
1792 { 2147 {
1793 SendControlsToScripts(flagsForScripts); 2148 SendControlsToScripts(flagsForScripts);
@@ -1796,12 +2151,11 @@ namespace OpenSim.Region.Framework.Scenes
1796 2151
1797 if (AllowMovement && !SitGround) 2152 if (AllowMovement && !SitGround)
1798 { 2153 {
1799 Quaternion bodyRotation = agentData.BodyRotation; 2154// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1800 bool update_rotation = false; 2155 bool update_rotation = false;
1801 2156 if (agentData.BodyRotation != Rotation)
1802 if (bodyRotation != Rotation)
1803 { 2157 {
1804 Rotation = bodyRotation; 2158 Rotation = agentData.BodyRotation;
1805 update_rotation = true; 2159 update_rotation = true;
1806 } 2160 }
1807 2161
@@ -1817,7 +2171,7 @@ namespace OpenSim.Region.Framework.Scenes
1817 bool DCFlagKeyPressed = false; 2171 bool DCFlagKeyPressed = false;
1818 Vector3 agent_control_v3 = Vector3.Zero; 2172 Vector3 agent_control_v3 = Vector3.Zero;
1819 2173
1820 bool newFlying = actor.Flying; 2174 bool newFlying = false;
1821 2175
1822 if (ForceFly) 2176 if (ForceFly)
1823 newFlying = true; 2177 newFlying = true;
@@ -1842,15 +2196,13 @@ namespace OpenSim.Region.Framework.Scenes
1842 2196
1843 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying 2197 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
1844 // this prevents 'jumping' in inappropriate situations. 2198 // this prevents 'jumping' in inappropriate situations.
1845 if (!Flying && (m_mouseLook || m_leftButtonDown)) 2199// if (!Flying && (m_mouseLook || m_leftButtonDown))
1846 dirVectors = GetWalkDirectionVectors(); 2200// dirVectors = GetWalkDirectionVectors();
1847 else 2201// else
1848 dirVectors = Dir_Vectors; 2202 dirVectors = Dir_Vectors;
1849 2203
1850 // The fact that MovementFlag is a byte needs to be fixed 2204
1851 // it really should be a uint
1852 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2205 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
1853 uint nudgehack = 250;
1854 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2206 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1855 { 2207 {
1856 if (((uint)flags & (uint)DCF) != 0) 2208 if (((uint)flags & (uint)DCF) != 0)
@@ -1867,29 +2219,19 @@ namespace OpenSim.Region.Framework.Scenes
1867 // Why did I get this? 2219 // Why did I get this?
1868 } 2220 }
1869 2221
1870 if ((MovementFlag & (byte)(uint)DCF) == 0) 2222 if (((MovementFlag & (uint)DCF) == 0))
1871 { 2223 {
1872 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1873 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1874 {
1875 MovementFlag |= (byte)nudgehack;
1876 }
1877
1878 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2224 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1879 MovementFlag += (byte)(uint)DCF; 2225 MovementFlag |= (uint)DCF;
1880 update_movementflag = true; 2226 update_movementflag = true;
1881 } 2227 }
1882 } 2228 }
1883 else 2229 else
1884 { 2230 {
1885 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2231 if ((MovementFlag & (uint)DCF) != 0)
1886 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1887 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1888 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1889 ) // This or is for Nudge forward
1890 { 2232 {
1891 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2233 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1892 MovementFlag -= ((byte)(uint)DCF); 2234 MovementFlag &= (uint)~DCF;
1893 update_movementflag = true; 2235 update_movementflag = true;
1894 2236
1895 /* 2237 /*
@@ -1909,6 +2251,13 @@ namespace OpenSim.Region.Framework.Scenes
1909 i++; 2251 i++;
1910 } 2252 }
1911 2253
2254 // Detect AGENT_CONTROL_STOP state changes
2255 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2256 {
2257 AgentControlStopActive = !AgentControlStopActive;
2258 update_movementflag = true;
2259 }
2260
1912 if (MovingToTarget) 2261 if (MovingToTarget)
1913 { 2262 {
1914 // If the user has pressed a key then we want to cancel any move to target. 2263 // If the user has pressed a key then we want to cancel any move to target.
@@ -1934,74 +2283,167 @@ namespace OpenSim.Region.Framework.Scenes
1934 // Only do this if we're flying 2283 // Only do this if we're flying
1935 if (Flying && !ForceFly) 2284 if (Flying && !ForceFly)
1936 { 2285 {
1937 // Landing detection code 2286 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1938 2287 // if (AgentControlStopActive)
1939 // Are the landing controls requirements filled? 2288 // {
1940 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2289 // agent_control_v3 = Vector3.Zero;
1941 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2290 // }
1942 2291 // else
1943 //m_log.Debug("[CONTROL]: " +flags);
1944 // Applies a satisfying roll effect to the avatar when flying.
1945 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
1946 {
1947 ApplyFlyingRoll(
1948 FLY_ROLL_RADIANS_PER_UPDATE,
1949 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1950 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1951 }
1952 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
1953 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1954 {
1955 ApplyFlyingRoll(
1956 -FLY_ROLL_RADIANS_PER_UPDATE,
1957 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1958 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1959 }
1960 else
1961 { 2292 {
1962 if (m_AngularVelocity.Z != 0) 2293 // Landing detection code
1963 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1964 }
1965 2294
1966 if (Flying && IsColliding && controlland) 2295 // Are the landing controls requirements filled?
1967 { 2296 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1968 // nesting this check because LengthSquared() is expensive and we don't 2297 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1969 // want to do it every step when flying. 2298
1970 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2299 //m_log.Debug("[CONTROL]: " +flags);
1971 StopFlying(); 2300 // Applies a satisfying roll effect to the avatar when flying.
2301 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2302 {
2303 ApplyFlyingRoll(
2304 FLY_ROLL_RADIANS_PER_UPDATE,
2305 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2306 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2307 }
2308 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2309 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2310 {
2311 ApplyFlyingRoll(
2312 -FLY_ROLL_RADIANS_PER_UPDATE,
2313 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2314 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2315 }
2316 else
2317 {
2318 if (m_AngularVelocity.Z != 0)
2319 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2320 }
2321
2322 /*
2323 if (Flying && IsColliding && controlland)
2324 {
2325 // nesting this check because LengthSquared() is expensive and we don't
2326 // want to do it every step when flying.
2327 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2328 StopFlying();
2329 }
2330 */
1972 } 2331 }
1973 } 2332 }
2333 else if (IsColliding && agent_control_v3.Z < 0f)
2334 agent_control_v3.Z = 0;
2335// else if(AgentControlStopActive %% Velocity.Z <0.01f)
2336
2337
2338// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
1974 2339
1975 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2340 // If the agent update does move the avatar, then calculate the force ready for the velocity update,
1976 // which occurs later in the main scene loop 2341 // which occurs later in the main scene loop
1977 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2342 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2343 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2344 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2345 // avatar location in place).
2346 if (update_movementflag
2347 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1978 { 2348 {
1979// m_log.DebugFormat(
1980// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
1981// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);
1982 2349
1983 AddNewMovement(agent_control_v3); 2350 if (AgentControlStopActive)
2351 {
2352 // if (MovementFlag == 0 && Animator.Falling)
2353 if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2354 {
2355 AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2356 }
2357 else
2358 AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2359 }
2360 else
2361 {
2362 AddNewMovement(agent_control_v3);
2363 }
2364
1984 } 2365 }
1985// else
1986// {
1987// if (!update_movementflag)
1988// {
1989// m_log.DebugFormat(
1990// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
1991// m_scene.RegionInfo.RegionName, agent_control_v3, Name);
1992// }
1993// }
1994 2366
1995 if (update_movementflag && ParentID == 0) 2367 if (update_movementflag && ParentID == 0)
2368 {
2369// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1996 Animator.UpdateMovementAnimations(); 2370 Animator.UpdateMovementAnimations();
2371 }
1997 2372
1998 SendControlsToScripts(flagsForScripts); 2373 SendControlsToScripts(flagsForScripts);
1999 } 2374 }
2000 2375
2376 // We need to send this back to the client in order to see the edit beams
2377 if ((State & (uint)AgentState.Editing) != 0)
2378 SendAgentTerseUpdate(this);
2379
2001 m_scene.EventManager.TriggerOnClientMovement(this); 2380 m_scene.EventManager.TriggerOnClientMovement(this);
2002 TriggerScenePresenceUpdated();
2003 } 2381 }
2004 2382
2383
2384 /// <summary>
2385 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2386 /// </summary>
2387 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2388 {
2389 //m_log.DebugFormat(
2390 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2391 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2392
2393 if (IsChildAgent)
2394 {
2395 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2396 return;
2397 }
2398
2399 ++m_movementUpdateCount;
2400 if (m_movementUpdateCount < 1)
2401 m_movementUpdateCount = 1;
2402
2403// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2404
2405 // Camera location in world. We'll need to raytrace
2406 // from this location from time to time.
2407 CameraPosition = agentData.CameraCenter;
2408 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2409 {
2410 ReprioritizeUpdates();
2411 m_lastCameraPosition = CameraPosition;
2412 }
2413
2414 // Use these three vectors to figure out what the agent is looking at
2415 // Convert it to a Matrix and/or Quaternion
2416 CameraAtAxis = agentData.CameraAtAxis;
2417 CameraLeftAxis = agentData.CameraLeftAxis;
2418 CameraUpAxis = agentData.CameraUpAxis;
2419
2420 // The Agent's Draw distance setting
2421 // When we get to the point of re-computing neighbors everytime this
2422 // changes, then start using the agent's drawdistance rather than the
2423 // region's draw distance.
2424 DrawDistance = Util.Clamp(agentData.Far, 32, m_scene.MaxDrawDistance);
2425
2426 // Check if Client has camera in 'follow cam' or 'build' mode.
2427 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2428
2429 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2430 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2431
2432
2433 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2434 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2435 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2436 {
2437 if (m_followCamAuto)
2438 {
2439 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2440 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2441 }
2442 }
2443
2444 TriggerScenePresenceUpdated();
2445 }
2446
2005 /// <summary> 2447 /// <summary>
2006 /// Calculate an update to move the presence to the set target. 2448 /// Calculate an update to move the presence to the set target.
2007 /// </summary> 2449 /// </summary>
@@ -2016,11 +2458,13 @@ namespace OpenSim.Region.Framework.Scenes
2016 2458
2017 bool updated = false; 2459 bool updated = false;
2018 2460
2461 Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition;
2462
2019// m_log.DebugFormat( 2463// m_log.DebugFormat(
2020// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 2464// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2021// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 2465// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2022 2466
2023 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 2467 double distanceToTarget = LocalVectorToTarget3D.Length();
2024 2468
2025// m_log.DebugFormat( 2469// m_log.DebugFormat(
2026// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 2470// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
@@ -2043,11 +2487,11 @@ namespace OpenSim.Region.Framework.Scenes
2043 // Theoretically we might need a more complex PID approach here if other 2487 // Theoretically we might need a more complex PID approach here if other
2044 // unknown forces are acting on the avatar and we need to adaptively respond 2488 // unknown forces are acting on the avatar and we need to adaptively respond
2045 // to such forces, but the following simple approach seems to works fine. 2489 // to such forces, but the following simple approach seems to works fine.
2046 Vector3 LocalVectorToTarget3D = 2490
2047 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 2491 LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords
2048 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
2049 // Ignore z component of vector 2492 // Ignore z component of vector
2050// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 2493// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
2494
2051 LocalVectorToTarget3D.Normalize(); 2495 LocalVectorToTarget3D.Normalize();
2052 2496
2053 // update avatar movement flags. the avatar coordinate system is as follows: 2497 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -2071,28 +2515,37 @@ namespace OpenSim.Region.Framework.Scenes
2071 2515
2072 // based on the above avatar coordinate system, classify the movement into 2516 // based on the above avatar coordinate system, classify the movement into
2073 // one of left/right/back/forward. 2517 // one of left/right/back/forward.
2518
2519 const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2520 Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2521 Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2522 Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2523
2524 MovementFlag &= noMovFlagsMask;
2525 AgentControlFlags &= noMovFlagsMask;
2526
2074 if (LocalVectorToTarget3D.X < 0) //MoveBack 2527 if (LocalVectorToTarget3D.X < 0) //MoveBack
2075 { 2528 {
2076 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2529 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2077 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2530 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2078 updated = true; 2531 updated = true;
2079 } 2532 }
2080 else if (LocalVectorToTarget3D.X > 0) //Move Forward 2533 else if (LocalVectorToTarget3D.X > 0) //Move Forward
2081 { 2534 {
2082 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2535 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2083 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2536 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2084 updated = true; 2537 updated = true;
2085 } 2538 }
2086 2539
2087 if (LocalVectorToTarget3D.Y > 0) //MoveLeft 2540 if (LocalVectorToTarget3D.Y > 0) //MoveLeft
2088 { 2541 {
2089 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2542 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2090 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2543 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2091 updated = true; 2544 updated = true;
2092 } 2545 }
2093 else if (LocalVectorToTarget3D.Y < 0) //MoveRight 2546 else if (LocalVectorToTarget3D.Y < 0) //MoveRight
2094 { 2547 {
2095 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2548 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2096 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2549 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2097 updated = true; 2550 updated = true;
2098 } 2551 }
@@ -2187,6 +2640,8 @@ namespace OpenSim.Region.Framework.Scenes
2187 targetScene = m_scene; 2640 targetScene = m_scene;
2188 2641
2189 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2642 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
2643 // dont try to land underground
2644 terrainHeight += Appearance.AvatarHeight / 2;
2190 pos.Z = Math.Max(terrainHeight, pos.Z); 2645 pos.Z = Math.Max(terrainHeight, pos.Z);
2191 2646
2192 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2647 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2198,10 +2653,11 @@ namespace OpenSim.Region.Framework.Scenes
2198// m_log.DebugFormat( 2653// m_log.DebugFormat(
2199// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2654// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2200// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2655// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2656
2201 2657
2202 if (noFly) 2658 if (noFly)
2203 Flying = false; 2659 Flying = false;
2204 else if (pos.Z > terrainHeight) 2660 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2205 Flying = true; 2661 Flying = true;
2206 2662
2207 LandAtTarget = landAtTarget; 2663 LandAtTarget = landAtTarget;
@@ -2254,17 +2710,13 @@ namespace OpenSim.Region.Framework.Scenes
2254 { 2710 {
2255// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2711// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2256 2712
2713 bool satOnObject = IsSatOnObject;
2714 SceneObjectPart part = ParentPart;
2257 SitGround = false; 2715 SitGround = false;
2258 2716
2259/* move this down so avatar gets physical in the new position and not where it is siting 2717 if (satOnObject)
2260 if (PhysicsActor == null)
2261 AddToPhysicalScene(false);
2262 */
2263
2264 if (ParentID != 0)
2265 { 2718 {
2266 PrevSitOffset = m_pos; // Save sit offset 2719 PrevSitOffset = m_pos; // Save sit offset
2267 SceneObjectPart part = ParentPart;
2268 UnRegisterSeatControls(part.ParentGroup.UUID); 2720 UnRegisterSeatControls(part.ParentGroup.UUID);
2269 2721
2270 TaskInventoryDictionary taskIDict = part.TaskInventory; 2722 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2283,34 +2735,64 @@ namespace OpenSim.Region.Framework.Scenes
2283 } 2735 }
2284 2736
2285 part.ParentGroup.DeleteAvatar(UUID); 2737 part.ParentGroup.DeleteAvatar(UUID);
2286// ParentPosition = part.GetWorldPosition();
2287 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2288 2738
2289// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2739 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2290// ParentPosition = Vector3.Zero; 2740 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2291 m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2741 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2292 if (part.SitTargetAvatar == UUID)
2293 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2294 2742
2295 ParentID = 0; 2743 ParentID = 0;
2296 ParentPart = null; 2744 ParentPart = null;
2297 2745
2298 if (PhysicsActor == null) 2746 if (part.SitTargetAvatar == UUID)
2299 AddToPhysicalScene(false); 2747 standRotation = standRotation * part.SitTargetOrientation;
2748 else
2749 standRotation = standRotation * m_bodyRot;
2300 2750
2301 SendAvatarDataToAllAgents(); 2751 m_bodyRot = standRotation;
2302 m_requestedSitTargetID = 0;
2303 2752
2304 part.RemoveSittingAvatar(UUID); 2753 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2305 2754
2306 if (part != null) 2755 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2307 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2756 if (t > 0)
2757 {
2758 t = 1.0f / (float)Math.Sqrt(t);
2759 standRotationZ.W *= t;
2760 standRotationZ.Z *= t;
2761 }
2762 else
2763 {
2764 standRotationZ.W = 1.0f;
2765 standRotationZ.Z = 0f;
2766 }
2767
2768 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2769
2770 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2771
2772 m_pos = standPos;
2308 } 2773 }
2309 2774
2310 else if (PhysicsActor == null) 2775 // We need to wait until we have calculated proper stand positions before sitting up the physical
2776 // avatar to avoid race conditions.
2777 if (PhysicsActor == null)
2311 AddToPhysicalScene(false); 2778 AddToPhysicalScene(false);
2312 2779
2313 Animator.TrySetMovementAnimation("STAND"); 2780 if (satOnObject)
2781 {
2782 m_requestedSitTargetID = 0;
2783 part.RemoveSittingAvatar(UUID);
2784 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2785
2786 SendAvatarDataToAllAgents();
2787 }
2788
2789 // reset to default sitAnimation
2790 sitAnimation = "SIT";
2791
2792// Animator.TrySetMovementAnimation("STAND");
2793 Animator.SetMovementAnimations("STAND");
2794
2795 TriggerScenePresenceUpdated();
2314 } 2796 }
2315 2797
2316 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2798 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2357,20 +2839,17 @@ namespace OpenSim.Region.Framework.Scenes
2357 if (part == null) 2839 if (part == null)
2358 return; 2840 return;
2359 2841
2842
2360 if (PhysicsActor != null) 2843 if (PhysicsActor != null)
2361 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2844 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2362 2845
2363 bool canSit = false; 2846 bool canSit = false;
2364 Vector3 pos = part.AbsolutePosition + offset;
2365 2847
2366 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2848 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2367 { 2849 {
2368// m_log.DebugFormat(
2369// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2370// Name, part.Name, part.LocalId);
2371
2372 offset = part.SitTargetPosition; 2850 offset = part.SitTargetPosition;
2373 sitOrientation = part.SitTargetOrientation; 2851 sitOrientation = part.SitTargetOrientation;
2852
2374 canSit = true; 2853 canSit = true;
2375 } 2854 }
2376 else 2855 else
@@ -2378,9 +2857,10 @@ namespace OpenSim.Region.Framework.Scenes
2378 if (PhysicsSit(part,offset)) // physics engine 2857 if (PhysicsSit(part,offset)) // physics engine
2379 return; 2858 return;
2380 2859
2860 Vector3 pos = part.AbsolutePosition + offset;
2861
2381 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2862 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2382 { 2863 {
2383
2384 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2864 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2385 canSit = true; 2865 canSit = true;
2386 } 2866 }
@@ -2406,10 +2886,31 @@ namespace OpenSim.Region.Framework.Scenes
2406 cameraEyeOffset = part.GetCameraEyeOffset(); 2886 cameraEyeOffset = part.GetCameraEyeOffset();
2407 forceMouselook = part.GetForceMouselook(); 2887 forceMouselook = part.GetForceMouselook();
2408 2888
2889 if (!part.IsRoot)
2890 {
2891 sitOrientation = part.RotationOffset * sitOrientation;
2892 offset = offset * part.RotationOffset;
2893 offset += part.OffsetPosition;
2894
2895 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2896 {
2897 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
2898 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2899 }
2900 else
2901 {
2902 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2903 cameraAtOffset += part.OffsetPosition;
2904 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
2905 cameraEyeOffset += part.OffsetPosition;
2906 }
2907 }
2908
2909
2409 ControllingClient.SendSitResponse( 2910 ControllingClient.SendSitResponse(
2410 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2911 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2411 2912
2412 m_requestedSitTargetUUID = targetID; 2913 m_requestedSitTargetUUID = part.UUID;
2413 2914
2414 HandleAgentSit(ControllingClient, UUID); 2915 HandleAgentSit(ControllingClient, UUID);
2415 2916
@@ -2437,7 +2938,7 @@ namespace OpenSim.Region.Framework.Scenes
2437 if (part != null) 2938 if (part != null)
2438 { 2939 {
2439 m_requestedSitTargetID = part.LocalId; 2940 m_requestedSitTargetID = part.LocalId;
2440 m_requestedSitTargetUUID = targetID; 2941 m_requestedSitTargetUUID = part.UUID;
2441 2942
2442 } 2943 }
2443 else 2944 else
@@ -2524,6 +3025,7 @@ namespace OpenSim.Region.Framework.Scenes
2524 ResetMoveToTarget(); 3025 ResetMoveToTarget();
2525 3026
2526 Velocity = Vector3.Zero; 3027 Velocity = Vector3.Zero;
3028 m_AngularVelocity = Vector3.Zero;
2527 3029
2528 part.AddSittingAvatar(UUID); 3030 part.AddSittingAvatar(UUID);
2529 3031
@@ -2531,24 +3033,55 @@ namespace OpenSim.Region.Framework.Scenes
2531 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3033 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2532 bool forceMouselook = part.GetForceMouselook(); 3034 bool forceMouselook = part.GetForceMouselook();
2533 3035
2534 ControllingClient.SendSitResponse( 3036 m_bodyRot = Orientation;
2535 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2536 3037
2537 // not using autopilot 3038 if (!part.IsRoot)
3039 {
3040 Orientation = part.RotationOffset * Orientation;
3041 offset = offset * part.RotationOffset;
3042 offset += part.OffsetPosition;
3043
3044 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3045 {
3046 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3047 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3048 }
3049 else
3050 {
3051 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3052 cameraAtOffset += part.OffsetPosition;
3053 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3054 cameraEyeOffset += part.OffsetPosition;
3055 }
3056
3057 }
2538 3058
2539 Rotation = Orientation;
2540 m_pos = offset; 3059 m_pos = offset;
2541 3060
3061 ControllingClient.SendSitResponse(
3062 part.ParentGroup.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
3063
3064
2542 m_requestedSitTargetID = 0; 3065 m_requestedSitTargetID = 0;
2543 part.ParentGroup.AddAvatar(UUID); 3066 part.ParentGroup.AddAvatar(UUID);
2544 3067
2545 ParentPart = part; 3068 ParentPart = part;
2546 ParentID = part.LocalId; 3069 ParentID = part.LocalId;
3070
3071 SendAvatarDataToAllAgents();
3072
3073/*
2547 if(status == 3) 3074 if(status == 3)
2548 Animator.TrySetMovementAnimation("SIT_GROUND"); 3075 Animator.TrySetMovementAnimation("SIT_GROUND");
2549 else 3076 else
2550 Animator.TrySetMovementAnimation("SIT"); 3077 Animator.TrySetMovementAnimation("SIT");
2551 SendAvatarDataToAllAgents(); 3078*/
3079 if (status == 3)
3080 sitAnimation = "SIT_GROUND";
3081 else
3082 sitAnimation = "SIT";
3083
3084 Animator.SetMovementAnimations("SIT");
2552 3085
2553 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3086 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2554 } 3087 }
@@ -2556,6 +3089,9 @@ namespace OpenSim.Region.Framework.Scenes
2556 3089
2557 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 3090 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2558 { 3091 {
3092 if (IsChildAgent)
3093 return;
3094
2559 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3095 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2560 3096
2561 if (part != null) 3097 if (part != null)
@@ -2605,47 +3141,74 @@ namespace OpenSim.Region.Framework.Scenes
2605 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3141 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2606 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 3142 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2607 3143
2608 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 3144 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3145 Quaternion newRot;
3146
3147 if (part.IsRoot)
3148 {
3149 newRot = sitTargetOrient;
3150 }
3151 else
3152 {
3153 newPos = newPos * part.RotationOffset;
3154 newRot = part.RotationOffset * sitTargetOrient;
3155 }
3156
3157 newPos += part.OffsetPosition;
3158
3159 m_pos = newPos;
3160 Rotation = newRot;
2609 3161
2610// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2611 Rotation = sitTargetOrient;
2612// ParentPosition = part.AbsolutePosition; 3162// ParentPosition = part.AbsolutePosition;
2613 part.ParentGroup.AddAvatar(UUID);
2614 } 3163 }
2615 else 3164 else
2616 { 3165 {
2617 m_pos -= part.AbsolutePosition; 3166 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
3167 // being sat upon.
3168 m_pos -= part.GroupPosition;
3169
2618// ParentPosition = part.AbsolutePosition; 3170// ParentPosition = part.AbsolutePosition;
2619 part.ParentGroup.AddAvatar(UUID);
2620 3171
2621// m_log.DebugFormat( 3172// m_log.DebugFormat(
2622// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 3173// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2623// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3174// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2624 } 3175 }
2625 3176
3177 part.ParentGroup.AddAvatar(UUID);
2626 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3178 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2627 ParentID = m_requestedSitTargetID; 3179 ParentID = m_requestedSitTargetID;
2628 m_AngularVelocity = Vector3.Zero; 3180 m_AngularVelocity = Vector3.Zero;
2629 Velocity = Vector3.Zero; 3181 Velocity = Vector3.Zero;
2630 RemoveFromPhysicalScene(); 3182 RemoveFromPhysicalScene();
2631 3183
2632 String sitAnimation = "SIT"; 3184 SendAvatarDataToAllAgents();
3185
3186 sitAnimation = "SIT";
2633 if (!String.IsNullOrEmpty(part.SitAnimation)) 3187 if (!String.IsNullOrEmpty(part.SitAnimation))
2634 { 3188 {
2635 sitAnimation = part.SitAnimation; 3189 sitAnimation = part.SitAnimation;
2636 } 3190 }
2637 Animator.TrySetMovementAnimation(sitAnimation); 3191// Animator.TrySetMovementAnimation(sitAnimation);
2638 SendAvatarDataToAllAgents(); 3192 Animator.SetMovementAnimations("SIT");
3193 TriggerScenePresenceUpdated();
2639 } 3194 }
2640 } 3195 }
2641 3196
2642 public void HandleAgentSitOnGround() 3197 public void HandleAgentSitOnGround()
2643 { 3198 {
3199 if (IsChildAgent)
3200 return;
3201
2644// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3202// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2645 m_AngularVelocity = Vector3.Zero; 3203 m_AngularVelocity = Vector3.Zero;
2646 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3204 sitAnimation = "SIT_GROUND_CONSTRAINED";
3205// Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3206// TriggerScenePresenceUpdated();
2647 SitGround = true; 3207 SitGround = true;
2648 RemoveFromPhysicalScene(); 3208 RemoveFromPhysicalScene();
3209
3210 Animator.SetMovementAnimations("SITGROUND");
3211 TriggerScenePresenceUpdated();
2649 } 3212 }
2650 3213
2651 /// <summary> 3214 /// <summary>
@@ -2660,11 +3223,13 @@ namespace OpenSim.Region.Framework.Scenes
2660 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 3223 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2661 { 3224 {
2662 Animator.AddAnimation(animID, UUID.Zero); 3225 Animator.AddAnimation(animID, UUID.Zero);
3226 TriggerScenePresenceUpdated();
2663 } 3227 }
2664 3228
2665 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 3229 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2666 { 3230 {
2667 Animator.RemoveAnimation(animID, false); 3231 Animator.RemoveAnimation(animID, false);
3232 TriggerScenePresenceUpdated();
2668 } 3233 }
2669 3234
2670 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 3235 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2678,67 +3243,57 @@ namespace OpenSim.Region.Framework.Scenes
2678 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3243 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2679 /// </summary> 3244 /// </summary>
2680 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3245 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2681 public void AddNewMovement(Vector3 vec) 3246 /// <param name="thisAddSpeedModifier">
3247 /// Optional additional speed modifier for this particular add. Default is 1</param>
3248 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
2682 { 3249 {
2683// m_log.DebugFormat( 3250 // m_log.DebugFormat(
2684// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3251 // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3252 // vec, Rotation, thisAddSpeedModifier, Name);
2685 3253
3254 // rotate from avatar coord space to world
3255 // for now all controls assume this is only a rotation around Z
3256 // if not all checks below need to be done before this rotation
2686 Vector3 direc = vec * Rotation; 3257 Vector3 direc = vec * Rotation;
2687 direc.Normalize(); 3258 direc.Normalize();
2688 3259
2689 if (Flying != FlyingOld) // add for fly velocity control 3260 // mouse look situation ?
2690 {
2691 FlyingOld = Flying; // add for fly velocity control
2692 if (!Flying)
2693 WasFlying = true; // add for fly velocity control
2694 }
2695
2696 if (IsColliding)
2697 WasFlying = false; // add for fly velocity control
2698
2699 if ((vec.Z == 0f) && !Flying) 3261 if ((vec.Z == 0f) && !Flying)
2700 direc.Z = 0f; // Prevent camera WASD up. 3262 direc.Z = 0f; // Prevent camera WASD up.
2701 3263
2702 direc *= 0.03f * 128f * SpeedModifier; 3264 // odd rescalings
3265 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2703 3266
2704// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3267 // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2705 3268
2706 if (PhysicsActor != null) 3269 if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2707 { 3270 {
2708 if (Flying) 3271 if (breaking)
2709 { 3272 direc.Z = -9999f; //hack to tell physics to stop on Z
3273 else
3274 direc = Vector3.Zero;
3275 }
3276 else if (Flying)
3277 {
3278 if (IsColliding && direc.Z < 0)
3279 // landing situation, prevent avatar moving or it may fail to land
3280 // animator will handle this condition and do the land
3281 direc = Vector3.Zero;
3282 else
2710 direc *= 4.0f; 3283 direc *= 4.0f;
2711 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 3284 }
2712 //if (controlland) 3285 else if (IsColliding)
2713 // m_log.Info("[AGENT]: landCommand"); 3286 {
2714 //if (IsColliding) 3287 if (direc.Z > 2.0f) // reinforce jumps
2715 // m_log.Info("[AGENT]: colliding");
2716 //if (Flying && IsColliding && controlland)
2717 //{
2718 // StopFlying();
2719 // m_log.Info("[AGENT]: Stop Flying");
2720 //}
2721 }
2722 if (Animator.Falling && WasFlying) // if falling from flying, disable motion add
2723 {
2724 direc *= 0.0f;
2725 }
2726 else if (!Flying && IsColliding)
2727 { 3288 {
2728 if (direc.Z > 2.0f) 3289 direc.Z *= 2.6f;
2729 {
2730 direc.Z *= 2.6f;
2731
2732 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2733// Animator.TrySetMovementAnimation("PREJUMP");
2734// Animator.TrySetMovementAnimation("JUMP");
2735 }
2736 } 3290 }
3291 else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3292 direc.Z = 0;
2737 } 3293 }
2738 3294
2739// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); 3295 // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
2740 3296
2741 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2742 m_forceToApply = direc; 3297 m_forceToApply = direc;
2743 Animator.UpdateMovementAnimations(); 3298 Animator.UpdateMovementAnimations();
2744 } 3299 }
@@ -2755,6 +3310,11 @@ namespace OpenSim.Region.Framework.Scenes
2755 3310
2756 if (IsChildAgent == false) 3311 if (IsChildAgent == false)
2757 { 3312 {
3313 CheckForBorderCrossing();
3314
3315 if (IsInTransit)
3316 return;
3317
2758 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3318 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
2759 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3319 // grab the latest PhysicsActor velocity, whereas m_velocity is often
2760 // storing a requested force instead of an actual traveling velocity 3320 // storing a requested force instead of an actual traveling velocity
@@ -2773,8 +3333,6 @@ namespace OpenSim.Region.Framework.Scenes
2773 m_lastVelocity = Velocity; 3333 m_lastVelocity = Velocity;
2774 } 3334 }
2775 3335
2776 CheckForBorderCrossing();
2777
2778 CheckForSignificantMovement(); // sends update to the modules. 3336 CheckForSignificantMovement(); // sends update to the modules.
2779 } 3337 }
2780 } 3338 }
@@ -2783,9 +3341,38 @@ namespace OpenSim.Region.Framework.Scenes
2783 3341
2784 #region Update Client(s) 3342 #region Update Client(s)
2785 3343
3344 public void SendUpdateToAgent(ScenePresence p)
3345 {
3346 IClientAPI remoteClient = p.ControllingClient;
3347
3348 if (remoteClient.IsActive)
3349 {
3350 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3351 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3352 m_scene.StatsReporter.AddAgentUpdates(1);
3353 }
3354 }
3355
3356 public void SendFullUpdateToClient(IClientAPI remoteClient)
3357 {
3358 if (remoteClient.IsActive)
3359 {
3360 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3361 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3362 m_scene.StatsReporter.AddAgentUpdates(1);
3363 }
3364 }
3365
3366 // this is diferente from SendTerseUpdateToClient
3367 // this sends bypassing entities updates
3368 public void SendAgentTerseUpdate(ISceneEntity p)
3369 {
3370 ControllingClient.SendAgentTerseUpdate(p);
3371 }
2786 3372
2787 /// <summary> 3373 /// <summary>
2788 /// Sends a location update to the client connected to this scenePresence 3374 /// Sends a location update to the client connected to this scenePresence
3375 /// via entity updates
2789 /// </summary> 3376 /// </summary>
2790 /// <param name="remoteClient"></param> 3377 /// <param name="remoteClient"></param>
2791 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3378 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -2795,7 +3382,6 @@ namespace OpenSim.Region.Framework.Scenes
2795 if (remoteClient.IsActive) 3382 if (remoteClient.IsActive)
2796 { 3383 {
2797 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3384 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
2798
2799 remoteClient.SendEntityUpdate( 3385 remoteClient.SendEntityUpdate(
2800 this, 3386 this,
2801 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3387 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -2805,6 +3391,38 @@ namespace OpenSim.Region.Framework.Scenes
2805 } 3391 }
2806 } 3392 }
2807 3393
3394 public void SendTerseUpdateToAgent(ScenePresence p)
3395 {
3396 IClientAPI remoteClient = p.ControllingClient;
3397
3398 if (!remoteClient.IsActive)
3399 return;
3400
3401 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3402 return;
3403
3404 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3405 remoteClient.SendEntityUpdate(
3406 this,
3407 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3408 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3409
3410 m_scene.StatsReporter.AddAgentUpdates(1);
3411 }
3412
3413 public void SendTerseUpdateToAgentNF(ScenePresence p)
3414 {
3415 IClientAPI remoteClient = p.ControllingClient;
3416 if (remoteClient.IsActive)
3417 {
3418 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3419 remoteClient.SendEntityUpdate(this,
3420 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3421 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3422 m_scene.StatsReporter.AddAgentUpdates(1);
3423 }
3424 }
3425
2808 3426
2809 // vars to support reduced update frequency when velocity is unchanged 3427 // vars to support reduced update frequency when velocity is unchanged
2810 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3428 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -2845,7 +3463,9 @@ namespace OpenSim.Region.Framework.Scenes
2845 lastTerseUpdateToAllClientsTick = currentTick; 3463 lastTerseUpdateToAllClientsTick = currentTick;
2846 lastPositionSentToAllClients = OffsetPosition; 3464 lastPositionSentToAllClients = OffsetPosition;
2847 3465
2848 m_scene.ForEachClient(SendTerseUpdateToClient); 3466// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3467// m_scene.ForEachClient(SendTerseUpdateToClient);
3468 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
2849 } 3469 }
2850 TriggerScenePresenceUpdated(); 3470 TriggerScenePresenceUpdated();
2851 } 3471 }
@@ -2878,13 +3498,20 @@ namespace OpenSim.Region.Framework.Scenes
2878 // we created a new ScenePresence (a new child agent) in a fresh region. 3498 // we created a new ScenePresence (a new child agent) in a fresh region.
2879 // Request info about all the (root) agents in this region 3499 // Request info about all the (root) agents in this region
2880 // Note: This won't send data *to* other clients in that region (children don't send) 3500 // Note: This won't send data *to* other clients in that region (children don't send)
2881 SendOtherAgentsAvatarDataToMe(); 3501 if (m_teleportFlags <= 0)
2882 SendOtherAgentsAppearanceToMe(); 3502 {
3503 ILandChannel landch = m_scene.LandChannel;
3504 if (landch != null)
3505 {
3506 landch.sendClientInitialLandInfo(ControllingClient);
3507 }
3508 }
2883 3509
3510 SendOtherAgentsAvatarFullToMe();
2884 EntityBase[] entities = Scene.Entities.GetEntities(); 3511 EntityBase[] entities = Scene.Entities.GetEntities();
2885 foreach(EntityBase e in entities) 3512 foreach (EntityBase e in entities)
2886 { 3513 {
2887 if (e != null && e is SceneObjectGroup) 3514 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
2888 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3515 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2889 } 3516 }
2890 }); 3517 });
@@ -2894,6 +3521,8 @@ namespace OpenSim.Region.Framework.Scenes
2894 /// Do everything required once a client completes its movement into a region and becomes 3521 /// Do everything required once a client completes its movement into a region and becomes
2895 /// a root agent. 3522 /// a root agent.
2896 /// </summary> 3523 /// </summary>
3524 ///
3525/* only called from on place, do done inline there
2897 private void ValidateAndSendAppearanceAndAgentData() 3526 private void ValidateAndSendAppearanceAndAgentData()
2898 { 3527 {
2899 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); 3528 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
@@ -2907,32 +3536,63 @@ namespace OpenSim.Region.Framework.Scenes
2907 // to see if all the baked textures are already here. 3536 // to see if all the baked textures are already here.
2908 if (m_scene.AvatarFactory != null) 3537 if (m_scene.AvatarFactory != null)
2909 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); 3538 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
2910 3539
2911 // If we aren't using a cached appearance, then clear out the baked textures 3540 // If we aren't using a cached appearance, then clear out the baked textures
2912 if (!cachedappearance) 3541 if (!cachedappearance)
2913 { 3542 {
2914 Appearance.ResetAppearance();
2915 if (m_scene.AvatarFactory != null) 3543 if (m_scene.AvatarFactory != null)
2916 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3544 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
2917 } 3545 }
2918 3546
2919 // This agent just became root. We are going to tell everyone about it. The process of 3547 // send avatar object to all viewers so they cross it into region
2920 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it 3548 bool newhide = m_currentParcelHide;
2921 // again here... this comes after the cached appearance check because the avatars 3549 m_currentParcelHide = false;
2922 // appearance goes into the avatar update packet 3550
2923 SendAvatarDataToAllAgents(); 3551 SendAvatarDataToAllAgents();
3552
3553 // now hide
3554 if (newhide)
3555 {
3556 ParcelLoginCheck(m_currentParcelUUID);
3557 m_currentParcelHide = true;
3558 }
3559
2924 SendAppearanceToAgent(this); 3560 SendAppearanceToAgent(this);
2925 3561
2926 // If we are using the the cached appearance then send it out to everyone 3562 m_inTransit = false;
2927 if (cachedappearance) 3563
3564 SendAppearanceToAllOtherAgents();
3565
3566 if(Animator!= null)
3567 Animator.SendAnimPack();
3568 }
3569*/
3570 /// <summary>
3571 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3572 /// can be either a child or root
3573 /// </summary>
3574 public void SendOtherAgentsAvatarFullToMe()
3575 {
3576 int count = 0;
3577 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
2928 { 3578 {
2929 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3579 // only send information about other root agents
3580 if (p.UUID == UUID)
3581 return;
2930 3582
2931 // If the avatars baked textures are all in the cache, then we have a 3583 // get the avatar, then a kill if can't see it
2932 // complete appearance... send it out, if not, then we'll send it when 3584 p.SendInitialAvatarDataToAgent(this);
2933 // the avatar finishes updating its appearance 3585
2934 SendAppearanceToAllOtherAgents(); 3586 if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200)
2935 } 3587 return;
3588
3589 p.SendAppearanceToAgentNF(this);
3590 p.SendAnimPackToAgentNF(this);
3591 p.SendAttachmentsToAgentNF(this);
3592 count++;
3593 });
3594
3595 m_scene.StatsReporter.AddAgentUpdates(count);
2936 } 3596 }
2937 3597
2938 /// <summary> 3598 /// <summary>
@@ -2948,42 +3608,51 @@ namespace OpenSim.Region.Framework.Scenes
2948 m_log.WarnFormat( 3608 m_log.WarnFormat(
2949 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", 3609 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
2950 Name, Scene.RegionInfo.RegionName); 3610 Name, Scene.RegionInfo.RegionName);
2951
2952 return; 3611 return;
2953 } 3612 }
2954 3613
2955 m_lastSize = Appearance.AvatarSize; 3614 m_lastSize = Appearance.AvatarSize;
2956
2957 int count = 0; 3615 int count = 0;
3616
2958 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3617 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2959 { 3618 {
2960 SendAvatarDataToAgent(scenePresence); 3619 SendAvatarDataToAgent(scenePresence);
2961 count++; 3620 count++;
2962 }); 3621 });
2963 3622
2964 m_scene.StatsReporter.AddAgentUpdates(count); 3623 m_scene.StatsReporter.AddAgentUpdates(count);
2965 } 3624 }
2966 3625
2967 /// <summary> 3626 // sends avatar object to all clients so they cross it into region
2968 /// Send avatar data for all other root agents to this agent, this agent 3627 // then sends kills to hide
2969 /// can be either a child or root 3628 public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
2970 /// </summary>
2971 public void SendOtherAgentsAvatarDataToMe()
2972 { 3629 {
3630 m_lastSize = Appearance.AvatarSize;
2973 int count = 0; 3631 int count = 0;
2974 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
2975 {
2976 // only send information about other root agents
2977 if (scenePresence.UUID == UUID)
2978 return;
2979
2980 scenePresence.SendAvatarDataToAgent(this);
2981 count++;
2982 });
2983 3632
3633 foreach (ScenePresence p in presences)
3634 {
3635 p.ControllingClient.SendAvatarDataImmediate(this);
3636 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3637 // either just kill the object
3638 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3639 // or also attachments viewer may still know about
3640 SendKillTo(p);
3641 count++;
3642 }
2984 m_scene.StatsReporter.AddAgentUpdates(count); 3643 m_scene.StatsReporter.AddAgentUpdates(count);
2985 } 3644 }
2986 3645
3646 public void SendInitialAvatarDataToAgent(ScenePresence p)
3647 {
3648 p.ControllingClient.SendAvatarDataImmediate(this);
3649 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3650 // either just kill the object
3651 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3652 // or also attachments viewer may still know about
3653 SendKillTo(p);
3654 }
3655
2987 /// <summary> 3656 /// <summary>
2988 /// Send avatar data to an agent. 3657 /// Send avatar data to an agent.
2989 /// </summary> 3658 /// </summary>
@@ -2991,18 +3660,23 @@ namespace OpenSim.Region.Framework.Scenes
2991 public void SendAvatarDataToAgent(ScenePresence avatar) 3660 public void SendAvatarDataToAgent(ScenePresence avatar)
2992 { 3661 {
2993 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3662 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2994 3663 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3664 return;
2995 avatar.ControllingClient.SendAvatarDataImmediate(this); 3665 avatar.ControllingClient.SendAvatarDataImmediate(this);
2996 Animator.SendAnimPackToClient(avatar.ControllingClient);
2997 } 3666 }
2998 3667
3668 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3669 {
3670 avatar.ControllingClient.SendAvatarDataImmediate(this);
3671 }
3672
2999 /// <summary> 3673 /// <summary>
3000 /// Send this agent's appearance to all other root and child agents in the scene 3674 /// Send this agent's appearance to all other root and child agents in the scene
3001 /// This agent must be root. 3675 /// This agent must be root.
3002 /// </summary> 3676 /// </summary>
3003 public void SendAppearanceToAllOtherAgents() 3677 public void SendAppearanceToAllOtherAgents()
3004 { 3678 {
3005// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); 3679 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3006 3680
3007 // only send update from root agents to other clients; children are only "listening posts" 3681 // only send update from root agents to other clients; children are only "listening posts"
3008 if (IsChildAgent) 3682 if (IsChildAgent)
@@ -3013,7 +3687,7 @@ namespace OpenSim.Region.Framework.Scenes
3013 3687
3014 return; 3688 return;
3015 } 3689 }
3016 3690
3017 int count = 0; 3691 int count = 0;
3018 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3692 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3019 { 3693 {
@@ -3024,29 +3698,6 @@ namespace OpenSim.Region.Framework.Scenes
3024 SendAppearanceToAgent(scenePresence); 3698 SendAppearanceToAgent(scenePresence);
3025 count++; 3699 count++;
3026 }); 3700 });
3027
3028 m_scene.StatsReporter.AddAgentUpdates(count);
3029 }
3030
3031 /// <summary>
3032 /// Send appearance from all other root agents to this agent. this agent
3033 /// can be either root or child
3034 /// </summary>
3035 public void SendOtherAgentsAppearanceToMe()
3036 {
3037// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID);
3038
3039 int count = 0;
3040 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
3041 {
3042 // only send information about other root agents
3043 if (scenePresence.UUID == UUID)
3044 return;
3045
3046 scenePresence.SendAppearanceToAgent(this);
3047 count++;
3048 });
3049
3050 m_scene.StatsReporter.AddAgentUpdates(count); 3701 m_scene.StatsReporter.AddAgentUpdates(count);
3051 } 3702 }
3052 3703
@@ -3058,11 +3709,66 @@ namespace OpenSim.Region.Framework.Scenes
3058 { 3709 {
3059// m_log.DebugFormat( 3710// m_log.DebugFormat(
3060// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3711// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3712 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3713 return;
3714 SendAppearanceToAgentNF(avatar);
3715 }
3061 3716
3062 avatar.ControllingClient.SendAppearance( 3717 public void SendAppearanceToAgentNF(ScenePresence avatar)
3063 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3718 {
3719 if (Invisible)
3720 avatar.ControllingClient.SendAppearance(
3721 UUID, Appearance.VisualParams, AvatarAppearance.Invisible.GetBytes());
3722 else
3723 avatar.ControllingClient.SendAppearance(
3724 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3725 }
3064 3726
3065 3727 public void SendAnimPackToAgent(ScenePresence p)
3728 {
3729 if (IsChildAgent || Animator == null)
3730 return;
3731
3732 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3733 return;
3734
3735 Animator.SendAnimPackToClient(p.ControllingClient);
3736 }
3737
3738 public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3739 {
3740 if (IsChildAgent)
3741 return;
3742
3743 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3744 return;
3745
3746 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3747 }
3748
3749 public void SendAnimPackToAgentNF(ScenePresence p)
3750 {
3751 if (IsChildAgent || Animator == null)
3752 return;
3753 Animator.SendAnimPackToClient(p.ControllingClient);
3754 }
3755
3756 public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3757 {
3758 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3759 }
3760
3761 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3762 {
3763 if (IsChildAgent)
3764 return;
3765
3766 m_scene.ForEachScenePresence(delegate(ScenePresence p)
3767 {
3768 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3769 return;
3770 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3771 });
3066 } 3772 }
3067 3773
3068 #endregion 3774 #endregion
@@ -3081,12 +3787,12 @@ namespace OpenSim.Region.Framework.Scenes
3081 } 3787 }
3082 3788
3083 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3789 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3084 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3790 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3085 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3086 { 3791 {
3087 m_lastChildAgentUpdatePosition = AbsolutePosition; 3792 m_lastChildAgentUpdatePosition = AbsolutePosition;
3088 m_lastChildAgentUpdateCamPosition = CameraPosition; 3793// m_lastChildAgentUpdateCamPosition = CameraPosition;
3089 3794
3795/* cadu is not used
3090 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3796 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3091 cadu.ActiveGroupID = UUID.Zero.Guid; 3797 cadu.ActiveGroupID = UUID.Zero.Guid;
3092 cadu.AgentID = UUID.Guid; 3798 cadu.AgentID = UUID.Guid;
@@ -3100,6 +3806,7 @@ namespace OpenSim.Region.Framework.Scenes
3100 3806
3101 // Throttles 3807 // Throttles
3102 float multiplier = 1; 3808 float multiplier = 1;
3809
3103 int childRegions = KnownRegionCount; 3810 int childRegions = KnownRegionCount;
3104 if (childRegions != 0) 3811 if (childRegions != 0)
3105 multiplier = 1f / childRegions; 3812 multiplier = 1f / childRegions;
@@ -3110,9 +3817,22 @@ namespace OpenSim.Region.Framework.Scenes
3110 3817
3111 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); 3818 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
3112 cadu.Velocity = Velocity; 3819 cadu.Velocity = Velocity;
3113 3820*/
3114 AgentPosition agentpos = new AgentPosition(); 3821 AgentPosition agentpos = new AgentPosition();
3115 agentpos.CopyFrom(cadu); 3822// agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3823
3824 agentpos.AgentID = new UUID(UUID.Guid);
3825 agentpos.SessionID = ControllingClient.SessionId;
3826
3827 agentpos.Size = Appearance.AvatarSize;
3828
3829 agentpos.Center = CameraPosition;
3830 agentpos.Far = DrawDistance;
3831 agentpos.Position = AbsolutePosition;
3832 agentpos.Velocity = Velocity;
3833 agentpos.RegionHandle = RegionHandle;
3834 agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
3835
3116 3836
3117 // Let's get this out of the update loop 3837 // Let's get this out of the update loop
3118 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3838 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3132,7 +3852,7 @@ namespace OpenSim.Region.Framework.Scenes
3132 protected void CheckForBorderCrossing() 3852 protected void CheckForBorderCrossing()
3133 { 3853 {
3134 // Check that we we are not a child 3854 // Check that we we are not a child
3135 if (IsChildAgent) 3855 if (IsChildAgent || IsInTransit)
3136 return; 3856 return;
3137 3857
3138 // If we don't have a PhysActor, we can't cross anyway 3858 // If we don't have a PhysActor, we can't cross anyway
@@ -3142,140 +3862,72 @@ namespace OpenSim.Region.Framework.Scenes
3142 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3862 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3143 return; 3863 return;
3144 3864
3145 if (!IsInTransit) 3865 Vector3 pos2 = AbsolutePosition;
3146 { 3866 Vector3 vel = Velocity;
3147 Vector3 pos2 = AbsolutePosition;
3148 Vector3 vel = Velocity;
3149 int neighbor = 0;
3150 int[] fix = new int[2];
3151 3867
3152 float timeStep = 0.1f; 3868 float timeStep = 0.1f;
3153 pos2.X = pos2.X + (vel.X * timeStep); 3869 pos2.X += vel.X * timeStep;
3154 pos2.Y = pos2.Y + (vel.Y * timeStep); 3870 pos2.Y += vel.Y * timeStep;
3155 pos2.Z = pos2.Z + (vel.Z * timeStep); 3871 pos2.Z += vel.Z * timeStep;
3156 3872
3157 if (!IsInTransit)
3158 {
3159// m_log.DebugFormat( 3873// m_log.DebugFormat(
3160// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", 3874// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3161// pos2, Name, Scene.Name); 3875// pos2, Name, Scene.Name);
3162 3876
3163 // Checks if where it's headed exists a region 3877 if( Scene.TestBorderCross(pos2, Cardinals.E) ||
3164 bool needsTransit = false; 3878 Scene.TestBorderCross(pos2, Cardinals.W) ||
3165 if (m_scene.TestBorderCross(pos2, Cardinals.W)) 3879 Scene.TestBorderCross(pos2, Cardinals.N) ||
3166 { 3880 Scene.TestBorderCross(pos2, Cardinals.S)
3167 if (m_scene.TestBorderCross(pos2, Cardinals.S)) 3881 )
3168 { 3882 {
3169 needsTransit = true; 3883 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3170 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3171 }
3172 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3173 {
3174 needsTransit = true;
3175 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3176 }
3177 else
3178 {
3179 needsTransit = true;
3180 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3181 }
3182 }
3183 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3184 {
3185 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3186 {
3187 needsTransit = true;
3188 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3189 }
3190 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3191 {
3192 needsTransit = true;
3193 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3194 }
3195 else
3196 {
3197 needsTransit = true;
3198 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3199 }
3200 }
3201 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3202 {
3203 needsTransit = true;
3204 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3205 }
3206 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3207 {
3208 needsTransit = true;
3209 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3210 }
3211
3212 // Makes sure avatar does not end up outside region
3213 if (neighbor <= 0)
3214 {
3215 if (needsTransit)
3216 {
3217 if (m_requestedSitTargetUUID == UUID.Zero)
3218 {
3219 bool isFlying = Flying;
3220 RemoveFromPhysicalScene();
3221
3222 Vector3 pos = AbsolutePosition;
3223 if (AbsolutePosition.X < 0)
3224 pos.X += Velocity.X * 2;
3225 else if (AbsolutePosition.X > Constants.RegionSize)
3226 pos.X -= Velocity.X * 2;
3227 if (AbsolutePosition.Y < 0)
3228 pos.Y += Velocity.Y * 2;
3229 else if (AbsolutePosition.Y > Constants.RegionSize)
3230 pos.Y -= Velocity.Y * 2;
3231 Velocity = Vector3.Zero;
3232 AbsolutePosition = pos;
3233
3234// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3235
3236 AddToPhysicalScene(isFlying);
3237 }
3238 }
3239 }
3240 else if (neighbor > 0)
3241 {
3242 if (!CrossToNewRegion())
3243 {
3244 if (m_requestedSitTargetUUID == UUID.Zero)
3245 {
3246 bool isFlying = Flying;
3247 RemoveFromPhysicalScene();
3248
3249 Vector3 pos = AbsolutePosition;
3250 if (AbsolutePosition.X < 0)
3251 pos.X += Velocity.X * 2;
3252 else if (AbsolutePosition.X > Constants.RegionSize)
3253 pos.X -= Velocity.X * 2;
3254 if (AbsolutePosition.Y < 0)
3255 pos.Y += Velocity.Y * 2;
3256 else if (AbsolutePosition.Y > Constants.RegionSize)
3257 pos.Y -= Velocity.Y * 2;
3258 Velocity = Vector3.Zero;
3259 AbsolutePosition = pos;
3260
3261 AddToPhysicalScene(isFlying);
3262 }
3263 }
3264 }
3265 }
3266 else
3267 { 3884 {
3268 // This constant has been inferred from experimentation 3885 // we don't have entity transfer module
3269 // I'm not sure what this value should be, so I tried a few values. 3886 Vector3 pos = AbsolutePosition;
3270 timeStep = 0.04f; 3887 float px = pos.X;
3271 pos2 = AbsolutePosition; 3888 if (px < 0)
3272 pos2.X = pos2.X + (vel.X * timeStep); 3889 pos.X += Velocity.X * 2;
3273 pos2.Y = pos2.Y + (vel.Y * timeStep); 3890 else if (px > m_scene.RegionInfo.RegionSizeX)
3274 // Don't touch the Z 3891 pos.X -= Velocity.X * 2;
3275 m_pos = pos2; 3892
3276 m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos); 3893 float py = pos.Y;
3894 if (py < 0)
3895 pos.Y += Velocity.Y * 2;
3896 else if (py > m_scene.RegionInfo.RegionSizeY)
3897 pos.Y -= Velocity.Y * 2;
3898
3899 Velocity = Vector3.Zero;
3900 AbsolutePosition = pos;
3277 } 3901 }
3278 } 3902 }
3903 }
3904
3905 public void CrossToNewRegionFail()
3906 {
3907 if (m_requestedSitTargetUUID == UUID.Zero)
3908 {
3909 bool isFlying = Flying;
3910 RemoveFromPhysicalScene();
3911
3912 Vector3 pos = AbsolutePosition;
3913 float px = pos.X;
3914 if (px < 0)
3915 pos.X += Velocity.X * 2;
3916 else if (px > m_scene.RegionInfo.RegionSizeX)
3917 pos.X -= Velocity.X * 2;
3918
3919 float py = pos.Y;
3920 if (py < 0)
3921 pos.Y += Velocity.Y * 2;
3922 else if (py > m_scene.RegionInfo.RegionSizeY)
3923 pos.Y -= Velocity.Y * 2;
3924
3925 Velocity = Vector3.Zero;
3926 AbsolutePosition = pos;
3927
3928 AddToPhysicalScene(isFlying);
3929 }
3930
3279 } 3931 }
3280 3932
3281 /// <summary> 3933 /// <summary>
@@ -3286,21 +3938,25 @@ namespace OpenSim.Region.Framework.Scenes
3286 /// </summary> 3938 /// </summary>
3287 protected bool CrossToNewRegion() 3939 protected bool CrossToNewRegion()
3288 { 3940 {
3941 bool result = false;
3942// parcelRegionCross(false);
3289 try 3943 try
3290 { 3944 {
3291 return m_scene.CrossAgentToNewRegion(this, Flying); 3945 result = m_scene.CrossAgentToNewRegion(this, Flying);
3292 } 3946 }
3293 catch 3947 catch
3294 { 3948 {
3295 return m_scene.CrossAgentToNewRegion(this, false); 3949// result = m_scene.CrossAgentToNewRegion(this, false);
3950 return false;
3296 } 3951 }
3297 } 3952 // if(!result)
3953 // parcelRegionCross(true);
3954
3955 return result;
3298 3956
3299 public void RestoreInCurrentScene()
3300 {
3301 AddToPhysicalScene(false); // not exactly false
3302 } 3957 }
3303 3958
3959/* useless. Either use MakeChild or delete the presence
3304 public void Reset() 3960 public void Reset()
3305 { 3961 {
3306// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3962// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3311,7 +3967,7 @@ namespace OpenSim.Region.Framework.Scenes
3311 3967
3312 Animator.ResetAnimations(); 3968 Animator.ResetAnimations();
3313 } 3969 }
3314 3970*/
3315 /// <summary> 3971 /// <summary>
3316 /// Computes which child agents to close when the scene presence moves to another region. 3972 /// Computes which child agents to close when the scene presence moves to another region.
3317 /// Removes those regions from m_knownRegions. 3973 /// Removes those regions from m_knownRegions.
@@ -3350,15 +4006,18 @@ namespace OpenSim.Region.Framework.Scenes
3350 if (byebyeRegions.Count > 0) 4006 if (byebyeRegions.Count > 0)
3351 { 4007 {
3352 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 4008 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3353 Util.FireAndForget(delegate 4009
3354 { 4010 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3355 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 4011 string auth = string.Empty;
3356 }); 4012 if (acd != null)
4013 auth = acd.SessionID.ToString();
4014 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3357 } 4015 }
3358 4016
3359 foreach (ulong handle in byebyeRegions) 4017 foreach (ulong handle in byebyeRegions)
3360 { 4018 {
3361 RemoveNeighbourRegion(handle); 4019 RemoveNeighbourRegion(handle);
4020 Scene.CapsModule.DropChildSeed(UUID, handle);
3362 } 4021 }
3363 } 4022 }
3364 4023
@@ -3370,6 +4029,8 @@ namespace OpenSim.Region.Framework.Scenes
3370 /// </summary> 4029 /// </summary>
3371 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 4030 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3372 { 4031 {
4032 int oldgodlevel = GodLevel;
4033
3373 if (godStatus) 4034 if (godStatus)
3374 { 4035 {
3375 // For now, assign god level 200 to anyone 4036 // For now, assign god level 200 to anyone
@@ -3390,11 +4051,14 @@ namespace OpenSim.Region.Framework.Scenes
3390 } 4051 }
3391 4052
3392 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4053 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4054
4055 if(oldgodlevel != GodLevel)
4056 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3393 } 4057 }
3394 4058
3395 #region Child Agent Updates 4059 #region Child Agent Updates
3396 4060
3397 public void ChildAgentDataUpdate(AgentData cAgentData) 4061 public void UpdateChildAgent(AgentData cAgentData)
3398 { 4062 {
3399// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 4063// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3400 if (!IsChildAgent) 4064 if (!IsChildAgent)
@@ -3404,19 +4068,23 @@ namespace OpenSim.Region.Framework.Scenes
3404 } 4068 }
3405 4069
3406 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4070 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
4071
3407 private void RaiseUpdateThrottles() 4072 private void RaiseUpdateThrottles()
3408 { 4073 {
3409 m_scene.EventManager.TriggerThrottleUpdate(this); 4074 m_scene.EventManager.TriggerThrottleUpdate(this);
3410 } 4075 }
4076
3411 /// <summary> 4077 /// <summary>
3412 /// This updates important decision making data about a child agent 4078 /// This updates important decision making data about a child agent
3413 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 4079 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3414 /// </summary> 4080 /// </summary>
3415 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 4081 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3416 { 4082 {
3417 if (!IsChildAgent) 4083 if (!IsChildAgent)
3418 return; 4084 return;
3419 4085
4086 RegionHandle = cAgentData.RegionHandle;
4087
3420 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 4088 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3421 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 4089 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
3422 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 4090 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
@@ -3426,8 +4094,8 @@ namespace OpenSim.Region.Framework.Scenes
3426 // When we get to the point of re-computing neighbors everytime this 4094 // When we get to the point of re-computing neighbors everytime this
3427 // changes, then start using the agent's drawdistance rather than the 4095 // changes, then start using the agent's drawdistance rather than the
3428 // region's draw distance. 4096 // region's draw distance.
3429 // DrawDistance = cAgentData.Far; 4097 DrawDistance = cAgentData.Far;
3430 DrawDistance = Scene.DefaultDrawDistance; 4098// DrawDistance = Scene.DefaultDrawDistance;
3431 4099
3432 if (cAgentData.Position != marker) // UGH!! 4100 if (cAgentData.Position != marker) // UGH!!
3433 m_pos = cAgentData.Position + offset; 4101 m_pos = cAgentData.Position + offset;
@@ -3441,10 +4109,36 @@ namespace OpenSim.Region.Framework.Scenes
3441 CameraPosition = cAgentData.Center + offset; 4109 CameraPosition = cAgentData.Center + offset;
3442 4110
3443 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) 4111 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
3444 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); 4112 {
4113 // some scaling factor
4114 float x = m_pos.X;
4115 if (x > m_scene.RegionInfo.RegionSizeX)
4116 x -= m_scene.RegionInfo.RegionSizeX;
4117 float y = m_pos.Y;
4118 if (y > m_scene.RegionInfo.RegionSizeY)
4119 y -= m_scene.RegionInfo.RegionSizeY;
4120
4121 x = x * x + y * y;
4122
4123 const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize;
4124 float factor = 1.0f - distScale * x;
4125 if (factor < 0.2f)
4126 factor = 0.2f;
4127
4128 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor);
4129 }
4130
4131 if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4132 {
4133 if (Scene.CapsModule != null)
4134 {
4135 Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4136 }
4137
4138 KnownRegions = cAgentData.ChildrenCapSeeds;
4139 }
3445 4140
3446 //cAgentData.AVHeight; 4141 //cAgentData.AVHeight;
3447 RegionHandle = cAgentData.RegionHandle;
3448 //m_velocity = cAgentData.Velocity; 4142 //m_velocity = cAgentData.Velocity;
3449 } 4143 }
3450 4144
@@ -3454,6 +4148,7 @@ namespace OpenSim.Region.Framework.Scenes
3454 4148
3455 cAgent.AgentID = UUID; 4149 cAgent.AgentID = UUID;
3456 cAgent.RegionID = Scene.RegionInfo.RegionID; 4150 cAgent.RegionID = Scene.RegionInfo.RegionID;
4151 cAgent.SessionID = ControllingClient.SessionId;
3457 4152
3458 cAgent.Position = AbsolutePosition; 4153 cAgent.Position = AbsolutePosition;
3459 cAgent.Velocity = m_velocity; 4154 cAgent.Velocity = m_velocity;
@@ -3465,16 +4160,7 @@ namespace OpenSim.Region.Framework.Scenes
3465 cAgent.Far = DrawDistance; 4160 cAgent.Far = DrawDistance;
3466 4161
3467 // Throttles 4162 // Throttles
3468 float multiplier = 1; 4163 cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
3469 int childRegions = KnownRegionCount;
3470 if (childRegions != 0)
3471 multiplier = 1f / childRegions;
3472
3473 // Minimum throttle for a child region is 1/4 of the root region throttle
3474 if (multiplier <= 0.25f)
3475 multiplier = 0.25f;
3476
3477 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
3478 4164
3479 cAgent.HeadRotation = m_headrotation; 4165 cAgent.HeadRotation = m_headrotation;
3480 cAgent.BodyRotation = Rotation; 4166 cAgent.BodyRotation = Rotation;
@@ -3487,7 +4173,8 @@ namespace OpenSim.Region.Framework.Scenes
3487 4173
3488 cAgent.AlwaysRun = SetAlwaysRun; 4174 cAgent.AlwaysRun = SetAlwaysRun;
3489 4175
3490 cAgent.Appearance = new AvatarAppearance(Appearance); 4176 // make clear we want the all thing
4177 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3491 4178
3492 cAgent.ParentPart = ParentUUID; 4179 cAgent.ParentPart = ParentUUID;
3493 cAgent.SitOffset = PrevSitOffset; 4180 cAgent.SitOffset = PrevSitOffset;
@@ -3513,13 +4200,16 @@ namespace OpenSim.Region.Framework.Scenes
3513 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 4200 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3514 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; 4201 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3515 4202
4203 cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4204
4205 cAgent.MotionState = (byte)Animator.currentControlState;
4206
3516 if (Scene.AttachmentsModule != null) 4207 if (Scene.AttachmentsModule != null)
3517 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 4208 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
3518 } 4209 }
3519 4210
3520 private void CopyFrom(AgentData cAgent) 4211 private void CopyFrom(AgentData cAgent)
3521 { 4212 {
3522 m_originRegionID = cAgent.RegionID;
3523 4213
3524 m_callbackURI = cAgent.CallbackURI; 4214 m_callbackURI = cAgent.CallbackURI;
3525// m_log.DebugFormat( 4215// m_log.DebugFormat(
@@ -3538,8 +4228,17 @@ namespace OpenSim.Region.Framework.Scenes
3538 // When we get to the point of re-computing neighbors everytime this 4228 // When we get to the point of re-computing neighbors everytime this
3539 // changes, then start using the agent's drawdistance rather than the 4229 // changes, then start using the agent's drawdistance rather than the
3540 // region's draw distance. 4230 // region's draw distance.
3541 // DrawDistance = cAgent.Far; 4231 DrawDistance = cAgent.Far;
3542 DrawDistance = Scene.DefaultDrawDistance; 4232 //DrawDistance = Scene.DefaultDrawDistance;
4233
4234 if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4235 {
4236 if (Scene.CapsModule != null)
4237 {
4238 Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4239 }
4240 KnownRegions = cAgent.ChildrenCapSeeds;
4241 }
3543 4242
3544 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4243 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
3545 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4244 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
@@ -3552,14 +4251,17 @@ namespace OpenSim.Region.Framework.Scenes
3552 GodLevel = cAgent.GodLevel; 4251 GodLevel = cAgent.GodLevel;
3553 SetAlwaysRun = cAgent.AlwaysRun; 4252 SetAlwaysRun = cAgent.AlwaysRun;
3554 4253
4254
3555 Appearance = new AvatarAppearance(cAgent.Appearance); 4255 Appearance = new AvatarAppearance(cAgent.Appearance);
4256/*
4257 bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4258
3556 if (PhysicsActor != null) 4259 if (PhysicsActor != null)
3557 { 4260 {
3558 bool isFlying = Flying;
3559 RemoveFromPhysicalScene(); 4261 RemoveFromPhysicalScene();
3560 AddToPhysicalScene(isFlying); 4262 AddToPhysicalScene(isFlying);
3561 } 4263 }
3562 4264*/
3563 try 4265 try
3564 { 4266 {
3565 lock (scriptedcontrols) 4267 lock (scriptedcontrols)
@@ -3583,16 +4285,26 @@ namespace OpenSim.Region.Framework.Scenes
3583 } 4285 }
3584 catch { } 4286 catch { }
3585 4287
4288 Animator.ResetAnimations();
4289
4290 Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4291
3586 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4292 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
3587 if (cAgent.Anims != null)
3588 Animator.Animations.FromArray(cAgent.Anims);
3589 if (cAgent.DefaultAnim != null) 4293 if (cAgent.DefaultAnim != null)
3590 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4294 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3591 if (cAgent.AnimState != null) 4295 if (cAgent.AnimState != null)
3592 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4296 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4297 if (cAgent.Anims != null)
4298 Animator.Animations.FromArray(cAgent.Anims);
4299 if (cAgent.MotionState != 0)
4300 Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
3593 4301
3594 if (Scene.AttachmentsModule != null) 4302 if (Scene.AttachmentsModule != null)
3595 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 4303 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4304
4305 lock (m_originRegionIDAccessLock)
4306 m_originRegionID = cAgent.RegionID;
4307
3596 } 4308 }
3597 4309
3598 public bool CopyAgent(out IAgentData agent) 4310 public bool CopyAgent(out IAgentData agent)
@@ -3609,12 +4321,12 @@ namespace OpenSim.Region.Framework.Scenes
3609 /// </summary> 4321 /// </summary>
3610 public void UpdateMovement() 4322 public void UpdateMovement()
3611 { 4323 {
4324 if (IsInTransit)
4325 return;
3612 if (m_forceToApply.HasValue) 4326 if (m_forceToApply.HasValue)
3613 { 4327 {
3614 Vector3 force = m_forceToApply.Value; 4328 Vector3 force = m_forceToApply.Value;
3615 4329
3616 Updated = true;
3617
3618 Velocity = force; 4330 Velocity = force;
3619 4331
3620 m_forceToApply = null; 4332 m_forceToApply = null;
@@ -3689,14 +4401,17 @@ namespace OpenSim.Region.Framework.Scenes
3689 { 4401 {
3690 if (IsChildAgent || Animator == null) 4402 if (IsChildAgent || Animator == null)
3691 return; 4403 return;
3692 4404
4405 if(IsInTransit)
4406 return;
3693 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4407 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3694 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( 4408 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3695 // as of this comment the interval is set in AddToPhysicalScene 4409 // as of this comment the interval is set in AddToPhysicalScene
3696 4410
3697// if (m_updateCount > 0) 4411// if (m_updateCount > 0)
3698// { 4412// {
3699 Animator.UpdateMovementAnimations(); 4413 if (Animator.UpdateMovementAnimations())
4414 TriggerScenePresenceUpdated();
3700// m_updateCount--; 4415// m_updateCount--;
3701// } 4416// }
3702 4417
@@ -3860,6 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
3860// Animator.Close(); 4575// Animator.Close();
3861 Animator = null; 4576 Animator = null;
3862 4577
4578 LifecycleState = ScenePresenceState.Removed;
3863 } 4579 }
3864 4580
3865 public void AddAttachment(SceneObjectGroup gobj) 4581 public void AddAttachment(SceneObjectGroup gobj)
@@ -4039,6 +4755,287 @@ namespace OpenSim.Region.Framework.Scenes
4039 return validated; 4755 return validated;
4040 } 4756 }
4041 4757
4758 public void SendAttachmentsToAllAgents()
4759 {
4760 lock (m_attachments)
4761 {
4762 foreach (SceneObjectGroup sog in m_attachments)
4763 {
4764 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4765 {
4766 if (p != this && sog.HasPrivateAttachmentPoint)
4767 return;
4768
4769 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4770 return;
4771
4772 SendTerseUpdateToAgentNF(p);
4773 SendAttachmentFullUpdateToAgentNF(sog, p);
4774 });
4775 }
4776 }
4777 }
4778
4779 // send attachments to a client without filters except for huds
4780 // for now they are checked in several places down the line...
4781 public void SendAttachmentsToAgentNF(ScenePresence p)
4782 {
4783 SendTerseUpdateToAgentNF(p);
4784 lock (m_attachments)
4785 {
4786 foreach (SceneObjectGroup sog in m_attachments)
4787 {
4788 SendAttachmentFullUpdateToAgentNF(sog, p);
4789 }
4790 }
4791 }
4792
4793 public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
4794 {
4795 if (p != this && sog.HasPrivateAttachmentPoint)
4796 return;
4797
4798 SceneObjectPart[] parts = sog.Parts;
4799 SceneObjectPart rootpart = sog.RootPart;
4800
4801 p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
4802
4803 for (int i = 0; i < parts.Length; i++)
4804 {
4805 SceneObjectPart part = parts[i];
4806 if (part == rootpart)
4807 continue;
4808 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4809 }
4810 }
4811
4812 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
4813 {
4814 if (IsChildAgent || IsInTransit)
4815 return;
4816
4817 SceneObjectPart[] origparts = sog.Parts;
4818 SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
4819 PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
4820
4821 SceneObjectPart rootpart = sog.RootPart;
4822 UpdateRequired rootreq = sog.RootPart.UpdateFlag;
4823
4824 int j = 0;
4825 bool allterse = true;
4826 for (int i = 0; i < origparts.Length; i++)
4827 {
4828 if (origparts[i] != rootpart)
4829 {
4830 switch (origparts[i].UpdateFlag)
4831 {
4832 case UpdateRequired.NONE:
4833 break;
4834
4835 case UpdateRequired.TERSE:
4836 flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4837 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4838 parts[j] = origparts[i];
4839 j++;
4840 break;
4841
4842 case UpdateRequired.FULL:
4843 flags[j] = PrimUpdateFlags.FullUpdate;
4844 allterse = false;
4845 parts[j] = origparts[i];
4846 j++;
4847 break;
4848 }
4849 }
4850 origparts[i].UpdateFlag = 0;
4851 }
4852
4853 if (j == 0 && rootreq == UpdateRequired.NONE)
4854 return;
4855
4856 PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
4857
4858 if (rootreq != UpdateRequired.FULL && allterse)
4859 {
4860 rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4861 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4862 }
4863
4864 int nparts = j;
4865
4866 ControllingClient.SendEntityUpdate(rootpart, rootflag);
4867
4868 for (int i = 0; i < nparts; i++)
4869 {
4870 ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4871 }
4872
4873 if (sog.HasPrivateAttachmentPoint)
4874 return;
4875
4876 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4877 foreach (ScenePresence p in allPresences)
4878 {
4879 if (p == this)
4880 continue;
4881
4882 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4883 continue;
4884
4885 p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
4886
4887 for (int i = 0; i < nparts; i++)
4888 {
4889 p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4890 }
4891 }
4892 }
4893
4894 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
4895 {
4896 if (IsChildAgent || IsInTransit)
4897 return;
4898
4899 PrimUpdateFlags flag;
4900 switch (UpdateFlag)
4901 {
4902 case UpdateRequired.TERSE:
4903 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4904 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4905 break;
4906
4907 case UpdateRequired.FULL:
4908 flag = PrimUpdateFlags.FullUpdate;
4909 break;
4910
4911 default:
4912 return;
4913 }
4914
4915 SceneObjectPart[] parts = sog.Parts;
4916 SceneObjectPart rootpart = sog.RootPart;
4917
4918// rootpart.UpdateFlag = 0;
4919
4920 ControllingClient.SendEntityUpdate(rootpart, flag);
4921
4922 for (int i = 0; i < parts.Length; i++)
4923 {
4924 SceneObjectPart part = parts[i];
4925 if (part == rootpart)
4926 continue;
4927 ControllingClient.SendEntityUpdate(part, flag);
4928// part.UpdateFlag = 0;
4929 }
4930
4931 if (sog.HasPrivateAttachmentPoint)
4932 return;
4933
4934
4935 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4936 foreach (ScenePresence p in allPresences)
4937 {
4938 if (p == this)
4939 continue;
4940
4941 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4942 continue;
4943
4944 p.ControllingClient.SendEntityUpdate(rootpart, flag);
4945
4946 for (int i = 0; i < parts.Length; i++)
4947 {
4948 SceneObjectPart part = parts[i];
4949 if (part == rootpart)
4950 continue;
4951 p.ControllingClient.SendEntityUpdate(part, flag);
4952 }
4953 }
4954 }
4955
4956 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
4957 {
4958 if (IsChildAgent || IsInTransit)
4959 return;
4960
4961
4962 PrimUpdateFlags flag;
4963 switch (part.UpdateFlag)
4964 {
4965 case UpdateRequired.TERSE:
4966 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4967 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4968 break;
4969
4970 case UpdateRequired.FULL:
4971 flag = PrimUpdateFlags.FullUpdate;
4972 break;
4973
4974 default:
4975 return;
4976 }
4977
4978 part.UpdateFlag = 0;
4979
4980 ControllingClient.SendEntityUpdate(part, flag);
4981
4982 if (part.ParentGroup.HasPrivateAttachmentPoint)
4983 return;
4984
4985 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4986 foreach (ScenePresence p in allPresences)
4987 {
4988 if (p == this)
4989 continue;
4990
4991 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4992 continue;
4993
4994 p.ControllingClient.SendEntityUpdate(part, flag);
4995 }
4996 }
4997
4998
4999 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
5000 {
5001 if (IsChildAgent || IsInTransit)
5002 return;
5003
5004 PrimUpdateFlags flag;
5005 switch (UpdateFlag)
5006 {
5007 case UpdateRequired.TERSE:
5008 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5009 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5010 break;
5011
5012 case UpdateRequired.FULL:
5013 flag = PrimUpdateFlags.FullUpdate;
5014 break;
5015
5016 default:
5017 return;
5018 }
5019
5020// part.UpdateFlag = 0;
5021
5022 ControllingClient.SendEntityUpdate(part, flag);
5023
5024 if (part.ParentGroup.HasPrivateAttachmentPoint)
5025 return;
5026
5027 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5028 foreach (ScenePresence p in allPresences)
5029 {
5030 if (p == this)
5031 continue;
5032 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5033 continue;
5034
5035 p.ControllingClient.SendEntityUpdate(part, flag);
5036 }
5037 }
5038
4042 /// <summary> 5039 /// <summary>
4043 /// Send a script event to this scene presence's attachments 5040 /// Send a script event to this scene presence's attachments
4044 /// </summary> 5041 /// </summary>
@@ -4157,6 +5154,15 @@ namespace OpenSim.Region.Framework.Scenes
4157 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5154 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4158 } 5155 }
4159 5156
5157 public void ClearControls()
5158 {
5159 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5160 lock (scriptedcontrols)
5161 {
5162 scriptedcontrols.Clear();
5163 }
5164 }
5165
4160 private void UnRegisterSeatControls(UUID obj) 5166 private void UnRegisterSeatControls(UUID obj)
4161 { 5167 {
4162 List<UUID> takers = new List<UUID>(); 5168 List<UUID> takers = new List<UUID>();
@@ -4546,8 +5552,8 @@ namespace OpenSim.Region.Framework.Scenes
4546 pos = land.LandData.UserLocation; 5552 pos = land.LandData.UserLocation;
4547 } 5553 }
4548 } 5554 }
4549 5555// this is now done in completeMovement for all cases and not just this
4550 land.SendLandUpdateToClient(ControllingClient); 5556// land.SendLandUpdateToClient(ControllingClient);
4551 } 5557 }
4552 } 5558 }
4553 5559
@@ -4562,6 +5568,7 @@ namespace OpenSim.Region.Framework.Scenes
4562 detobj.velVector = obj.Velocity; 5568 detobj.velVector = obj.Velocity;
4563 detobj.colliderType = 0; 5569 detobj.colliderType = 0;
4564 detobj.groupUUID = obj.GroupID; 5570 detobj.groupUUID = obj.GroupID;
5571 detobj.linkNumber = 0;
4565 5572
4566 return detobj; 5573 return detobj;
4567 } 5574 }
@@ -4577,6 +5584,7 @@ namespace OpenSim.Region.Framework.Scenes
4577 detobj.velVector = av.Velocity; 5584 detobj.velVector = av.Velocity;
4578 detobj.colliderType = 0; 5585 detobj.colliderType = 0;
4579 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 5586 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5587 detobj.linkNumber = 0;
4580 5588
4581 return detobj; 5589 return detobj;
4582 } 5590 }
@@ -4592,7 +5600,7 @@ namespace OpenSim.Region.Framework.Scenes
4592 detobj.velVector = Vector3.Zero; 5600 detobj.velVector = Vector3.Zero;
4593 detobj.colliderType = 0; 5601 detobj.colliderType = 0;
4594 detobj.groupUUID = UUID.Zero; 5602 detobj.groupUUID = UUID.Zero;
4595 5603 detobj.linkNumber = 0;
4596 return detobj; 5604 return detobj;
4597 } 5605 }
4598 5606
@@ -4684,6 +5692,8 @@ namespace OpenSim.Region.Framework.Scenes
4684 5692
4685 else 5693 else
4686 { 5694 {
5695 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5696
4687 foreach (uint id in coldata.Keys) 5697 foreach (uint id in coldata.Keys)
4688 { 5698 {
4689 thisHitColliders.Add(id); 5699 thisHitColliders.Add(id);
@@ -4691,7 +5701,7 @@ namespace OpenSim.Region.Framework.Scenes
4691 { 5701 {
4692 startedColliders.Add(id); 5702 startedColliders.Add(id);
4693 curcontact = coldata[id]; 5703 curcontact = coldata[id];
4694 if (Math.Abs(curcontact.RelativeSpeed) > 0.2) 5704 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
4695 { 5705 {
4696 soundinfo = new CollisionForSoundInfo(); 5706 soundinfo = new CollisionForSoundInfo();
4697 soundinfo.colliderID = id; 5707 soundinfo.colliderID = id;
@@ -4770,5 +5780,282 @@ namespace OpenSim.Region.Framework.Scenes
4770 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5780 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4771 5781
4772 } 5782 }
5783
5784 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5785 {
5786 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5787
5788 foreach (ScenePresence p in allpresences)
5789 {
5790 if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5791 continue;
5792
5793 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5794 {
5795 if (isGod)
5796 p.SendViewTo(this);
5797 else
5798 p.SendKillTo(this);
5799 }
5800 }
5801 }
5802
5803 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5804 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5805 {
5806 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5807 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5808 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5809 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5810 List<ScenePresence> allpresences = null;
5811
5812 if (IsInTransit || IsChildAgent)
5813 return;
5814
5815 if (check)
5816 {
5817 // check is relative to current parcel only
5818 if (currentParcelUUID == null || oldhide == currentParcelHide)
5819 return;
5820
5821 allpresences = m_scene.GetScenePresences();
5822
5823 if (oldhide)
5824 { // where private
5825 foreach (ScenePresence p in allpresences)
5826 {
5827 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5828 continue;
5829
5830 // those on not on parcel see me
5831 if (currentParcelID != p.currentParcelUUID)
5832 {
5833 viewsToSendto.Add(p); // they see me
5834 }
5835 }
5836 } // where private end
5837
5838 else
5839 { // where public
5840 foreach (ScenePresence p in allpresences)
5841 {
5842 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5843 continue;
5844
5845 // those not on parcel dont see me
5846 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5847 {
5848 killsToSendto.Add(p); // they dont see me
5849 }
5850 }
5851 } // where public end
5852
5853 allpresences.Clear();
5854 }
5855 else
5856 {
5857 if (currentParcelHide)
5858 {
5859 // now on a private parcel
5860 allpresences = m_scene.GetScenePresences();
5861
5862 if (previusParcelHide && previusParcelID != UUID.Zero)
5863 {
5864 foreach (ScenePresence p in allpresences)
5865 {
5866 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5867 continue;
5868
5869 // only those on previus parcel need receive kills
5870 if (previusParcelID == p.currentParcelUUID)
5871 {
5872 if(p.GodLevel < 200)
5873 killsToSendto.Add(p); // they dont see me
5874 if(GodLevel < 200)
5875 killsToSendme.Add(p); // i dont see them
5876 }
5877 // only those on new parcel need see
5878 if (currentParcelID == p.currentParcelUUID)
5879 {
5880 viewsToSendto.Add(p); // they see me
5881 viewsToSendme.Add(p); // i see them
5882 }
5883 }
5884 }
5885 else
5886 {
5887 //was on a public area
5888 allpresences = m_scene.GetScenePresences();
5889
5890 foreach (ScenePresence p in allpresences)
5891 {
5892 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5893 continue;
5894
5895 // those not on new parcel dont see me
5896 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5897 {
5898 killsToSendto.Add(p); // they dont see me
5899 }
5900 else
5901 {
5902 viewsToSendme.Add(p); // i see those on it
5903 }
5904 }
5905 }
5906 allpresences.Clear();
5907 } // now on a private parcel end
5908
5909 else
5910 {
5911 // now on public parcel
5912 if (previusParcelHide && previusParcelID != UUID.Zero)
5913 {
5914 // was on private area
5915 allpresences = m_scene.GetScenePresences();
5916
5917 foreach (ScenePresence p in allpresences)
5918 {
5919 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5920 continue;
5921 // only those old parcel need kills
5922 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
5923 {
5924 killsToSendme.Add(p); // i dont see them
5925 }
5926 else
5927 {
5928 viewsToSendto.Add(p); // they see me
5929 }
5930 }
5931 }
5932 else
5933 return; // was on a public area also
5934 } // now on public parcel end
5935 }
5936
5937 // send the things
5938
5939 if (killsToSendto.Count > 0)
5940 {
5941 foreach (ScenePresence p in killsToSendto)
5942 {
5943 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
5944 SendKillTo(p);
5945 }
5946 }
5947
5948 if (killsToSendme.Count > 0)
5949 {
5950 foreach (ScenePresence p in killsToSendme)
5951 {
5952 m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
5953 p.SendKillTo(this);
5954 }
5955 }
5956
5957 if (viewsToSendto.Count > 0)
5958 {
5959 foreach (ScenePresence p in viewsToSendto)
5960 {
5961 SendViewTo(p);
5962 }
5963 }
5964
5965 if (viewsToSendme.Count > 0 )
5966 {
5967 foreach (ScenePresence p in viewsToSendme)
5968 {
5969 if (p.IsChildAgent)
5970 continue;
5971// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
5972 p.SendViewTo(this);
5973 }
5974 }
5975 }
5976
5977 public void HasMovedAway(bool nearRegion)
5978 {
5979
5980 if (nearRegion)
5981 {
5982 if (Scene.AttachmentsModule != null)
5983 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
5984
5985 if (!ParcelHideThisAvatar || GodLevel >= 200)
5986 return;
5987
5988 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5989 foreach (ScenePresence p in allpresences)
5990 {
5991 if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
5992 continue;
5993
5994 if (p.currentParcelUUID == m_currentParcelUUID)
5995 {
5996 p.SendKillTo(this);
5997 }
5998 }
5999 }
6000 else
6001 {
6002 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6003 foreach (ScenePresence p in allpresences)
6004 {
6005 if (p == this)
6006 continue;
6007 SendKillTo(p);
6008 if (!p.IsChildAgent)
6009 p.SendKillTo(this);
6010 }
6011
6012 if (Scene.AttachmentsModule != null)
6013 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6014 }
6015 }
6016
6017
6018// kill with attachs root kills
6019 public void SendKillTo(ScenePresence p)
6020 {
6021 List<uint> ids = new List<uint>(m_attachments.Count + 1);
6022 foreach (SceneObjectGroup sog in m_attachments)
6023 {
6024 ids.Add(sog.RootPart.LocalId);
6025 }
6026
6027 ids.Add(LocalId);
6028 p.ControllingClient.SendKillObject(ids);
6029 }
6030
6031/*
6032// kill with hack
6033 public void SendKillTo(ScenePresence p)
6034 {
6035 foreach (SceneObjectGroup sog in m_attachments)
6036 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6037 p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6038 }
6039*/
6040 public void SendViewTo(ScenePresence p)
6041 {
6042 SendAvatarDataToAgentNF(p);
6043 SendAppearanceToAgent(p);
6044 if (Animator != null)
6045 Animator.SendAnimPackToClient(p.ControllingClient);
6046 SendAttachmentsToAgentNF(p);
6047 }
6048
6049 public void SetAnimationOverride(string animState, UUID animID)
6050 {
6051 Overrides.SetOverride(animState, animID);
6052// Animator.SendAnimPack();
6053 Animator.ForceUpdateMovementAnimations();
6054 }
6055
6056 public UUID GetAnimationOverride(string animState)
6057 {
6058 return Overrides.GetOverriddenAnimation(animState);
6059 }
4773 } 6060 }
4774} 6061}
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..40e88f1 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);
@@ -1371,8 +1415,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1371 if (sop.VehicleParams != null) 1415 if (sop.VehicleParams != null)
1372 sop.VehicleParams.ToXml2(writer); 1416 sop.VehicleParams.ToXml2(writer);
1373 1417
1374 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) 1418 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1375 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1376 if (sop.Density != 1000.0f) 1419 if (sop.Density != 1000.0f)
1377 writer.WriteElementString("Density", sop.Density.ToString().ToLower()); 1420 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1378 if (sop.Friction != 0.6f) 1421 if (sop.Friction != 0.6f)
@@ -1384,6 +1427,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1384 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); 1427 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1385 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); 1428 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1386 1429
1430 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1431 {
1432 WriteUUID(writer, "SoundID", sop.Sound, options);
1433 writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower());
1434 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1435 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower());
1436 }
1437 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1438
1387 writer.WriteEndElement(); 1439 writer.WriteEndElement();
1388 } 1440 }
1389 1441
@@ -1451,7 +1503,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1451 1503
1452 WriteUUID(writer, "CreatorID", item.CreatorID, options); 1504 WriteUUID(writer, "CreatorID", item.CreatorID, options);
1453 1505
1454 if (item.CreatorData != null && item.CreatorData != string.Empty) 1506 if (!string.IsNullOrEmpty(item.CreatorData))
1455 writer.WriteElementString("CreatorData", item.CreatorData); 1507 writer.WriteElementString("CreatorData", item.CreatorData);
1456 else if (options.ContainsKey("home")) 1508 else if (options.ContainsKey("home"))
1457 { 1509 {
@@ -1539,6 +1591,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1591 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1592 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1593 writer.WriteElementString("State", shp.State.ToString());
1594 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1595
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1596 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1597 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