diff options
Diffstat (limited to 'OpenSim/Region/Framework')
44 files changed, 2891 insertions, 1033 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs index 21ed44f..b536a49 100644 --- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs | |||
@@ -1,9 +1,30 @@ | |||
1 | //////////////////////////////////////////////////////////////// | 1 | /* |
2 | // | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | // (c) 2009, 2010 Careminster Limited and Melanie Thielker | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | // | 4 | * |
5 | // All rights reserved | 5 | * Redistribution and use in source and binary forms, with or without |
6 | // | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
7 | using System; | 28 | using System; |
8 | using Nini.Config; | 29 | using Nini.Config; |
9 | using OpenSim.Framework; | 30 | using 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..214b07a 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs | |||
@@ -47,13 +47,33 @@ namespace OpenSim.Region.Framework.Interfaces | |||
47 | /// The handle of the destination region. If it's the same as the region currently | 47 | /// 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. | 48 | /// occupied by the agent then the teleport will be within that region. |
49 | /// </param> | 49 | /// </param> |
50 | /// <param name='agent'></param> | ||
51 | /// <param name='regionHandle'></param> | ||
50 | /// <param name='position'></param> | 52 | /// <param name='position'></param> |
51 | /// <param name='lookAt'></param> | 53 | /// <param name='lookAt'></param> |
52 | /// <param name='teleportFlags'></param> | 54 | /// <param name='teleportFlags'></param> |
53 | void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); | 55 | void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); |
54 | 56 | ||
57 | /// <summary> | ||
58 | /// Teleports the agent for the given client to their home destination. | ||
59 | /// </summary> | ||
60 | /// <param name='id'></param> | ||
61 | /// <param name='client'></param> | ||
55 | bool TeleportHome(UUID id, IClientAPI client); | 62 | bool TeleportHome(UUID id, IClientAPI client); |
56 | 63 | ||
64 | /// <summary> | ||
65 | /// Teleport an agent directly to a given region without checking whether the region should be substituted. | ||
66 | /// </summary> | ||
67 | /// <remarks> | ||
68 | /// Please use Teleport() instead unless you know exactly what you're doing. | ||
69 | /// Do not use for same region teleports. | ||
70 | /// </remarks> | ||
71 | /// <param name='sp'></param> | ||
72 | /// <param name='reg'></param> | ||
73 | /// <param name='finalDestination'>/param> | ||
74 | /// <param name='position'></param> | ||
75 | /// <param name='lookAt'></param> | ||
76 | /// <param name='teleportFlags'></param> | ||
57 | void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, | 77 | void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, |
58 | Vector3 position, Vector3 lookAt, uint teleportFlags); | 78 | Vector3 position, Vector3 lookAt, uint teleportFlags); |
59 | 79 | ||
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 | |||
28 | using System; | ||
29 | using OpenMetaverse; | ||
30 | using OpenSim.Framework; | ||
31 | using Caps=OpenSim.Framework.Capabilities.Caps; | ||
32 | |||
33 | namespace 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 | |||
28 | using OpenMetaverse; | ||
29 | using OpenSim.Framework; | ||
30 | using OpenSim.Region.Framework.Scenes; | ||
31 | |||
32 | namespace 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 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | |||
4 | namespace OpenSim.Region.Framework.Interfaces | ||
5 | { | ||
6 | public interface IServiceThrottleModule | ||
7 | { | ||
8 | /// <summary> | ||
9 | /// Enqueue a continuation meant to get a resource from elsewhere. | ||
10 | /// As usual with CPS, caller beware: if that continuation is a never-ending computation, | ||
11 | /// the whole thread will be blocked, and no requests are processed | ||
12 | /// </summary> | ||
13 | /// <param name="category">Category of the resource (e.g. name, region)</param> | ||
14 | /// <param name="itemid">The resource identifier</param> | ||
15 | /// <param name="continuation">The continuation to be executed</param> | ||
16 | void Enqueue(string category, string itemid, Action continuation); | ||
17 | } | ||
18 | |||
19 | } | ||
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 68af492..8372ddd 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs | |||
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
104 | /// <param name="sound">Sound asset ID</param> | 104 | /// <param name="sound">Sound asset ID</param> |
105 | /// <param name="volume">Sound volume</param> | 105 | /// <param name="volume">Sound volume</param> |
106 | /// <param name="triggered">Triggered or not.</param> | 106 | /// <param name="triggered">Triggered or not.</param> |
107 | /// <param name="flags"></param> | ||
108 | /// <param name="radius">Sound radius</param> | 107 | /// <param name="radius">Sound radius</param> |
109 | /// <param name="useMaster">Play using sound master</param> | 108 | /// <param name="useMaster">Play using sound master</param> |
110 | /// <param name="isMaster">Play as sound master</param> | 109 | /// <param name="isMaster">Play as sound master</param> |
@@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces | |||
123 | /// <param name="max">AABB top north-east corner</param> | 122 | /// <param name="max">AABB top north-east corner</param> |
124 | void TriggerSoundLimited(UUID objectID, UUID sound, double volume, | 123 | void TriggerSoundLimited(UUID objectID, UUID sound, double volume, |
125 | Vector3 min, Vector3 max); | 124 | Vector3 min, Vector3 max); |
125 | |||
126 | /// <summary> | ||
127 | /// Set whether sounds on the given prim should be queued. | ||
128 | /// </summary> | ||
129 | /// <param name='objectID'></param> | ||
130 | /// <param name='shouldQueue'></param> | ||
131 | void SetSoundQueueing(UUID objectID, bool shouldQueue); | ||
126 | } | 132 | } |
127 | } \ No newline at end of file | 133 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/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 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.Text; | ||
31 | using log4net; | 32 | using log4net; |
32 | using OpenMetaverse; | 33 | using OpenMetaverse; |
34 | using OpenMetaverse.StructuredData; | ||
35 | |||
33 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
34 | 37 | ||
35 | using Animation = OpenSim.Framework.Animation; | 38 | using Animation = OpenSim.Framework.Animation; |
@@ -60,6 +63,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
60 | ResetDefaultAnimation(); | 63 | ResetDefaultAnimation(); |
61 | } | 64 | } |
62 | 65 | ||
66 | public AnimationSet(OSDArray pArray) | ||
67 | { | ||
68 | ResetDefaultAnimation(); | ||
69 | FromOSDArray(pArray); | ||
70 | } | ||
71 | |||
63 | public bool HasAnimation(UUID animID) | 72 | public bool HasAnimation(UUID animID) |
64 | { | 73 | { |
65 | if (m_defaultAnimation.AnimID == animID) | 74 | if (m_defaultAnimation.AnimID == animID) |
@@ -218,5 +227,110 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
218 | foreach (OpenSim.Framework.Animation anim in theArray) | 227 | foreach (OpenSim.Framework.Animation anim in theArray) |
219 | m_animations.Add(anim); | 228 | m_animations.Add(anim); |
220 | } | 229 | } |
230 | |||
231 | // Create representation of this AnimationSet as an OSDArray. | ||
232 | // First two entries in the array are the default and implicitDefault animations | ||
233 | // followed by the other animations. | ||
234 | public OSDArray ToOSDArray() | ||
235 | { | ||
236 | OSDArray ret = new OSDArray(); | ||
237 | ret.Add(DefaultAnimation.PackUpdateMessage()); | ||
238 | ret.Add(ImplicitDefaultAnimation.PackUpdateMessage()); | ||
239 | |||
240 | foreach (OpenSim.Framework.Animation anim in m_animations) | ||
241 | ret.Add(anim.PackUpdateMessage()); | ||
242 | |||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | public void FromOSDArray(OSDArray pArray) | ||
247 | { | ||
248 | this.Clear(); | ||
249 | |||
250 | if (pArray.Count >= 1) | ||
251 | { | ||
252 | m_defaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[0]); | ||
253 | } | ||
254 | if (pArray.Count >= 2) | ||
255 | { | ||
256 | m_implicitDefaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[1]); | ||
257 | } | ||
258 | for (int ii = 2; ii < pArray.Count; ii++) | ||
259 | { | ||
260 | m_animations.Add(new OpenSim.Framework.Animation((OSDMap)pArray[ii])); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | // Compare two AnimationSets and return 'true' if the default animations are the same | ||
265 | // and all of the animations in the list are equal. | ||
266 | public override bool Equals(object obj) | ||
267 | { | ||
268 | AnimationSet other = obj as AnimationSet; | ||
269 | if (other != null) | ||
270 | { | ||
271 | if (this.DefaultAnimation.Equals(other.DefaultAnimation) | ||
272 | && this.ImplicitDefaultAnimation.Equals(other.ImplicitDefaultAnimation)) | ||
273 | { | ||
274 | // The defaults are the same. Is the list of animations the same? | ||
275 | OpenSim.Framework.Animation[] thisAnims = this.ToArray(); | ||
276 | OpenSim.Framework.Animation[] otherAnims = other.ToArray(); | ||
277 | if (thisAnims.Length == 0 && otherAnims.Length == 0) | ||
278 | return true; // the common case | ||
279 | if (thisAnims.Length == otherAnims.Length) | ||
280 | { | ||
281 | // Do this the hard way but since the list is usually short this won't take long. | ||
282 | foreach (OpenSim.Framework.Animation thisAnim in thisAnims) | ||
283 | { | ||
284 | bool found = false; | ||
285 | foreach (OpenSim.Framework.Animation otherAnim in otherAnims) | ||
286 | { | ||
287 | if (thisAnim.Equals(otherAnim)) | ||
288 | { | ||
289 | found = true; | ||
290 | break; | ||
291 | } | ||
292 | } | ||
293 | if (!found) | ||
294 | { | ||
295 | // If anything is not in the other list, these are not equal | ||
296 | return false; | ||
297 | } | ||
298 | } | ||
299 | // Found everything in the other list. Since lists are equal length, they must be equal. | ||
300 | return true; | ||
301 | } | ||
302 | } | ||
303 | return false; | ||
304 | } | ||
305 | // Don't know what was passed, but the base system will figure it out for me. | ||
306 | return base.Equals(obj); | ||
307 | } | ||
308 | |||
309 | public override string ToString() | ||
310 | { | ||
311 | StringBuilder buff = new StringBuilder(); | ||
312 | buff.Append("dflt="); | ||
313 | buff.Append(DefaultAnimation.ToString()); | ||
314 | buff.Append(",iDflt="); | ||
315 | if (DefaultAnimation.Equals(ImplicitDefaultAnimation)) | ||
316 | buff.Append("same"); | ||
317 | else | ||
318 | buff.Append(ImplicitDefaultAnimation.ToString()); | ||
319 | if (m_animations.Count > 0) | ||
320 | { | ||
321 | buff.Append(",anims="); | ||
322 | bool firstTime = true; | ||
323 | foreach (OpenSim.Framework.Animation anim in m_animations) | ||
324 | { | ||
325 | if (!firstTime) | ||
326 | buff.Append(","); | ||
327 | buff.Append("<"); | ||
328 | buff.Append(anim.ToString()); | ||
329 | buff.Append(">"); | ||
330 | firstTime = false; | ||
331 | } | ||
332 | } | ||
333 | return buff.ToString(); | ||
334 | } | ||
221 | } | 335 | } |
222 | } | 336 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs index c2b0468..b79dd8f 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs | |||
@@ -104,5 +104,31 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
104 | 104 | ||
105 | return UUID.Zero; | 105 | return UUID.Zero; |
106 | } | 106 | } |
107 | |||
108 | /// <summary> | ||
109 | /// Get the name of the animation given a UUID. If there is no matching animation | ||
110 | /// return the UUID as a string. | ||
111 | /// </summary> | ||
112 | public static string GetDefaultAnimationName(UUID uuid) | ||
113 | { | ||
114 | string ret = "unknown"; | ||
115 | if (AnimsUUID.ContainsValue(uuid)) | ||
116 | { | ||
117 | foreach (KeyValuePair<string, UUID> kvp in AnimsUUID) | ||
118 | { | ||
119 | if (kvp.Value == uuid) | ||
120 | { | ||
121 | ret = kvp.Key; | ||
122 | break; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | ret = uuid.ToString(); | ||
129 | } | ||
130 | |||
131 | return ret; | ||
132 | } | ||
107 | } | 133 | } |
108 | } \ No newline at end of file | 134 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 65c279e..c1394aa 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -93,7 +93,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
93 | GetAnimName(animID), animID, m_scenePresence.Name); | 93 | GetAnimName(animID), animID, m_scenePresence.Name); |
94 | 94 | ||
95 | if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) | 95 | if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) |
96 | { | ||
96 | SendAnimPack(); | 97 | SendAnimPack(); |
98 | m_scenePresence.TriggerScenePresenceUpdated(); | ||
99 | } | ||
97 | } | 100 | } |
98 | 101 | ||
99 | // Called from scripts | 102 | // Called from scripts |
@@ -132,7 +135,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
132 | GetAnimName(animID), animID, m_scenePresence.Name); | 135 | GetAnimName(animID), animID, m_scenePresence.Name); |
133 | 136 | ||
134 | if (m_animations.Remove(animID, allowNoDefault)) | 137 | if (m_animations.Remove(animID, allowNoDefault)) |
138 | { | ||
135 | SendAnimPack(); | 139 | SendAnimPack(); |
140 | m_scenePresence.TriggerScenePresenceUpdated(); | ||
141 | } | ||
136 | } | 142 | } |
137 | 143 | ||
138 | public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) | 144 | public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) |
@@ -180,8 +186,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
180 | /// The movement animation is reserved for "main" animations | 186 | /// The movement animation is reserved for "main" animations |
181 | /// that are mutually exclusive, e.g. flying and sitting. | 187 | /// that are mutually exclusive, e.g. flying and sitting. |
182 | /// </summary> | 188 | /// </summary> |
183 | public void TrySetMovementAnimation(string anim) | 189 | /// <returns>'true' if the animation was updated</returns> |
190 | public bool TrySetMovementAnimation(string anim) | ||
184 | { | 191 | { |
192 | bool ret = false; | ||
185 | if (!m_scenePresence.IsChildAgent) | 193 | if (!m_scenePresence.IsChildAgent) |
186 | { | 194 | { |
187 | // m_log.DebugFormat( | 195 | // m_log.DebugFormat( |
@@ -198,6 +206,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
198 | // 16384 is CHANGED_ANIMATION | 206 | // 16384 is CHANGED_ANIMATION |
199 | m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); | 207 | m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); |
200 | SendAnimPack(); | 208 | SendAnimPack(); |
209 | ret = true; | ||
201 | } | 210 | } |
202 | } | 211 | } |
203 | else | 212 | else |
@@ -206,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
206 | "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", | 215 | "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", |
207 | anim, m_scenePresence.Name); | 216 | anim, m_scenePresence.Name); |
208 | } | 217 | } |
218 | return ret; | ||
209 | } | 219 | } |
210 | 220 | ||
211 | /// <summary> | 221 | /// <summary> |
@@ -410,11 +420,18 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
410 | Falling = false; | 420 | Falling = false; |
411 | // Walking / crouchwalking / running | 421 | // Walking / crouchwalking / running |
412 | if (move.Z < 0f) | 422 | if (move.Z < 0f) |
423 | { | ||
413 | return "CROUCHWALK"; | 424 | return "CROUCHWALK"; |
414 | else if (m_scenePresence.SetAlwaysRun) | 425 | } |
415 | return "RUN"; | 426 | // We need to prevent these animations if the user tries to make their avatar walk or run whilst |
416 | else | 427 | // specifying AGENT_CONTROL_STOP (pressing down space on viewers). |
417 | return "WALK"; | 428 | else if (!m_scenePresence.AgentControlStopActive) |
429 | { | ||
430 | if (m_scenePresence.SetAlwaysRun) | ||
431 | return "RUN"; | ||
432 | else | ||
433 | return "WALK"; | ||
434 | } | ||
418 | } | 435 | } |
419 | else if (!m_jumping) | 436 | else if (!m_jumping) |
420 | { | 437 | { |
@@ -439,8 +456,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
439 | /// <summary> | 456 | /// <summary> |
440 | /// Update the movement animation of this avatar according to its current state | 457 | /// Update the movement animation of this avatar according to its current state |
441 | /// </summary> | 458 | /// </summary> |
442 | public void UpdateMovementAnimations() | 459 | /// <returns>'true' if the animation was changed</returns> |
460 | public bool UpdateMovementAnimations() | ||
443 | { | 461 | { |
462 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name); | ||
463 | |||
464 | bool ret = false; | ||
444 | lock (m_animations) | 465 | lock (m_animations) |
445 | { | 466 | { |
446 | string newMovementAnimation = DetermineMovementAnimation(); | 467 | string newMovementAnimation = DetermineMovementAnimation(); |
@@ -454,9 +475,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
454 | 475 | ||
455 | // Only set it if it's actually changed, give a script | 476 | // Only set it if it's actually changed, give a script |
456 | // a chance to stop a default animation | 477 | // a chance to stop a default animation |
457 | TrySetMovementAnimation(CurrentMovementAnimation); | 478 | ret = TrySetMovementAnimation(CurrentMovementAnimation); |
458 | } | 479 | } |
459 | } | 480 | } |
481 | return ret; | ||
460 | } | 482 | } |
461 | 483 | ||
462 | public UUID[] GetAnimationArray() | 484 | public UUID[] GetAnimationArray() |
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index f555b49..11a0146 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs | |||
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
104 | // better than losing the object for now. | 104 | // better than losing the object for now. |
105 | if (permissionToDelete) | 105 | if (permissionToDelete) |
106 | { | 106 | { |
107 | List<uint> killIDs = new List<uint>(); | ||
108 | |||
109 | foreach (SceneObjectGroup g in objectGroups) | 107 | foreach (SceneObjectGroup g in objectGroups) |
110 | { killIDs.Add(g.LocalId); | 108 | g.DeleteGroupFromScene(false); |
111 | g.DeleteGroupFromScene(true); | ||
112 | } | ||
113 | |||
114 | m_scene.SendKillObject(killIDs); | ||
115 | } | 109 | } |
116 | } | 110 | } |
117 | 111 | ||
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
160 | if (x.permissionToDelete) | 154 | if (x.permissionToDelete) |
161 | { | 155 | { |
162 | foreach (SceneObjectGroup g in x.objectGroups) | 156 | foreach (SceneObjectGroup g in x.objectGroups) |
163 | m_scene.DeleteSceneObject(g, false); | 157 | m_scene.DeleteSceneObject(g, true); |
164 | } | 158 | } |
165 | } | 159 | } |
166 | catch (Exception e) | 160 | catch (Exception e) |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 4733547..7f06e82 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 | ||
@@ -2160,7 +2172,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2160 | } | 2172 | } |
2161 | } | 2173 | } |
2162 | 2174 | ||
2163 | public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) | 2175 | public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel) |
2164 | { | 2176 | { |
2165 | NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; | 2177 | NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; |
2166 | if (handlerNewInventoryItemUpdateComplete != null) | 2178 | if (handlerNewInventoryItemUpdateComplete != null) |
@@ -2169,7 +2181,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2169 | { | 2181 | { |
2170 | try | 2182 | try |
2171 | { | 2183 | { |
2172 | d(agentID, AssetID, AssetName, userlevel); | 2184 | d(agentID, type, AssetID, AssetName, userlevel); |
2173 | } | 2185 | } |
2174 | catch (Exception e) | 2186 | catch (Exception e) |
2175 | { | 2187 | { |
@@ -3096,6 +3108,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
3096 | } | 3108 | } |
3097 | } | 3109 | } |
3098 | 3110 | ||
3111 | public void TriggerRegionHeartbeatStart(Scene scene) | ||
3112 | { | ||
3113 | RegionHeartbeatStart handler = OnRegionHeartbeatStart; | ||
3114 | |||
3115 | if (handler != null) | ||
3116 | { | ||
3117 | foreach (RegionHeartbeatStart d in handler.GetInvocationList()) | ||
3118 | { | ||
3119 | try | ||
3120 | { | ||
3121 | d(scene); | ||
3122 | } | ||
3123 | catch (Exception e) | ||
3124 | { | ||
3125 | m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}", | ||
3126 | e.Message, e.StackTrace); | ||
3127 | } | ||
3128 | } | ||
3129 | } | ||
3130 | } | ||
3131 | |||
3099 | public void TriggerRegionHeartbeatEnd(Scene scene) | 3132 | public void TriggerRegionHeartbeatEnd(Scene scene) |
3100 | { | 3133 | { |
3101 | RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; | 3134 | RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; |
@@ -3251,5 +3284,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
3251 | handler(scenePresence); | 3284 | handler(scenePresence); |
3252 | } | 3285 | } |
3253 | } | 3286 | } |
3287 | |||
3288 | // public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids) | ||
3289 | // { | ||
3290 | // GatherUuids handler = OnGatherUuids; | ||
3291 | // | ||
3292 | // if (handler != null) | ||
3293 | // { | ||
3294 | // foreach (GatherUuids d in handler.GetInvocationList()) | ||
3295 | // { | ||
3296 | // try | ||
3297 | // { | ||
3298 | // d(sop, assetUuids); | ||
3299 | // } | ||
3300 | // catch (Exception e) | ||
3301 | // { | ||
3302 | // m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}", | ||
3303 | // e.Message, e.StackTrace); | ||
3304 | // } | ||
3305 | // } | ||
3306 | // } | ||
3307 | // } | ||
3254 | } | 3308 | } |
3255 | } | 3309 | } |
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index f0e639d..49b71e5 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | |||
@@ -1,6 +1,29 @@ | |||
1 | // Proprietary code of Avination Virtual Limited | 1 | /* |
2 | // (c) 2012 Melanie Thielker | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | // | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
4 | 27 | ||
5 | using System; | 28 | using System; |
6 | using System.Timers; | 29 | using System.Timers; |
@@ -32,7 +55,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
32 | private object m_lockObject = new object(); | 55 | private object m_lockObject = new object(); |
33 | private object m_timerLock = new object(); | 56 | private object m_timerLock = new object(); |
34 | private const double m_tickDuration = 50.0; | 57 | private const double m_tickDuration = 50.0; |
35 | private Scene m_scene; | ||
36 | 58 | ||
37 | public double TickDuration | 59 | public double TickDuration |
38 | { | 60 | { |
@@ -46,8 +68,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
46 | m_timer.AutoReset = true; | 68 | m_timer.AutoReset = true; |
47 | m_timer.Elapsed += OnTimer; | 69 | m_timer.Elapsed += OnTimer; |
48 | 70 | ||
49 | m_scene = scene; | ||
50 | |||
51 | m_timer.Start(); | 71 | m_timer.Start(); |
52 | } | 72 | } |
53 | 73 | ||
@@ -71,13 +91,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
71 | { | 91 | { |
72 | m.OnTimer(TickDuration); | 92 | m.OnTimer(TickDuration); |
73 | } | 93 | } |
74 | catch (Exception inner) | 94 | catch (Exception) |
75 | { | 95 | { |
76 | // Don't stop processing | 96 | // Don't stop processing |
77 | } | 97 | } |
78 | } | 98 | } |
79 | } | 99 | } |
80 | catch (Exception e) | 100 | catch (Exception) |
81 | { | 101 | { |
82 | // Keep running no matter what | 102 | // Keep running no matter what |
83 | } | 103 | } |
@@ -134,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
134 | [Serializable] | 154 | [Serializable] |
135 | public class KeyframeMotion | 155 | public class KeyframeMotion |
136 | { | 156 | { |
137 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 157 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
138 | 158 | ||
139 | public enum PlayMode : int | 159 | public enum PlayMode : int |
140 | { | 160 | { |
@@ -500,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
500 | k.Position = pos; | 520 | k.Position = pos; |
501 | // k.Velocity = Vector3.Zero; | 521 | // k.Velocity = Vector3.Zero; |
502 | } | 522 | } |
523 | k.AngularVelocity = (Vector3)k.Position; | ||
503 | 524 | ||
504 | k.StartRotation = rot; | 525 | k.StartRotation = rot; |
505 | if (k.Rotation.HasValue) | 526 | if (k.Rotation.HasValue) |
@@ -668,7 +689,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
668 | m_group.RootPart.Velocity = Vector3.Zero; | 689 | m_group.RootPart.Velocity = Vector3.Zero; |
669 | m_group.RootPart.AngularVelocity = Vector3.Zero; | 690 | m_group.RootPart.AngularVelocity = Vector3.Zero; |
670 | 691 | ||
671 | m_nextPosition = (Vector3)m_currentFrame.Position; | 692 | m_nextPosition = NormalizeVector(m_currentFrame.AngularVelocity); |
672 | m_group.AbsolutePosition = m_nextPosition; | 693 | m_group.AbsolutePosition = m_nextPosition; |
673 | 694 | ||
674 | // we are sending imediate updates, no doing force a extra terseUpdate | 695 | // we are sending imediate updates, no doing force a extra terseUpdate |
@@ -755,7 +776,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
755 | m_group.SendGroupRootTerseUpdate(); | 776 | m_group.SendGroupRootTerseUpdate(); |
756 | } | 777 | } |
757 | } | 778 | } |
779 | private Vector3 NormalizeVector(Vector3? pPosition) | ||
780 | { | ||
781 | if (pPosition == null) | ||
782 | return Vector3.Zero; | ||
783 | |||
784 | Vector3 tmp = (Vector3) pPosition; | ||
758 | 785 | ||
786 | while (tmp.X > Constants.RegionSize) | ||
787 | tmp.X -= Constants.RegionSize; | ||
788 | while (tmp.X < 0) | ||
789 | tmp.X += Constants.RegionSize; | ||
790 | while (tmp.Y > Constants.RegionSize) | ||
791 | tmp.Y -= Constants.RegionSize; | ||
792 | while (tmp.Y < 0) | ||
793 | tmp.Y += Constants.RegionSize; | ||
794 | |||
795 | return tmp; | ||
796 | |||
797 | |||
798 | } | ||
759 | public Byte[] Serialize() | 799 | public Byte[] Serialize() |
760 | { | 800 | { |
761 | StopTimer(); | 801 | StopTimer(); |
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs index c11174d..f208afb 100644 --- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs +++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs | |||
@@ -46,47 +46,33 @@ using OpenSim.Region.Framework.Scenes; | |||
46 | 46 | ||
47 | namespace OpenSim.Region.Framework.Scenes | 47 | namespace OpenSim.Region.Framework.Scenes |
48 | { | 48 | { |
49 | public class RegionStatsHandler : IStreamedRequestHandler | 49 | public class RegionStatsHandler : BaseStreamHandler |
50 | { | 50 | { |
51 | //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | 52 | ||
53 | private string osRXStatsURI = String.Empty; | ||
54 | private string osXStatsURI = String.Empty; | 53 | private string osXStatsURI = String.Empty; |
55 | //private string osSecret = String.Empty; | 54 | //private string osSecret = String.Empty; |
56 | private OpenSim.Framework.RegionInfo regionInfo; | 55 | private OpenSim.Framework.RegionInfo regionInfo; |
57 | public string localZone = TimeZone.CurrentTimeZone.StandardName; | 56 | public string localZone = TimeZone.CurrentTimeZone.StandardName; |
58 | public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); | 57 | public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); |
59 | 58 | ||
60 | public string Name { get { return "RegionStats"; } } | 59 | public RegionStatsHandler(RegionInfo region_info) |
61 | public string Description { get { return "Region Statistics"; } } | 60 | : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics") |
62 | |||
63 | public RegionStatsHandler(RegionInfo region_info) | ||
64 | { | 61 | { |
65 | regionInfo = region_info; | 62 | regionInfo = region_info; |
66 | osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret); | ||
67 | osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); | 63 | osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); |
68 | } | 64 | } |
69 | 65 | ||
70 | public byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | 66 | protected override byte[] ProcessRequest( |
67 | string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | ||
71 | { | 68 | { |
72 | return Util.UTF8.GetBytes(Report()); | 69 | return Util.UTF8.GetBytes(Report()); |
73 | } | 70 | } |
74 | 71 | ||
75 | public string ContentType | 72 | public override string ContentType |
76 | { | 73 | { |
77 | get { return "text/plain"; } | 74 | get { return "text/plain"; } |
78 | } | 75 | } |
79 | |||
80 | public string HttpMethod | ||
81 | { | ||
82 | get { return "GET"; } | ||
83 | } | ||
84 | |||
85 | public string Path | ||
86 | { | ||
87 | // This is for the region and is the regionSecret hashed | ||
88 | get { return "/" + osRXStatsURI; } | ||
89 | } | ||
90 | 76 | ||
91 | private string Report() | 77 | private string Report() |
92 | { | 78 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index d2e41f8..d87091c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -31,6 +31,7 @@ using System.Collections; | |||
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Text; | 32 | using System.Text; |
33 | using System.Timers; | 33 | using System.Timers; |
34 | using System.Xml; | ||
34 | using OpenMetaverse; | 35 | using OpenMetaverse; |
35 | using OpenMetaverse.Packets; | 36 | using OpenMetaverse.Packets; |
36 | using log4net; | 37 | using log4net; |
@@ -139,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
139 | { | 140 | { |
140 | userlevel = 1; | 141 | userlevel = 1; |
141 | } | 142 | } |
142 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); | 143 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel); |
143 | 144 | ||
144 | return true; | 145 | return true; |
145 | } | 146 | } |
@@ -178,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
178 | { | 179 | { |
179 | userlevel = 1; | 180 | userlevel = 1; |
180 | } | 181 | } |
181 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); | 182 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel); |
182 | 183 | ||
183 | if (originalFolder != UUID.Zero) | 184 | if (originalFolder != UUID.Zero) |
184 | { | 185 | { |
@@ -411,19 +412,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
411 | // itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, | 412 | // itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, |
412 | // item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); | 413 | // item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); |
413 | 414 | ||
415 | bool sendUpdate = false; | ||
416 | |||
414 | if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid | 417 | if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid |
415 | { | 418 | { |
416 | // Create a set of base permissions that will not include export if the user | 419 | // Create a set of base permissions that will not include export if the user |
417 | // is not allowed to change the export flag. | 420 | // is not allowed to change the export flag. |
418 | bool denyExportChange = false; | 421 | bool denyExportChange = false; |
419 | 422 | ||
420 | m_log.InfoFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); | 423 | // m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); |
421 | 424 | ||
422 | // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export | 425 | // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export |
423 | if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) | 426 | if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) |
424 | denyExportChange = true; | 427 | denyExportChange = true; |
425 | 428 | ||
426 | m_log.InfoFormat("[XXX]: Deny Export Update {0}", denyExportChange); | 429 | // m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange); |
427 | 430 | ||
428 | // If it is already set, force it set and also force full perm | 431 | // If it is already set, force it set and also force full perm |
429 | // else prevent setting it. It can and should never be set unless | 432 | // else prevent setting it. It can and should never be set unless |
@@ -447,7 +450,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
447 | // If the new state is exportable, force full perm | 450 | // If the new state is exportable, force full perm |
448 | if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) | 451 | if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) |
449 | { | 452 | { |
450 | m_log.InfoFormat("[XXX]: Force full perm"); | 453 | // m_log.DebugFormat("[XXX]: Force full perm"); |
451 | itemUpd.NextPermissions = (uint)(PermissionMask.All); | 454 | itemUpd.NextPermissions = (uint)(PermissionMask.All); |
452 | } | 455 | } |
453 | } | 456 | } |
@@ -484,8 +487,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
484 | item.SalePrice = itemUpd.SalePrice; | 487 | item.SalePrice = itemUpd.SalePrice; |
485 | item.SaleType = itemUpd.SaleType; | 488 | item.SaleType = itemUpd.SaleType; |
486 | 489 | ||
490 | if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0) | ||
491 | { | ||
492 | item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf); | ||
493 | sendUpdate = true; | ||
494 | } | ||
495 | |||
487 | InventoryService.UpdateItem(item); | 496 | InventoryService.UpdateItem(item); |
488 | remoteClient.SendBulkUpdateInventory(item); | ||
489 | } | 497 | } |
490 | 498 | ||
491 | if (UUID.Zero != transactionID) | 499 | if (UUID.Zero != transactionID) |
@@ -495,6 +503,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
495 | AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); | 503 | AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); |
496 | } | 504 | } |
497 | } | 505 | } |
506 | else | ||
507 | { | ||
508 | // This MAY be problematic, if it is, another solution | ||
509 | // needs to be found. If inventory item flags are updated | ||
510 | // the viewer's notion of the item needs to be refreshed. | ||
511 | // | ||
512 | // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start | ||
513 | // failing frequently. Possibly this is a race with a separate transaction that uploads the asset. | ||
514 | if (sendUpdate) | ||
515 | remoteClient.SendBulkUpdateInventory(item); | ||
516 | } | ||
498 | } | 517 | } |
499 | else | 518 | else |
500 | { | 519 | { |
@@ -548,6 +567,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
548 | { | 567 | { |
549 | //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); | 568 | //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); |
550 | 569 | ||
570 | if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient)) | ||
571 | return null; | ||
572 | |||
551 | InventoryItemBase item = new InventoryItemBase(itemId, senderId); | 573 | InventoryItemBase item = new InventoryItemBase(itemId, senderId); |
552 | item = InventoryService.GetItem(item); | 574 | item = InventoryService.GetItem(item); |
553 | 575 | ||
@@ -642,17 +664,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
642 | // a mask | 664 | // a mask |
643 | if (item.InvType == (int)InventoryType.Object) | 665 | if (item.InvType == (int)InventoryType.Object) |
644 | { | 666 | { |
645 | // Create a safe mask for the current perms | ||
646 | uint foldedPerms = (item.CurrentPermissions & 7) << 13; | ||
647 | foldedPerms |= permsMask; | ||
648 | |||
649 | bool isRootMod = (item.CurrentPermissions & | 667 | bool isRootMod = (item.CurrentPermissions & |
650 | (uint)PermissionMask.Modify) != 0 ? | 668 | (uint)PermissionMask.Modify) != 0 ? |
651 | true : false; | 669 | true : false; |
652 | 670 | ||
653 | // Mask the owner perms to the folded perms | 671 | // Mask the owner perms to the folded perms |
654 | ownerPerms &= foldedPerms; | 672 | PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms); |
655 | basePerms &= foldedPerms; | 673 | PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms); |
656 | 674 | ||
657 | // If the root was mod, let the mask reflect that | 675 | // If the root was mod, let the mask reflect that |
658 | // We also need to adjust the base here, because | 676 | // We also need to adjust the base here, because |
@@ -1213,9 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1213 | { | 1231 | { |
1214 | agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); | 1232 | agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); |
1215 | if (taskItem.InvType == (int)InventoryType.Object) | 1233 | if (taskItem.InvType == (int)InventoryType.Object) |
1216 | agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); | 1234 | { |
1235 | uint perms = taskItem.CurrentPermissions; | ||
1236 | PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms); | ||
1237 | agentItem.BasePermissions = perms | (uint)PermissionMask.Move; | ||
1238 | agentItem.CurrentPermissions = agentItem.BasePermissions; | ||
1239 | } | ||
1217 | else | 1240 | else |
1241 | { | ||
1218 | agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; | 1242 | agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; |
1243 | } | ||
1219 | 1244 | ||
1220 | agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; | 1245 | agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; |
1221 | agentItem.NextPermissions = taskItem.NextPermissions; | 1246 | agentItem.NextPermissions = taskItem.NextPermissions; |
@@ -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,87 @@ 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 | if (!attachment) | ||
2336 | { | ||
2337 | g.RootPart.AttachPoint = g.RootPart.Shape.State; | ||
2338 | g.RootPart.AttachOffset = g.AbsolutePosition; | ||
2339 | g.RootPart.AttachRotation = g.GroupRotation; | ||
2340 | if (g.RootPart.Shape.PCode != (byte)PCode.NewTree && | ||
2341 | g.RootPart.Shape.PCode != (byte)PCode.Tree) | ||
2342 | g.RootPart.Shape.State = 0; | ||
2343 | } | ||
2344 | |||
2345 | objlist.Add(g); | ||
2346 | veclist.Add(new Vector3(0, 0, 0)); | ||
2347 | bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); | ||
2348 | return true; | ||
2349 | } | ||
2350 | else | ||
2351 | { | ||
2352 | XmlElement coll = (XmlElement)e; | ||
2353 | float bx = Convert.ToSingle(coll.GetAttribute("x")); | ||
2354 | float by = Convert.ToSingle(coll.GetAttribute("y")); | ||
2355 | float bz = Convert.ToSingle(coll.GetAttribute("z")); | ||
2356 | bbox = new Vector3(bx, by, bz); | ||
2357 | offsetHeight = 0; | ||
2358 | |||
2359 | XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); | ||
2360 | foreach (XmlNode n in groups) | ||
2361 | { | ||
2362 | SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); | ||
2363 | |||
2364 | g.RootPart.AttachPoint = g.RootPart.Shape.State; | ||
2365 | g.RootPart.AttachOffset = g.AbsolutePosition; | ||
2366 | g.RootPart.AttachRotation = g.GroupRotation; | ||
2367 | if (g.RootPart.Shape.PCode != (byte)PCode.NewTree && | ||
2368 | g.RootPart.Shape.PCode != (byte)PCode.Tree) | ||
2369 | g.RootPart.Shape.State = 0; | ||
2370 | |||
2371 | objlist.Add(g); | ||
2372 | |||
2373 | XmlElement el = (XmlElement)n; | ||
2374 | string rawX = el.GetAttribute("offsetx"); | ||
2375 | string rawY = el.GetAttribute("offsety"); | ||
2376 | string rawZ = el.GetAttribute("offsetz"); | ||
2377 | |||
2378 | float x = Convert.ToSingle(rawX); | ||
2379 | float y = Convert.ToSingle(rawY); | ||
2380 | float z = Convert.ToSingle(rawZ); | ||
2381 | veclist.Add(new Vector3(x, y, z)); | ||
2382 | } | ||
2383 | } | ||
2384 | |||
2385 | return false; | ||
2386 | } | ||
2387 | |||
2388 | /// <summary> | ||
2280 | /// Event Handler Rez an object into a scene | 2389 | /// Event Handler Rez an object into a scene |
2281 | /// Calls the non-void event handler | 2390 | /// Calls the non-void event handler |
2282 | /// </summary> | 2391 | /// </summary> |
@@ -2351,19 +2460,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
2351 | /// will be used if it exists.</param> | 2460 | /// will be used if it exists.</param> |
2352 | /// <param name="vel">The velocity of the rezzed object.</param> | 2461 | /// <param name="vel">The velocity of the rezzed object.</param> |
2353 | /// <param name="param"></param> | 2462 | /// <param name="param"></param> |
2354 | /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> | 2463 | /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns> |
2355 | public virtual SceneObjectGroup RezObject( | 2464 | public virtual List<SceneObjectGroup> RezObject( |
2356 | SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) | 2465 | SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) |
2357 | { | 2466 | { |
2358 | if (null == item) | 2467 | if (null == item) |
2359 | return null; | 2468 | return null; |
2469 | |||
2470 | List<SceneObjectGroup> objlist; | ||
2471 | List<Vector3> veclist; | ||
2360 | 2472 | ||
2361 | SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); | 2473 | bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); |
2362 | 2474 | if (!success) | |
2363 | if (null == group) | ||
2364 | return null; | 2475 | return null; |
2365 | 2476 | ||
2366 | if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) | 2477 | int totalPrims = 0; |
2478 | foreach (SceneObjectGroup group in objlist) | ||
2479 | totalPrims += group.PrimCount; | ||
2480 | |||
2481 | if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos)) | ||
2367 | return null; | 2482 | return null; |
2368 | 2483 | ||
2369 | if (!Permissions.BypassPermissions()) | 2484 | if (!Permissions.BypassPermissions()) |
@@ -2372,16 +2487,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
2372 | sourcePart.Inventory.RemoveInventoryItem(item.ItemID); | 2487 | sourcePart.Inventory.RemoveInventoryItem(item.ItemID); |
2373 | } | 2488 | } |
2374 | 2489 | ||
2375 | group.FromPartID = sourcePart.UUID; | 2490 | for (int i = 0; i < objlist.Count; i++) |
2376 | AddNewSceneObject(group, true, pos, rot, vel); | 2491 | { |
2377 | 2492 | SceneObjectGroup group = objlist[i]; | |
2378 | // We can only call this after adding the scene object, since the scene object references the scene | 2493 | Vector3 curpos = pos + veclist[i]; |
2379 | // to find out if scripts should be activated at all. | 2494 | |
2380 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); | 2495 | if (group.IsAttachment == false && group.RootPart.Shape.State != 0) |
2381 | 2496 | { | |
2382 | group.ScheduleGroupForFullUpdate(); | 2497 | group.RootPart.AttachedPos = group.AbsolutePosition; |
2383 | 2498 | group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; | |
2384 | return group; | 2499 | } |
2500 | |||
2501 | group.FromPartID = sourcePart.UUID; | ||
2502 | AddNewSceneObject(group, true, curpos, rot, vel); | ||
2503 | |||
2504 | // We can only call this after adding the scene object, since the scene object references the scene | ||
2505 | // to find out if scripts should be activated at all. | ||
2506 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); | ||
2507 | |||
2508 | group.ScheduleGroupForFullUpdate(); | ||
2509 | } | ||
2510 | |||
2511 | return objlist; | ||
2385 | } | 2512 | } |
2386 | 2513 | ||
2387 | public virtual bool returnObjects(SceneObjectGroup[] returnobjects, | 2514 | public virtual bool returnObjects(SceneObjectGroup[] returnobjects, |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ce6415a..46b2d2e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | |||
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
252 | if (part.ParentGroup.RootPart.LocalId != part.LocalId) | 252 | if (part.ParentGroup.RootPart.LocalId != part.LocalId) |
253 | return; | 253 | return; |
254 | 254 | ||
255 | bool isAttachment = false; | ||
256 | |||
257 | // This is wrong, wrong, wrong. Selection should not be | 255 | // This is wrong, wrong, wrong. Selection should not be |
258 | // handled by group, but by prim. Legacy cruft. | 256 | // handled by group, but by prim. Legacy cruft. |
259 | // TODO: Make selection flagging per prim! | 257 | // TODO: Make selection flagging per prim! |
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
262 | || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 260 | || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) |
263 | part.ParentGroup.IsSelected = false; | 261 | part.ParentGroup.IsSelected = false; |
264 | 262 | ||
265 | if (part.ParentGroup.IsAttachment) | 263 | part.ParentGroup.ScheduleGroupForFullUpdate(); |
266 | isAttachment = true; | ||
267 | else | ||
268 | part.ParentGroup.ScheduleGroupForFullUpdate(); | ||
269 | 264 | ||
270 | // If it's not an attachment, and we are allowed to move it, | 265 | // If it's not an attachment, and we are allowed to move it, |
271 | // then we might have done so. If we moved across a parcel | 266 | // then we might have done so. If we moved across a parcel |
272 | // boundary, we will need to recount prims on the parcels. | 267 | // boundary, we will need to recount prims on the parcels. |
273 | // For attachments, that makes no sense. | 268 | // For attachments, that makes no sense. |
274 | // | 269 | // |
275 | if (!isAttachment) | 270 | if (!part.ParentGroup.IsAttachment) |
276 | { | 271 | { |
277 | if (Permissions.CanEditObject( | 272 | if (Permissions.CanEditObject( |
278 | part.UUID, remoteClient.AgentId) | 273 | part.UUID, remoteClient.AgentId) |
@@ -416,6 +411,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
416 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) | 411 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) |
417 | { | 412 | { |
418 | // TODO: don't create new blocks if recycling an old packet | 413 | // TODO: don't create new blocks if recycling an old packet |
414 | bool discardableEffects = true; | ||
419 | ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; | 415 | ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; |
420 | for (int i = 0; i < args.Count; i++) | 416 | for (int i = 0; i < args.Count; i++) |
421 | { | 417 | { |
@@ -427,17 +423,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
427 | effect.Type = args[i].Type; | 423 | effect.Type = args[i].Type; |
428 | effect.TypeData = args[i].TypeData; | 424 | effect.TypeData = args[i].TypeData; |
429 | effectBlockArray[i] = effect; | 425 | effectBlockArray[i] = effect; |
426 | |||
427 | if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam) | ||
428 | discardableEffects = false; | ||
429 | |||
430 | //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type); | ||
430 | } | 431 | } |
431 | 432 | ||
432 | ForEachClient( | 433 | ForEachScenePresence(sp => |
433 | delegate(IClientAPI client) | ||
434 | { | 434 | { |
435 | if (client.AgentId != remoteClient.AgentId) | 435 | if (sp.ControllingClient.AgentId != remoteClient.AgentId) |
436 | client.SendViewerEffect(effectBlockArray); | 436 | { |
437 | } | 437 | if (!discardableEffects || |
438 | ); | 438 | (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp))) |
439 | { | ||
440 | //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID); | ||
441 | sp.ControllingClient.SendViewerEffect(effectBlockArray); | ||
442 | } | ||
443 | //else | ||
444 | // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID); | ||
445 | } | ||
446 | }); | ||
439 | } | 447 | } |
440 | 448 | ||
449 | private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other) | ||
450 | { | ||
451 | return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; | ||
452 | } | ||
453 | |||
441 | private class DescendentsRequestData | 454 | private class DescendentsRequestData |
442 | { | 455 | { |
443 | public IClientAPI RemoteClient; | 456 | public IClientAPI RemoteClient; |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b189599..55766cf 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
151 | public SynchronizeSceneHandler SynchronizeScene; | 151 | public SynchronizeSceneHandler SynchronizeScene; |
152 | 152 | ||
153 | /// <summary> | 153 | /// <summary> |
154 | /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. | 154 | /// Used to prevent simultaneous calls to code that adds and removes agents. |
155 | /// </summary> | 155 | /// </summary> |
156 | private object m_removeClientLock = new object(); | 156 | private object m_removeClientLock = new object(); |
157 | 157 | ||
@@ -230,6 +230,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
230 | public bool m_seeIntoBannedRegion = false; | 230 | public bool m_seeIntoBannedRegion = false; |
231 | public int MaxUndoCount = 5; | 231 | public int MaxUndoCount = 5; |
232 | 232 | ||
233 | public bool SeeIntoRegion { get; set; } | ||
234 | |||
233 | // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; | 235 | // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; |
234 | public bool LoginLock = false; | 236 | public bool LoginLock = false; |
235 | 237 | ||
@@ -396,10 +398,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
396 | if (value) | 398 | if (value) |
397 | { | 399 | { |
398 | if (!m_active) | 400 | if (!m_active) |
399 | Start(); | 401 | Start(false); |
400 | } | 402 | } |
401 | else | 403 | else |
402 | { | 404 | { |
405 | // This appears assymetric with Start() above but is not - setting m_active = false stops the loops | ||
406 | // XXX: Possibly this should be in an explicit Stop() method for symmetry. | ||
403 | m_active = false; | 407 | m_active = false; |
404 | } | 408 | } |
405 | } | 409 | } |
@@ -747,6 +751,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
747 | m_config = config; | 751 | m_config = config; |
748 | MinFrameTime = 0.089f; | 752 | MinFrameTime = 0.089f; |
749 | MinMaintenanceTime = 1; | 753 | MinMaintenanceTime = 1; |
754 | SeeIntoRegion = true; | ||
750 | 755 | ||
751 | Random random = new Random(); | 756 | Random random = new Random(); |
752 | 757 | ||
@@ -859,9 +864,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
859 | //Animation states | 864 | //Animation states |
860 | m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); | 865 | m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); |
861 | 866 | ||
867 | SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion); | ||
868 | |||
869 | MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); | ||
870 | |||
862 | PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); | 871 | PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); |
863 | CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); | 872 | CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); |
864 | |||
865 | m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); | 873 | m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); |
866 | if (RegionInfo.NonphysPrimMin > 0) | 874 | if (RegionInfo.NonphysPrimMin > 0) |
867 | { | 875 | { |
@@ -1332,7 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1332 | Thread.Sleep(500); | 1340 | Thread.Sleep(500); |
1333 | 1341 | ||
1334 | // Stop all client threads. | 1342 | // Stop all client threads. |
1335 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); | 1343 | ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); |
1336 | 1344 | ||
1337 | m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); | 1345 | m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); |
1338 | EventManager.TriggerSceneShuttingDown(this); | 1346 | EventManager.TriggerSceneShuttingDown(this); |
@@ -1361,10 +1369,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1361 | } | 1369 | } |
1362 | } | 1370 | } |
1363 | 1371 | ||
1372 | public override void Start() | ||
1373 | { | ||
1374 | Start(true); | ||
1375 | } | ||
1376 | |||
1364 | /// <summary> | 1377 | /// <summary> |
1365 | /// Start the scene | 1378 | /// Start the scene |
1366 | /// </summary> | 1379 | /// </summary> |
1367 | public void Start() | 1380 | /// <param name='startScripts'> |
1381 | /// Start the scripts within the scene. | ||
1382 | /// </param> | ||
1383 | public void Start(bool startScripts) | ||
1368 | { | 1384 | { |
1369 | m_active = true; | 1385 | m_active = true; |
1370 | 1386 | ||
@@ -1401,6 +1417,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1401 | m_heartbeatThread | 1417 | m_heartbeatThread |
1402 | = Watchdog.StartThread( | 1418 | = Watchdog.StartThread( |
1403 | Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); | 1419 | Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); |
1420 | |||
1421 | StartScripts(); | ||
1404 | } | 1422 | } |
1405 | 1423 | ||
1406 | /// <summary> | 1424 | /// <summary> |
@@ -1557,6 +1575,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1557 | 1575 | ||
1558 | try | 1576 | try |
1559 | { | 1577 | { |
1578 | EventManager.TriggerRegionHeartbeatStart(this); | ||
1579 | |||
1560 | // Apply taints in terrain module to terrain in physics scene | 1580 | // Apply taints in terrain module to terrain in physics scene |
1561 | if (Frame % m_update_terrain == 0) | 1581 | if (Frame % m_update_terrain == 0) |
1562 | { | 1582 | { |
@@ -1996,6 +2016,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1996 | 2016 | ||
1997 | GridRegion region = new GridRegion(RegionInfo); | 2017 | GridRegion region = new GridRegion(RegionInfo); |
1998 | string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); | 2018 | string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); |
2019 | m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>", | ||
2020 | LogHeader, m_regionName, | ||
2021 | RegionInfo.RegionID, | ||
2022 | RegionInfo.RegionLocX, RegionInfo.RegionLocY, | ||
2023 | RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); | ||
1999 | if (error != String.Empty) | 2024 | if (error != String.Empty) |
2000 | throw new Exception(error); | 2025 | throw new Exception(error); |
2001 | } | 2026 | } |
@@ -2935,14 +2960,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2935 | 2960 | ||
2936 | #region Add/Remove Avatar Methods | 2961 | #region Add/Remove Avatar Methods |
2937 | 2962 | ||
2938 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2963 | public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) |
2939 | { | 2964 | { |
2940 | ScenePresence sp; | 2965 | ScenePresence sp; |
2941 | bool vialogin; | 2966 | bool vialogin; |
2967 | bool reallyNew = true; | ||
2942 | 2968 | ||
2943 | // Validation occurs in LLUDPServer | 2969 | // Validation occurs in LLUDPServer |
2944 | // | 2970 | // |
2945 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | 2971 | // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with |
2946 | // each other. In practice, this does not currently occur in the code. | 2972 | // each other. In practice, this does not currently occur in the code. |
2947 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2973 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2948 | 2974 | ||
@@ -2950,9 +2976,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2950 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point | 2976 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point |
2951 | // whilst connecting). | 2977 | // whilst connecting). |
2952 | // | 2978 | // |
2953 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and | 2979 | // It would be easier to lock across all NewUserConnection(), AddNewAgent() and |
2954 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | 2980 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service |
2955 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. | 2981 | // response in some module listening to AddNewAgent()) from holding up unrelated agent calls. |
2956 | // | 2982 | // |
2957 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all | 2983 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all |
2958 | // AddNewClient() operations (though not other ops). | 2984 | // AddNewClient() operations (though not other ops). |
@@ -2969,7 +2995,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2969 | 2995 | ||
2970 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 2996 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this |
2971 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause | 2997 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause |
2972 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 2998 | // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already |
2973 | // connected. | 2999 | // connected. |
2974 | if (sp == null) | 3000 | if (sp == null) |
2975 | { | 3001 | { |
@@ -2997,16 +3023,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2997 | m_log.WarnFormat( | 3023 | m_log.WarnFormat( |
2998 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | 3024 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", |
2999 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 3025 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); |
3026 | reallyNew = false; | ||
3000 | } | 3027 | } |
3001 | 3028 | ||
3002 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | 3029 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the |
3003 | // client is for a root or child agent. | 3030 | // client is for a root or child agent. |
3031 | // XXX: This may be better set for a new client before that client is added to the client manager. | ||
3032 | // But need to know what happens in the case where a ScenePresence is already present (and if this | ||
3033 | // actually occurs). | ||
3004 | client.SceneAgent = sp; | 3034 | client.SceneAgent = sp; |
3005 | 3035 | ||
3006 | // Cache the user's name | 3036 | // This is currently also being done earlier in NewUserConnection for real users to see if this |
3037 | // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other | ||
3038 | // places. However, we still need to do it here for NPCs. | ||
3007 | CacheUserName(sp, aCircuit); | 3039 | CacheUserName(sp, aCircuit); |
3008 | 3040 | ||
3009 | EventManager.TriggerOnNewClient(client); | 3041 | if (reallyNew) |
3042 | EventManager.TriggerOnNewClient(client); | ||
3043 | |||
3010 | if (vialogin) | 3044 | if (vialogin) |
3011 | EventManager.TriggerOnClientLogin(client); | 3045 | EventManager.TriggerOnClientLogin(client); |
3012 | } | 3046 | } |
@@ -3027,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3027 | { | 3061 | { |
3028 | string first = aCircuit.firstname, last = aCircuit.lastname; | 3062 | string first = aCircuit.firstname, last = aCircuit.lastname; |
3029 | 3063 | ||
3030 | if (sp.PresenceType == PresenceType.Npc) | 3064 | if (sp != null && sp.PresenceType == PresenceType.Npc) |
3031 | { | 3065 | { |
3032 | UserManagementModule.AddUser(aCircuit.AgentID, first, last); | 3066 | UserManagementModule.AddUser(aCircuit.AgentID, first, last); |
3033 | } | 3067 | } |
@@ -3105,7 +3139,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3105 | if (sp != null) | 3139 | if (sp != null) |
3106 | { | 3140 | { |
3107 | PresenceService.LogoutAgent(sp.ControllingClient.SessionId); | 3141 | PresenceService.LogoutAgent(sp.ControllingClient.SessionId); |
3108 | sp.ControllingClient.Close(); | 3142 | |
3143 | CloseAgent(sp.UUID, false); | ||
3109 | } | 3144 | } |
3110 | 3145 | ||
3111 | // BANG! SLASH! | 3146 | // BANG! SLASH! |
@@ -3244,8 +3279,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3244 | { | 3279 | { |
3245 | //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; | 3280 | //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; |
3246 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; | 3281 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; |
3247 | client.OnSetStartLocationRequest += SetHomeRezPoint; | ||
3248 | client.OnRegionHandleRequest += RegionHandleRequest; | ||
3249 | } | 3282 | } |
3250 | 3283 | ||
3251 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) | 3284 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) |
@@ -3371,8 +3404,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3371 | { | 3404 | { |
3372 | //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; | 3405 | //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; |
3373 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; | 3406 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; |
3374 | client.OnSetStartLocationRequest -= SetHomeRezPoint; | ||
3375 | client.OnRegionHandleRequest -= RegionHandleRequest; | ||
3376 | } | 3407 | } |
3377 | 3408 | ||
3378 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) | 3409 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) |
@@ -3498,33 +3529,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3498 | } | 3529 | } |
3499 | 3530 | ||
3500 | /// <summary> | 3531 | /// <summary> |
3501 | /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in | ||
3502 | /// </summary> | ||
3503 | /// <param name="remoteClient"></param> | ||
3504 | /// <param name="regionHandle"></param> | ||
3505 | /// <param name="position"></param> | ||
3506 | /// <param name="lookAt"></param> | ||
3507 | /// <param name="flags"></param> | ||
3508 | public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) | ||
3509 | { | ||
3510 | //Add half the avatar's height so that the user doesn't fall through prims | ||
3511 | ScenePresence presence; | ||
3512 | if (TryGetScenePresence(remoteClient.AgentId, out presence)) | ||
3513 | { | ||
3514 | if (presence.Appearance != null) | ||
3515 | { | ||
3516 | position.Z = position.Z + (presence.Appearance.AvatarHeight / 2); | ||
3517 | } | ||
3518 | } | ||
3519 | |||
3520 | if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) | ||
3521 | // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. | ||
3522 | m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); | ||
3523 | else | ||
3524 | m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed."); | ||
3525 | } | ||
3526 | |||
3527 | /// <summary> | ||
3528 | /// Get the avatar apperance for the given client. | 3532 | /// Get the avatar apperance for the given client. |
3529 | /// </summary> | 3533 | /// </summary> |
3530 | /// <param name="client"></param> | 3534 | /// <param name="client"></param> |
@@ -3548,63 +3552,69 @@ namespace OpenSim.Region.Framework.Scenes | |||
3548 | } | 3552 | } |
3549 | } | 3553 | } |
3550 | 3554 | ||
3551 | public override void RemoveClient(UUID agentID, bool closeChildAgents) | 3555 | /// <summary> |
3556 | /// Remove the given client from the scene. | ||
3557 | /// </summary> | ||
3558 | /// <remarks> | ||
3559 | /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead | ||
3560 | /// to properly operate the state machine and avoid race conditions with other close requests (such as directly | ||
3561 | /// from viewers). | ||
3562 | /// </remarks> | ||
3563 | /// <param name='agentID'>ID of agent to close</param> | ||
3564 | /// <param name='closeChildAgents'> | ||
3565 | /// Close the neighbour child agents associated with this client. | ||
3566 | /// </param> | ||
3567 | public void RemoveClient(UUID agentID, bool closeChildAgents) | ||
3552 | { | 3568 | { |
3553 | // CheckHeartbeat(); | 3569 | AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
3554 | bool isChildAgent = false; | ||
3555 | AgentCircuitData acd; | ||
3556 | 3570 | ||
3557 | lock (m_removeClientLock) | 3571 | // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which |
3572 | // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not | ||
3573 | // However, will keep for now just in case. | ||
3574 | if (acd == null) | ||
3558 | { | 3575 | { |
3559 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); | 3576 | m_log.ErrorFormat( |
3577 | "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name); | ||
3560 | 3578 | ||
3561 | if (acd == null) | 3579 | return; |
3562 | { | 3580 | } |
3563 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); | 3581 | else |
3564 | return; | 3582 | { |
3565 | } | 3583 | m_authenticateHandler.RemoveCircuit(agentID); |
3566 | else | ||
3567 | { | ||
3568 | // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred | ||
3569 | // simultaneously. | ||
3570 | // We also need to remove by agent ID since NPCs will have no circuit code. | ||
3571 | m_authenticateHandler.RemoveCircuit(agentID); | ||
3572 | } | ||
3573 | } | 3584 | } |
3574 | 3585 | ||
3586 | // TODO: Can we now remove this lock? | ||
3575 | lock (acd) | 3587 | lock (acd) |
3576 | { | 3588 | { |
3589 | bool isChildAgent = false; | ||
3590 | |||
3577 | ScenePresence avatar = GetScenePresence(agentID); | 3591 | ScenePresence avatar = GetScenePresence(agentID); |
3578 | 3592 | ||
3593 | // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which | ||
3594 | // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not | ||
3595 | // However, will keep for now just in case. | ||
3579 | if (avatar == null) | 3596 | if (avatar == null) |
3580 | { | 3597 | { |
3581 | m_log.WarnFormat( | 3598 | m_log.ErrorFormat( |
3582 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | 3599 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); |
3583 | 3600 | ||
3584 | return; | 3601 | return; |
3585 | } | 3602 | } |
3586 | 3603 | ||
3587 | try | 3604 | try |
3588 | { | 3605 | { |
3589 | isChildAgent = avatar.IsChildAgent; | 3606 | isChildAgent = avatar.IsChildAgent; |
3590 | 3607 | ||
3591 | m_log.DebugFormat( | 3608 | m_log.DebugFormat( |
3592 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | 3609 | "[SCENE]: Removing {0} agent {1} {2} from {3}", |
3593 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | 3610 | isChildAgent ? "child" : "root", avatar.Name, agentID, Name); |
3594 | 3611 | ||
3595 | // Don't do this to root agents, it's not nice for the viewer | 3612 | // Don't do this to root agents, it's not nice for the viewer |
3596 | if (closeChildAgents && isChildAgent) | 3613 | if (closeChildAgents && isChildAgent) |
3597 | { | 3614 | { |
3598 | // Tell a single agent to disconnect from the region. | 3615 | // Tell a single agent to disconnect from the region. |
3599 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | 3616 | // Let's do this via UDP |
3600 | if (eq != null) | 3617 | avatar.ControllingClient.SendShutdownConnectionNotice(); |
3601 | { | ||
3602 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3603 | } | ||
3604 | else | ||
3605 | { | ||
3606 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3607 | } | ||
3608 | } | 3618 | } |
3609 | 3619 | ||
3610 | // Only applies to root agents. | 3620 | // Only applies to root agents. |
@@ -3620,16 +3630,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
3620 | if (closeChildAgents && CapsModule != null) | 3630 | if (closeChildAgents && CapsModule != null) |
3621 | CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); | 3631 | CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); |
3622 | 3632 | ||
3623 | // // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3624 | // // this method is doing is HORRIBLE!!! | ||
3625 | // Commented pending deletion since this method no longer appears to do anything at all | ||
3626 | // avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3627 | |||
3628 | if (closeChildAgents && !isChildAgent) | 3633 | if (closeChildAgents && !isChildAgent) |
3629 | { | 3634 | { |
3630 | List<ulong> regions = avatar.KnownRegionHandles; | 3635 | List<ulong> regions = avatar.KnownRegionHandles; |
3631 | regions.Remove(RegionInfo.RegionHandle); | 3636 | regions.Remove(RegionInfo.RegionHandle); |
3632 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | 3637 | |
3638 | // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours. | ||
3639 | m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions); | ||
3633 | } | 3640 | } |
3634 | 3641 | ||
3635 | m_eventManager.TriggerClientClosed(agentID, this); | 3642 | m_eventManager.TriggerClientClosed(agentID, this); |
@@ -3646,7 +3653,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3646 | delegate(IClientAPI client) | 3653 | delegate(IClientAPI client) |
3647 | { | 3654 | { |
3648 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3655 | //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 }); } | 3656 | try { client.SendKillObject(new List<uint> { avatar.LocalId }); } |
3650 | catch (NullReferenceException) { } | 3657 | catch (NullReferenceException) { } |
3651 | }); | 3658 | }); |
3652 | } | 3659 | } |
@@ -3727,7 +3734,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3727 | } | 3734 | } |
3728 | deleteIDs.Add(localID); | 3735 | deleteIDs.Add(localID); |
3729 | } | 3736 | } |
3730 | ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); | 3737 | |
3738 | ForEachClient(c => c.SendKillObject(deleteIDs)); | ||
3731 | } | 3739 | } |
3732 | 3740 | ||
3733 | #endregion | 3741 | #endregion |
@@ -3763,13 +3771,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
3763 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of | 3771 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of |
3764 | /// the LLUDP stack). | 3772 | /// the LLUDP stack). |
3765 | /// </remarks> | 3773 | /// </remarks> |
3766 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3774 | /// <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> | 3775 | /// <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 | 3776 | /// <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> | 3777 | /// 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 | 3778 | /// <returns>True if the region accepts this agent. False if it does not. False will |
3771 | /// also return a reason.</returns> | 3779 | /// also return a reason.</returns> |
3772 | public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) | 3780 | public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup) |
3773 | { | 3781 | { |
3774 | bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || | 3782 | bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || |
3775 | (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); | 3783 | (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); |
@@ -3789,15 +3797,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
3789 | m_log.DebugFormat( | 3797 | 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})", | 3798 | "[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, | 3799 | RegionInfo.RegionName, |
3792 | (agent.child ? "child" : "root"), | 3800 | (acd.child ? "child" : "root"), |
3793 | agent.firstname, | 3801 | acd.firstname, |
3794 | agent.lastname, | 3802 | acd.lastname, |
3795 | agent.AgentID, | 3803 | acd.AgentID, |
3796 | agent.circuitcode, | 3804 | acd.circuitcode, |
3797 | agent.IPAddress, | 3805 | acd.IPAddress, |
3798 | agent.Viewer, | 3806 | acd.Viewer, |
3799 | ((TPFlags)teleportFlags).ToString(), | 3807 | ((TPFlags)teleportFlags).ToString(), |
3800 | agent.startpos | 3808 | acd.startpos |
3801 | ); | 3809 | ); |
3802 | 3810 | ||
3803 | if (!LoginsEnabled) | 3811 | if (!LoginsEnabled) |
@@ -3815,7 +3823,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3815 | { | 3823 | { |
3816 | foreach (string viewer in m_AllowedViewers) | 3824 | foreach (string viewer in m_AllowedViewers) |
3817 | { | 3825 | { |
3818 | if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) | 3826 | if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower()) |
3819 | { | 3827 | { |
3820 | ViewerDenied = false; | 3828 | ViewerDenied = false; |
3821 | break; | 3829 | break; |
@@ -3832,7 +3840,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3832 | { | 3840 | { |
3833 | foreach (string viewer in m_BannedViewers) | 3841 | foreach (string viewer in m_BannedViewers) |
3834 | { | 3842 | { |
3835 | if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) | 3843 | if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower()) |
3836 | { | 3844 | { |
3837 | ViewerDenied = true; | 3845 | ViewerDenied = true; |
3838 | break; | 3846 | break; |
@@ -3844,54 +3852,129 @@ namespace OpenSim.Region.Framework.Scenes | |||
3844 | { | 3852 | { |
3845 | m_log.DebugFormat( | 3853 | m_log.DebugFormat( |
3846 | "[SCENE]: Access denied for {0} {1} using {2}", | 3854 | "[SCENE]: Access denied for {0} {1} using {2}", |
3847 | agent.firstname, agent.lastname, agent.Viewer); | 3855 | acd.firstname, acd.lastname, acd.Viewer); |
3848 | reason = "Access denied, your viewer is banned by the region owner"; | 3856 | reason = "Access denied, your viewer is banned by the region owner"; |
3849 | return false; | 3857 | return false; |
3850 | } | 3858 | } |
3851 | 3859 | ||
3852 | ScenePresence sp = GetScenePresence(agent.AgentID); | 3860 | ILandObject land; |
3861 | ScenePresence sp; | ||
3853 | 3862 | ||
3854 | // If we have noo presence here or if that presence is a zombie root | 3863 | lock (m_removeClientLock) |
3855 | // presence that will be kicled, we need a new CAPS object. | ||
3856 | if (sp == null || (sp != null && !sp.IsChildAgent)) | ||
3857 | { | 3864 | { |
3858 | if (CapsModule != null) | 3865 | sp = GetScenePresence(acd.AgentID); |
3866 | |||
3867 | // We need to ensure that we are not already removing the scene presence before we ask it not to be | ||
3868 | // closed. | ||
3869 | if (sp != null && sp.IsChildAgent | ||
3870 | && (sp.LifecycleState == ScenePresenceState.Running | ||
3871 | || sp.LifecycleState == ScenePresenceState.PreRemove)) | ||
3859 | { | 3872 | { |
3860 | lock (agent) | 3873 | m_log.DebugFormat( |
3874 | "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", | ||
3875 | sp.Name, sp.LifecycleState, Name); | ||
3876 | |||
3877 | // In the case where, for example, an A B C D region layout, an avatar may | ||
3878 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C | ||
3879 | // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. | ||
3880 | // | ||
3881 | // XXX: In the end, this should not be necessary if child agents are closed without delay on | ||
3882 | // teleport, since realistically, the close request should always be processed before any other | ||
3883 | // region tried to re-establish a child agent. This is much simpler since the logic below is | ||
3884 | // vulnerable to an issue when a viewer quits a region without sending a proper logout but then | ||
3885 | // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport | ||
3886 | // flag when no teleport had taken place (and hence no close was going to come). | ||
3887 | // if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) | ||
3888 | // { | ||
3889 | // m_log.DebugFormat( | ||
3890 | // "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", | ||
3891 | // sp.Name, Name); | ||
3892 | // | ||
3893 | // sp.DoNotCloseAfterTeleport = true; | ||
3894 | // } | ||
3895 | // else if (EntityTransferModule.IsInTransit(sp.UUID)) | ||
3896 | |||
3897 | sp.LifecycleState = ScenePresenceState.Running; | ||
3898 | |||
3899 | if (EntityTransferModule.IsInTransit(sp.UUID)) | ||
3861 | { | 3900 | { |
3862 | CapsModule.SetAgentCapsSeeds(agent); | 3901 | sp.DoNotCloseAfterTeleport = true; |
3863 | CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); | 3902 | |
3903 | m_log.DebugFormat( | ||
3904 | "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", | ||
3905 | sp.Name, Name); | ||
3864 | } | 3906 | } |
3865 | } | 3907 | } |
3866 | } | 3908 | } |
3867 | 3909 | ||
3910 | // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will | ||
3911 | // allow unpredictable things to happen. | ||
3868 | if (sp != null) | 3912 | if (sp != null) |
3869 | { | 3913 | { |
3870 | if (!sp.IsChildAgent) | 3914 | const int polls = 10; |
3915 | const int pollInterval = 1000; | ||
3916 | int pollsLeft = polls; | ||
3917 | |||
3918 | while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0) | ||
3919 | Thread.Sleep(pollInterval); | ||
3920 | |||
3921 | if (sp.LifecycleState == ScenePresenceState.Removing) | ||
3871 | { | 3922 | { |
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( | 3923 | m_log.WarnFormat( |
3876 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | 3924 | "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", |
3877 | sp.Name, sp.UUID, RegionInfo.RegionName); | 3925 | sp.Name, Name, polls * pollInterval / 1000); |
3878 | 3926 | ||
3879 | sp.ControllingClient.Close(true, true); | 3927 | return false; |
3880 | sp = null; | 3928 | } |
3929 | else if (polls != pollsLeft) | ||
3930 | { | ||
3931 | m_log.DebugFormat( | ||
3932 | "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.", | ||
3933 | sp.Name, Name, polls * pollInterval / 1000); | ||
3881 | } | 3934 | } |
3882 | } | 3935 | } |
3883 | 3936 | ||
3884 | lock (agent) | 3937 | // TODO: can we remove this lock? |
3938 | lock (acd) | ||
3885 | { | 3939 | { |
3886 | //On login test land permisions | 3940 | if (sp != null && !sp.IsChildAgent) |
3941 | { | ||
3942 | // We have a root agent. Is it in transit? | ||
3943 | if (!EntityTransferModule.IsInTransit(sp.UUID)) | ||
3944 | { | ||
3945 | // We have a zombie from a crashed session. | ||
3946 | // Or the same user is trying to be root twice here, won't work. | ||
3947 | // Kill it. | ||
3948 | m_log.WarnFormat( | ||
3949 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | ||
3950 | sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3951 | |||
3952 | if (sp.ControllingClient != null) | ||
3953 | CloseAgent(sp.UUID, true); | ||
3954 | |||
3955 | sp = null; | ||
3956 | } | ||
3957 | //else | ||
3958 | // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3959 | } | ||
3960 | |||
3961 | // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. | ||
3962 | // We need the circuit data here for some of the subsequent checks. (groups, for example) | ||
3963 | // If the checks fail, we remove the circuit. | ||
3964 | acd.teleportFlags = teleportFlags; | ||
3965 | m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); | ||
3966 | |||
3967 | land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); | ||
3968 | |||
3969 | // On login test land permisions | ||
3887 | if (vialogin) | 3970 | if (vialogin) |
3888 | { | 3971 | { |
3889 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); | 3972 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); |
3890 | if (cache != null) | 3973 | if (cache != null) |
3891 | cache.Remove(agent.firstname + " " + agent.lastname); | 3974 | cache.Remove(acd.firstname + " " + acd.lastname); |
3892 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | 3975 | if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) |
3893 | { | 3976 | { |
3894 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | 3977 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); |
3895 | return false; | 3978 | return false; |
3896 | } | 3979 | } |
3897 | } | 3980 | } |
@@ -3902,84 +3985,97 @@ namespace OpenSim.Region.Framework.Scenes | |||
3902 | { | 3985 | { |
3903 | try | 3986 | try |
3904 | { | 3987 | { |
3905 | if (!VerifyUserPresence(agent, out reason)) | 3988 | if (!VerifyUserPresence(acd, out reason)) |
3989 | { | ||
3990 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3906 | return false; | 3991 | return false; |
3907 | } catch (Exception e) | 3992 | } |
3993 | } | ||
3994 | catch (Exception e) | ||
3908 | { | 3995 | { |
3909 | m_log.ErrorFormat( | 3996 | m_log.ErrorFormat( |
3910 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | 3997 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); |
3998 | |||
3999 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3911 | return false; | 4000 | return false; |
3912 | } | 4001 | } |
3913 | } | 4002 | } |
3914 | 4003 | ||
3915 | try | 4004 | try |
3916 | { | 4005 | { |
3917 | // Always check estate if this is a login. Always | 4006 | if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason)) |
3918 | // check if banned regions are to be blacked out. | ||
3919 | if (vialogin || (!m_seeIntoBannedRegion)) | ||
3920 | { | 4007 | { |
3921 | if (!AuthorizeUser(agent, out reason)) | 4008 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); |
3922 | { | 4009 | return false; |
3923 | return false; | ||
3924 | } | ||
3925 | } | 4010 | } |
3926 | } | 4011 | } |
3927 | catch (Exception e) | 4012 | catch (Exception e) |
3928 | { | 4013 | { |
3929 | m_log.ErrorFormat( | 4014 | m_log.ErrorFormat( |
3930 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | 4015 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); |
4016 | |||
4017 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3931 | return false; | 4018 | return false; |
3932 | } | 4019 | } |
3933 | 4020 | ||
3934 | m_log.InfoFormat( | 4021 | m_log.InfoFormat( |
3935 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | 4022 | "[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, | 4023 | Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname, |
3937 | agent.AgentID, agent.circuitcode); | 4024 | acd.AgentID, acd.circuitcode); |
3938 | 4025 | ||
4026 | if (CapsModule != null) | ||
4027 | { | ||
4028 | CapsModule.SetAgentCapsSeeds(acd); | ||
4029 | CapsModule.CreateCaps(acd.AgentID, acd.circuitcode); | ||
4030 | } | ||
3939 | } | 4031 | } |
3940 | else | 4032 | else |
3941 | { | 4033 | { |
3942 | // Let the SP know how we got here. This has a lot of interesting | 4034 | // Let the SP know how we got here. This has a lot of interesting |
3943 | // uses down the line. | 4035 | // uses down the line. |
3944 | sp.TeleportFlags = (TPFlags)teleportFlags; | 4036 | sp.TeleportFlags = (TPFlags)teleportFlags; |
3945 | 4037 | ||
3946 | if (sp.IsChildAgent) | 4038 | if (sp.IsChildAgent) |
3947 | { | 4039 | { |
3948 | m_log.DebugFormat( | 4040 | m_log.DebugFormat( |
3949 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | 4041 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", |
3950 | agent.AgentID, RegionInfo.RegionName); | 4042 | acd.AgentID, RegionInfo.RegionName); |
3951 | 4043 | ||
3952 | sp.AdjustKnownSeeds(); | 4044 | sp.AdjustKnownSeeds(); |
3953 | 4045 | ||
3954 | if (CapsModule != null) | 4046 | if (CapsModule != null) |
3955 | CapsModule.SetAgentCapsSeeds(agent); | 4047 | { |
4048 | CapsModule.SetAgentCapsSeeds(acd); | ||
4049 | CapsModule.CreateCaps(acd.AgentID, acd.circuitcode); | ||
4050 | } | ||
3956 | } | 4051 | } |
3957 | } | 4052 | } |
3958 | } | ||
3959 | 4053 | ||
3960 | // In all cases, add or update the circuit data with the new agent circuit data and teleport flags | 4054 | // Try caching an incoming user name much earlier on to see if this helps with an issue |
3961 | agent.teleportFlags = teleportFlags; | 4055 | // where HG users are occasionally seen by others as "Unknown User" because their UUIDName |
3962 | m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); | 4056 | // request for the HG avatar appears to trigger before the user name is cached. |
4057 | CacheUserName(null, acd); | ||
4058 | } | ||
3963 | 4059 | ||
3964 | if (CapsModule != null) | 4060 | if (CapsModule != null) |
3965 | { | 4061 | { |
3966 | CapsModule.ActivateCaps(agent.circuitcode); | 4062 | CapsModule.ActivateCaps(acd.circuitcode); |
3967 | } | 4063 | } |
3968 | 4064 | ||
3969 | if (vialogin) | 4065 | if (vialogin) |
3970 | { | 4066 | { |
3971 | // CleanDroppedAttachments(); | 4067 | // CleanDroppedAttachments(); |
3972 | 4068 | ||
3973 | if (TestBorderCross(agent.startpos, Cardinals.E)) | 4069 | if (TestBorderCross(acd.startpos, Cardinals.E)) |
3974 | { | 4070 | { |
3975 | Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); | 4071 | Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); |
3976 | agent.startpos.X = crossedBorder.BorderLine.Z - 1; | 4072 | acd.startpos.X = crossedBorder.BorderLine.Z - 1; |
3977 | } | 4073 | } |
3978 | 4074 | ||
3979 | if (TestBorderCross(agent.startpos, Cardinals.N)) | 4075 | if (TestBorderCross(acd.startpos, Cardinals.N)) |
3980 | { | 4076 | { |
3981 | Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); | 4077 | Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N); |
3982 | agent.startpos.Y = crossedBorder.BorderLine.Z - 1; | 4078 | acd.startpos.Y = crossedBorder.BorderLine.Z - 1; |
3983 | } | 4079 | } |
3984 | 4080 | ||
3985 | //Mitigate http://opensimulator.org/mantis/view.php?id=3522 | 4081 | //Mitigate http://opensimulator.org/mantis/view.php?id=3522 |
@@ -3989,68 +4085,88 @@ namespace OpenSim.Region.Framework.Scenes | |||
3989 | { | 4085 | { |
3990 | lock (EastBorders) | 4086 | lock (EastBorders) |
3991 | { | 4087 | { |
3992 | if (agent.startpos.X > EastBorders[0].BorderLine.Z) | 4088 | if (acd.startpos.X > EastBorders[0].BorderLine.Z) |
3993 | { | 4089 | { |
3994 | m_log.Warn("FIX AGENT POSITION"); | 4090 | m_log.Warn("FIX AGENT POSITION"); |
3995 | agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; | 4091 | acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; |
3996 | if (agent.startpos.Z > 720) | 4092 | if (acd.startpos.Z > 720) |
3997 | agent.startpos.Z = 720; | 4093 | acd.startpos.Z = 720; |
3998 | } | 4094 | } |
3999 | } | 4095 | } |
4000 | lock (NorthBorders) | 4096 | lock (NorthBorders) |
4001 | { | 4097 | { |
4002 | if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) | 4098 | if (acd.startpos.Y > NorthBorders[0].BorderLine.Z) |
4003 | { | 4099 | { |
4004 | m_log.Warn("FIX Agent POSITION"); | 4100 | m_log.Warn("FIX Agent POSITION"); |
4005 | agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; | 4101 | acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; |
4006 | if (agent.startpos.Z > 720) | 4102 | if (acd.startpos.Z > 720) |
4007 | agent.startpos.Z = 720; | 4103 | acd.startpos.Z = 720; |
4008 | } | 4104 | } |
4009 | } | 4105 | } |
4010 | } else | 4106 | } else |
4011 | { | 4107 | { |
4012 | if (agent.startpos.X > EastBorders[0].BorderLine.Z) | 4108 | if (acd.startpos.X > EastBorders[0].BorderLine.Z) |
4013 | { | 4109 | { |
4014 | m_log.Warn("FIX AGENT POSITION"); | 4110 | m_log.Warn("FIX AGENT POSITION"); |
4015 | agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; | 4111 | acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; |
4016 | if (agent.startpos.Z > 720) | 4112 | if (acd.startpos.Z > 720) |
4017 | agent.startpos.Z = 720; | 4113 | acd.startpos.Z = 720; |
4018 | } | 4114 | } |
4019 | if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) | 4115 | if (acd.startpos.Y > NorthBorders[0].BorderLine.Z) |
4020 | { | 4116 | { |
4021 | m_log.Warn("FIX Agent POSITION"); | 4117 | m_log.Warn("FIX Agent POSITION"); |
4022 | agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; | 4118 | acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; |
4023 | if (agent.startpos.Z > 720) | 4119 | if (acd.startpos.Z > 720) |
4024 | agent.startpos.Z = 720; | 4120 | acd.startpos.Z = 720; |
4025 | } | 4121 | } |
4026 | } | 4122 | } |
4027 | 4123 | ||
4124 | // m_log.DebugFormat( | ||
4125 | // "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", | ||
4126 | // RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); | ||
4127 | |||
4028 | // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags | 4128 | // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags |
4029 | if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && | 4129 | if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && |
4030 | RegionInfo.EstateSettings.AllowDirectTeleport == false && | 4130 | RegionInfo.EstateSettings.AllowDirectTeleport == false && |
4031 | !viahome && !godlike) | 4131 | !viahome && !godlike) |
4032 | { | 4132 | { |
4033 | SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); | 4133 | SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); |
4034 | // Can have multiple SpawnPoints | 4134 | |
4035 | List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); | 4135 | if (telehub != null) |
4036 | if (spawnpoints.Count > 1) | ||
4037 | { | 4136 | { |
4038 | // We have multiple SpawnPoints, Route the agent to a random or sequential one | 4137 | // Can have multiple SpawnPoints |
4039 | if (SpawnPointRouting == "random") | 4138 | List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); |
4040 | agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( | 4139 | if (spawnpoints.Count > 1) |
4041 | telehub.AbsolutePosition, | 4140 | { |
4042 | telehub.GroupRotation | 4141 | // We have multiple SpawnPoints, Route the agent to a random or sequential one |
4043 | ); | 4142 | if (SpawnPointRouting == "random") |
4143 | acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( | ||
4144 | telehub.AbsolutePosition, | ||
4145 | telehub.GroupRotation | ||
4146 | ); | ||
4147 | else | ||
4148 | acd.startpos = spawnpoints[SpawnPoint()].GetLocation( | ||
4149 | telehub.AbsolutePosition, | ||
4150 | telehub.GroupRotation | ||
4151 | ); | ||
4152 | } | ||
4153 | else if (spawnpoints.Count == 1) | ||
4154 | { | ||
4155 | // We have a single SpawnPoint and will route the agent to it | ||
4156 | acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); | ||
4157 | } | ||
4044 | else | 4158 | else |
4045 | agent.startpos = spawnpoints[SpawnPoint()].GetLocation( | 4159 | { |
4046 | telehub.AbsolutePosition, | 4160 | m_log.DebugFormat( |
4047 | telehub.GroupRotation | 4161 | "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", |
4048 | ); | 4162 | RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); |
4163 | } | ||
4049 | } | 4164 | } |
4050 | else | 4165 | else |
4051 | { | 4166 | { |
4052 | // We have a single SpawnPoint and will route the agent to it | 4167 | m_log.DebugFormat( |
4053 | agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); | 4168 | "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", |
4169 | RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); | ||
4054 | } | 4170 | } |
4055 | 4171 | ||
4056 | return true; | 4172 | return true; |
@@ -4063,7 +4179,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4063 | { | 4179 | { |
4064 | if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) | 4180 | if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) |
4065 | { | 4181 | { |
4066 | agent.startpos = land.LandData.UserLocation; | 4182 | acd.startpos = land.LandData.UserLocation; |
4067 | } | 4183 | } |
4068 | } | 4184 | } |
4069 | */// This is now handled properly in ScenePresence.MakeRootAgent | 4185 | */// This is now handled properly in ScenePresence.MakeRootAgent |
@@ -4158,7 +4274,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4158 | /// <param name="reason">outputs the reason to this string</param> | 4274 | /// <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 | 4275 | /// <returns>True if the region accepts this agent. False if it does not. False will |
4160 | /// also return a reason.</returns> | 4276 | /// also return a reason.</returns> |
4161 | protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) | 4277 | protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) |
4162 | { | 4278 | { |
4163 | reason = String.Empty; | 4279 | reason = String.Empty; |
4164 | 4280 | ||
@@ -4177,67 +4293,75 @@ namespace OpenSim.Region.Framework.Scenes | |||
4177 | } | 4293 | } |
4178 | } | 4294 | } |
4179 | 4295 | ||
4180 | if (RegionInfo.EstateSettings != null) | 4296 | // We only test the things below when we want to cut off |
4297 | // child agents from being present in the scene for which their root | ||
4298 | // agent isn't allowed. Otherwise, we allow child agents. The test for | ||
4299 | // the root is done elsewhere (QueryAccess) | ||
4300 | if (!bypassAccessControl) | ||
4181 | { | 4301 | { |
4182 | if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) | 4302 | if (RegionInfo.EstateSettings != null) |
4183 | { | 4303 | { |
4184 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", | 4304 | int flags = GetUserFlags(agent.AgentID); |
4185 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); | 4305 | if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags)) |
4186 | reason = String.Format("Denied access to region {0}: You have been banned from that region.", | 4306 | { |
4187 | RegionInfo.RegionName); | 4307 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", |
4188 | return false; | 4308 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); |
4309 | reason = String.Format("Denied access to region {0}: You have been banned from that region.", | ||
4310 | RegionInfo.RegionName); | ||
4311 | return false; | ||
4312 | } | ||
4189 | } | 4313 | } |
4190 | } | 4314 | 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 | { | 4315 | { |
4204 | for (int i = 0; i < GroupMembership.Length; i++) | 4316 | m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); |
4205 | agentGroups.Add(GroupMembership[i].GroupID); | ||
4206 | } | 4317 | } |
4207 | else | 4318 | |
4319 | List<UUID> agentGroups = new List<UUID>(); | ||
4320 | |||
4321 | if (m_groupsModule != null) | ||
4208 | { | 4322 | { |
4209 | m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); | 4323 | GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); |
4324 | |||
4325 | if (GroupMembership != null) | ||
4326 | { | ||
4327 | for (int i = 0; i < GroupMembership.Length; i++) | ||
4328 | agentGroups.Add(GroupMembership[i].GroupID); | ||
4329 | } | ||
4330 | else | ||
4331 | { | ||
4332 | m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); | ||
4333 | } | ||
4210 | } | 4334 | } |
4211 | } | ||
4212 | 4335 | ||
4213 | bool groupAccess = false; | 4336 | bool groupAccess = false; |
4214 | UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; | 4337 | UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; |
4215 | 4338 | ||
4216 | if (estateGroups != null) | 4339 | if (estateGroups != null) |
4217 | { | ||
4218 | foreach (UUID group in estateGroups) | ||
4219 | { | 4340 | { |
4220 | if (agentGroups.Contains(group)) | 4341 | foreach (UUID group in estateGroups) |
4221 | { | 4342 | { |
4222 | groupAccess = true; | 4343 | if (agentGroups.Contains(group)) |
4223 | break; | 4344 | { |
4345 | groupAccess = true; | ||
4346 | break; | ||
4347 | } | ||
4224 | } | 4348 | } |
4225 | } | 4349 | } |
4226 | } | 4350 | else |
4227 | else | 4351 | { |
4228 | { | 4352 | m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); |
4229 | m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); | 4353 | } |
4230 | } | ||
4231 | 4354 | ||
4232 | if (!RegionInfo.EstateSettings.PublicAccess && | 4355 | if (!RegionInfo.EstateSettings.PublicAccess && |
4233 | !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && | 4356 | !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && |
4234 | !groupAccess) | 4357 | !groupAccess) |
4235 | { | 4358 | { |
4236 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", | 4359 | 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); | 4360 | 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.", | 4361 | reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", |
4239 | RegionInfo.RegionName); | 4362 | RegionInfo.RegionName); |
4240 | return false; | 4363 | return false; |
4364 | } | ||
4241 | } | 4365 | } |
4242 | 4366 | ||
4243 | // TODO: estate/region settings are not properly hooked up | 4367 | // TODO: estate/region settings are not properly hooked up |
@@ -4362,13 +4486,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
4362 | /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. | 4486 | /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. |
4363 | /// Appearance, animations, position, etc.</param> | 4487 | /// Appearance, animations, position, etc.</param> |
4364 | /// <returns>true if we handled it.</returns> | 4488 | /// <returns>true if we handled it.</returns> |
4365 | public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) | 4489 | public virtual bool IncomingUpdateChildAgent(AgentData cAgentData) |
4366 | { | 4490 | { |
4367 | m_log.DebugFormat( | 4491 | m_log.DebugFormat( |
4368 | "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); | 4492 | "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); |
4369 | 4493 | ||
4370 | // XPTO: if this agent is not allowed here as root, always return false | ||
4371 | |||
4372 | // We have to wait until the viewer contacts this region after receiving EAC. | 4494 | // We have to wait until the viewer contacts this region after receiving EAC. |
4373 | // That calls AddNewClient, which finally creates the ScenePresence | 4495 | // That calls AddNewClient, which finally creates the ScenePresence |
4374 | int flags = GetUserFlags(cAgentData.AgentID); | 4496 | int flags = GetUserFlags(cAgentData.AgentID); |
@@ -4382,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4382 | ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); | 4504 | ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); |
4383 | if (nearestParcel == null) | 4505 | if (nearestParcel == null) |
4384 | { | 4506 | { |
4385 | m_log.DebugFormat( | 4507 | m_log.InfoFormat( |
4386 | "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", | 4508 | "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", |
4387 | cAgentData.AgentID, RegionInfo.RegionName); | 4509 | cAgentData.AgentID, RegionInfo.RegionName); |
4388 | 4510 | ||
@@ -4390,13 +4512,44 @@ namespace OpenSim.Region.Framework.Scenes | |||
4390 | } | 4512 | } |
4391 | 4513 | ||
4392 | // We have to wait until the viewer contacts this region | 4514 | // 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 | 4515 | // 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. | 4516 | // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send |
4395 | ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); | 4517 | // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. |
4518 | ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); | ||
4396 | 4519 | ||
4397 | if (childAgentUpdate != null) | 4520 | if (sp != null) |
4398 | { | 4521 | { |
4399 | childAgentUpdate.ChildAgentDataUpdate(cAgentData); | 4522 | if (cAgentData.SessionID != sp.ControllingClient.SessionId) |
4523 | { | ||
4524 | m_log.WarnFormat( | ||
4525 | "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", | ||
4526 | sp.UUID, cAgentData.SessionID); | ||
4527 | |||
4528 | Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", | ||
4529 | sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); | ||
4530 | } | ||
4531 | |||
4532 | sp.UpdateChildAgent(cAgentData); | ||
4533 | |||
4534 | int ntimes = 20; | ||
4535 | if (cAgentData.SenderWantsToWaitForRoot) | ||
4536 | { | ||
4537 | while (sp.IsChildAgent && ntimes-- > 0) | ||
4538 | Thread.Sleep(1000); | ||
4539 | |||
4540 | if (sp.IsChildAgent) | ||
4541 | m_log.WarnFormat( | ||
4542 | "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}", | ||
4543 | sp.Name, sp.UUID, Name); | ||
4544 | else | ||
4545 | m_log.InfoFormat( | ||
4546 | "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits", | ||
4547 | sp.Name, sp.UUID, Name, 20 - ntimes); | ||
4548 | |||
4549 | if (sp.IsChildAgent) | ||
4550 | return false; | ||
4551 | } | ||
4552 | |||
4400 | return true; | 4553 | return true; |
4401 | } | 4554 | } |
4402 | 4555 | ||
@@ -4409,12 +4562,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
4409 | /// </summary> | 4562 | /// </summary> |
4410 | /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> | 4563 | /// <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> | 4564 | /// <returns>true if we handled it.</returns> |
4412 | public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) | 4565 | public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) |
4413 | { | 4566 | { |
4414 | //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); | 4567 | //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); |
4415 | ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); | 4568 | ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); |
4416 | if (childAgentUpdate != null) | 4569 | if (childAgentUpdate != null) |
4417 | { | 4570 | { |
4571 | // if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) | ||
4572 | // // Only warn for now | ||
4573 | // m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", | ||
4574 | // childAgentUpdate.UUID, cAgentData.SessionID); | ||
4575 | |||
4418 | // I can't imagine *yet* why we would get an update if the agent is a root agent.. | 4576 | // 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.. | 4577 | // however to avoid a race condition crossing borders.. |
4420 | if (childAgentUpdate.IsChildAgent) | 4578 | if (childAgentUpdate.IsChildAgent) |
@@ -4424,7 +4582,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4424 | uint tRegionX = RegionInfo.RegionLocX; | 4582 | uint tRegionX = RegionInfo.RegionLocX; |
4425 | uint tRegionY = RegionInfo.RegionLocY; | 4583 | uint tRegionY = RegionInfo.RegionLocY; |
4426 | //Send Data to ScenePresence | 4584 | //Send Data to ScenePresence |
4427 | childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); | 4585 | childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); |
4428 | // Not Implemented: | 4586 | // Not Implemented: |
4429 | //TODO: Do we need to pass the message on to one of our neighbors? | 4587 | //TODO: Do we need to pass the message on to one of our neighbors? |
4430 | } | 4588 | } |
@@ -4451,35 +4609,99 @@ namespace OpenSim.Region.Framework.Scenes | |||
4451 | m_log.WarnFormat( | 4609 | m_log.WarnFormat( |
4452 | "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", | 4610 | "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", |
4453 | agentID, RegionInfo.RegionName); | 4611 | 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 | 4612 | ||
4459 | return sp; | 4613 | return sp; |
4460 | } | 4614 | } |
4461 | 4615 | ||
4462 | public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) | 4616 | /// <summary> |
4617 | /// Authenticated close (via network) | ||
4618 | /// </summary> | ||
4619 | /// <param name="agentID"></param> | ||
4620 | /// <param name="force"></param> | ||
4621 | /// <param name="auth_token"></param> | ||
4622 | /// <returns></returns> | ||
4623 | public bool CloseAgent(UUID agentID, bool force, string auth_token) | ||
4463 | { | 4624 | { |
4464 | agent = null; | 4625 | //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); | 4626 | |
4466 | if ((sp != null) && (!sp.IsChildAgent)) | 4627 | // Check that the auth_token is valid |
4628 | AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); | ||
4629 | |||
4630 | if (acd == null) | ||
4467 | { | 4631 | { |
4468 | sp.IsChildAgent = true; | 4632 | m_log.DebugFormat( |
4469 | return sp.CopyAgent(out agent); | 4633 | "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", |
4634 | agentID, Name); | ||
4635 | |||
4636 | return false; | ||
4637 | } | ||
4638 | |||
4639 | if (acd.SessionID.ToString() == auth_token) | ||
4640 | { | ||
4641 | return CloseAgent(agentID, force); | ||
4642 | } | ||
4643 | else | ||
4644 | { | ||
4645 | m_log.WarnFormat( | ||
4646 | "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", | ||
4647 | agentID, auth_token, Name); | ||
4470 | } | 4648 | } |
4471 | 4649 | ||
4472 | return false; | 4650 | return false; |
4473 | } | 4651 | } |
4474 | 4652 | ||
4475 | public bool IncomingCloseAgent(UUID agentID) | 4653 | // public bool IncomingCloseAgent(UUID agentID) |
4476 | { | 4654 | // { |
4477 | return IncomingCloseAgent(agentID, false); | 4655 | // return IncomingCloseAgent(agentID, false); |
4478 | } | 4656 | // } |
4479 | 4657 | ||
4480 | public bool IncomingCloseChildAgent(UUID agentID) | 4658 | // public bool IncomingCloseChildAgent(UUID agentID) |
4659 | // { | ||
4660 | // return IncomingCloseAgent(agentID, true); | ||
4661 | // } | ||
4662 | |||
4663 | /// <summary> | ||
4664 | /// Tell a single client to prepare to close. | ||
4665 | /// </summary> | ||
4666 | /// <remarks> | ||
4667 | /// This should only be called if we may close the client but there will be some delay in so doing. Meant for | ||
4668 | /// internal use - other callers should almost certainly called CloseClient(). | ||
4669 | /// </remarks> | ||
4670 | /// <param name="sp"></param> | ||
4671 | /// <returns>true if pre-close state notification was successful. false if the agent | ||
4672 | /// was not in a state where it could transition to pre-close.</returns> | ||
4673 | public bool IncomingPreCloseClient(ScenePresence sp) | ||
4481 | { | 4674 | { |
4482 | return IncomingCloseAgent(agentID, true); | 4675 | lock (m_removeClientLock) |
4676 | { | ||
4677 | // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may | ||
4678 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not | ||
4679 | // want to obey this close since C may have renewed the child agent lease on B. | ||
4680 | if (sp.DoNotCloseAfterTeleport) | ||
4681 | { | ||
4682 | m_log.DebugFormat( | ||
4683 | "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", | ||
4684 | sp.IsChildAgent ? "child" : "root", sp.Name, Name); | ||
4685 | |||
4686 | // Need to reset the flag so that a subsequent close after another teleport can succeed. | ||
4687 | sp.DoNotCloseAfterTeleport = false; | ||
4688 | |||
4689 | return false; | ||
4690 | } | ||
4691 | |||
4692 | if (sp.LifecycleState != ScenePresenceState.Running) | ||
4693 | { | ||
4694 | m_log.DebugFormat( | ||
4695 | "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", | ||
4696 | sp.Name, Name, sp.LifecycleState); | ||
4697 | |||
4698 | return false; | ||
4699 | } | ||
4700 | |||
4701 | sp.LifecycleState = ScenePresenceState.PreRemove; | ||
4702 | |||
4703 | return true; | ||
4704 | } | ||
4483 | } | 4705 | } |
4484 | 4706 | ||
4485 | /// <summary> | 4707 | /// <summary> |
@@ -4490,18 +4712,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
4490 | /// Force the agent to close even if it might be in the middle of some other operation. You do not want to | 4712 | /// 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. | 4713 | /// force unless you are absolutely sure that the agent is dead and a normal close is not working. |
4492 | /// </param> | 4714 | /// </param> |
4493 | public bool IncomingCloseAgent(UUID agentID, bool force) | 4715 | public override bool CloseAgent(UUID agentID, bool force) |
4494 | { | 4716 | { |
4495 | //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); | 4717 | ScenePresence sp; |
4496 | 4718 | ||
4497 | ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); | 4719 | lock (m_removeClientLock) |
4498 | if (presence != null) | 4720 | { |
4721 | sp = GetScenePresence(agentID); | ||
4722 | |||
4723 | if (sp == null) | ||
4724 | { | ||
4725 | m_log.DebugFormat( | ||
4726 | "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", | ||
4727 | agentID, Name); | ||
4728 | |||
4729 | return false; | ||
4730 | } | ||
4731 | |||
4732 | if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) | ||
4733 | { | ||
4734 | m_log.DebugFormat( | ||
4735 | "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}", | ||
4736 | sp.Name, Name, sp.LifecycleState); | ||
4737 | |||
4738 | return false; | ||
4739 | } | ||
4740 | |||
4741 | // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may | ||
4742 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not | ||
4743 | // want to obey this close since C may have renewed the child agent lease on B. | ||
4744 | if (sp.DoNotCloseAfterTeleport) | ||
4745 | { | ||
4746 | m_log.DebugFormat( | ||
4747 | "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection", | ||
4748 | sp.IsChildAgent ? "child" : "root", sp.Name, Name); | ||
4749 | |||
4750 | // Need to reset the flag so that a subsequent close after another teleport can succeed. | ||
4751 | sp.DoNotCloseAfterTeleport = false; | ||
4752 | |||
4753 | return false; | ||
4754 | } | ||
4755 | |||
4756 | sp.LifecycleState = ScenePresenceState.Removing; | ||
4757 | } | ||
4758 | |||
4759 | if (sp != null) | ||
4499 | { | 4760 | { |
4500 | presence.ControllingClient.Close(force, force); | 4761 | sp.ControllingClient.Close(force, force); |
4501 | return true; | 4762 | return true; |
4502 | } | 4763 | } |
4503 | 4764 | ||
4504 | // Agent not here | 4765 | // Agent not here |
4505 | return false; | 4766 | return false; |
4506 | } | 4767 | } |
4507 | 4768 | ||
@@ -5091,21 +5352,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
5091 | 5352 | ||
5092 | #endregion | 5353 | #endregion |
5093 | 5354 | ||
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 | 5355 | ||
5110 | // Commented pending deletion since this method no longer appears to do anything at all | 5356 | // Commented pending deletion since this method no longer appears to do anything at all |
5111 | // public bool NeedSceneCacheClear(UUID agentID) | 5357 | // public bool NeedSceneCacheClear(UUID agentID) |
@@ -5657,12 +5903,12 @@ Environment.Exit(1); | |||
5657 | List<SceneObjectGroup> objects, | 5903 | List<SceneObjectGroup> objects, |
5658 | out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) | 5904 | out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) |
5659 | { | 5905 | { |
5660 | minX = 256; | 5906 | minX = float.MaxValue; |
5661 | maxX = -256; | 5907 | maxX = float.MinValue; |
5662 | minY = 256; | 5908 | minY = float.MaxValue; |
5663 | maxY = -256; | 5909 | maxY = float.MinValue; |
5664 | minZ = 8192; | 5910 | minZ = float.MaxValue; |
5665 | maxZ = -256; | 5911 | maxZ = float.MinValue; |
5666 | 5912 | ||
5667 | List<Vector3> offsets = new List<Vector3>(); | 5913 | List<Vector3> offsets = new List<Vector3>(); |
5668 | 5914 | ||
@@ -5802,17 +6048,6 @@ Environment.Exit(1); | |||
5802 | { | 6048 | { |
5803 | reason = "You are banned from the region"; | 6049 | reason = "You are banned from the region"; |
5804 | 6050 | ||
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)) | 6051 | if (Permissions.IsGod(agentID)) |
5817 | { | 6052 | { |
5818 | reason = String.Empty; | 6053 | reason = String.Empty; |
@@ -5862,9 +6097,9 @@ Environment.Exit(1); | |||
5862 | 6097 | ||
5863 | try | 6098 | try |
5864 | { | 6099 | { |
5865 | if (!AuthorizeUser(aCircuit, out reason)) | 6100 | if (!AuthorizeUser(aCircuit, false, out reason)) |
5866 | { | 6101 | { |
5867 | // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); | 6102 | //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); |
5868 | return false; | 6103 | return false; |
5869 | } | 6104 | } |
5870 | } | 6105 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 74c9582..08e26c5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs | |||
@@ -42,7 +42,8 @@ namespace 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 | protected static readonly string LogHeader = "[SCENE]"; | ||
46 | 47 | ||
47 | #region Events | 48 | #region Events |
48 | 49 | ||
@@ -217,8 +218,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
217 | 218 | ||
218 | #region Add/Remove Agent/Avatar | 219 | #region Add/Remove Agent/Avatar |
219 | 220 | ||
220 | public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); | 221 | public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type); |
221 | public abstract void RemoveClient(UUID agentID, bool closeChildAgents); | 222 | |
223 | public abstract bool CloseAgent(UUID agentID, bool force); | ||
222 | 224 | ||
223 | public bool TryGetScenePresence(UUID agentID, out object scenePresence) | 225 | public bool TryGetScenePresence(UUID agentID, out object scenePresence) |
224 | { | 226 | { |
@@ -562,6 +564,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
562 | get { return false; } | 564 | get { return false; } |
563 | } | 565 | } |
564 | 566 | ||
567 | public virtual void Start() | ||
568 | { | ||
569 | } | ||
570 | |||
565 | public void Restart() | 571 | public void Restart() |
566 | { | 572 | { |
567 | // This has to be here to fire the event | 573 | // This has to be here to fire the event |
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 775a4c2..52f46f2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | |||
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
200 | /// This Closes child agents on neighboring regions | 200 | /// This Closes child agents on neighboring regions |
201 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 201 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
202 | /// </summary> | 202 | /// </summary> |
203 | protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) | 203 | protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token) |
204 | { | 204 | { |
205 | // let's do our best, but there's not much we can do if the neighbour doesn't accept. | 205 | // let's do our best, but there's not much we can do if the neighbour doesn't accept. |
206 | 206 | ||
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
209 | Utils.LongToUInts(regionHandle, out x, out y); | 209 | Utils.LongToUInts(regionHandle, out x, out y); |
210 | 210 | ||
211 | GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); | 211 | GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); |
212 | m_scene.SimulationService.CloseChildAgent(destination, agentID); | ||
213 | } | ||
214 | 212 | ||
215 | private void SendCloseChildAgentCompleted(IAsyncResult iar) | 213 | m_log.DebugFormat( |
216 | { | 214 | "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName); |
217 | SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; | 215 | |
218 | icon.EndInvoke(iar); | 216 | m_scene.SimulationService.CloseAgent(destination, agentID, auth_token); |
219 | } | 217 | } |
220 | 218 | ||
221 | public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) | 219 | /// <summary> |
220 | /// Closes a child agents in a collection of regions. Does so asynchronously | ||
221 | /// so that the caller doesn't wait. | ||
222 | /// </summary> | ||
223 | /// <param name="agentID"></param> | ||
224 | /// <param name="regionslst"></param> | ||
225 | public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst) | ||
222 | { | 226 | { |
223 | foreach (ulong handle in regionslst) | 227 | foreach (ulong handle in regionslst) |
224 | { | 228 | { |
225 | SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; | 229 | ulong handleCopy = handle; |
226 | d.BeginInvoke(agentID, handle, | 230 | Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); }); |
227 | SendCloseChildAgentCompleted, | ||
228 | d); | ||
229 | } | 231 | } |
230 | } | 232 | } |
231 | 233 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e599e90..b0f8991 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
631 | protected internal ScenePresence CreateAndAddChildScenePresence( | 631 | protected internal ScenePresence CreateAndAddChildScenePresence( |
632 | IClientAPI client, AvatarAppearance appearance, PresenceType type) | 632 | IClientAPI client, AvatarAppearance appearance, PresenceType type) |
633 | { | 633 | { |
634 | ScenePresence newAvatar = null; | ||
635 | |||
636 | // ScenePresence always defaults to child agent | 634 | // ScenePresence always defaults to child agent |
637 | newAvatar = new ScenePresence(client, m_parentScene, appearance, type); | 635 | ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type); |
638 | |||
639 | AddScenePresence(newAvatar); | ||
640 | |||
641 | return newAvatar; | ||
642 | } | ||
643 | |||
644 | /// <summary> | ||
645 | /// Add a presence to the scene | ||
646 | /// </summary> | ||
647 | /// <param name="presence"></param> | ||
648 | protected internal void AddScenePresence(ScenePresence presence) | ||
649 | { | ||
650 | // Always a child when added to the scene | ||
651 | bool child = presence.IsChildAgent; | ||
652 | |||
653 | if (child) | ||
654 | { | ||
655 | m_numChildAgents++; | ||
656 | } | ||
657 | else | ||
658 | { | ||
659 | m_numRootAgents++; | ||
660 | presence.AddToPhysicalScene(false); | ||
661 | } | ||
662 | 636 | ||
663 | Entities[presence.UUID] = presence; | 637 | Entities[presence.UUID] = presence; |
664 | 638 | ||
665 | m_scenePresencesLock.EnterWriteLock(); | 639 | m_scenePresencesLock.EnterWriteLock(); |
666 | try | 640 | try |
667 | { | 641 | { |
642 | m_numChildAgents++; | ||
643 | |||
668 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 644 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
669 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 645 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
670 | 646 | ||
@@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
675 | } | 651 | } |
676 | else | 652 | else |
677 | { | 653 | { |
678 | // Remember the old presene reference from the dictionary | 654 | // Remember the old presence reference from the dictionary |
679 | ScenePresence oldref = newmap[presence.UUID]; | 655 | ScenePresence oldref = newmap[presence.UUID]; |
680 | // Replace the presence reference in the dictionary with the new value | 656 | // Replace the presence reference in the dictionary with the new value |
681 | newmap[presence.UUID] = presence; | 657 | newmap[presence.UUID] = presence; |
@@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
691 | { | 667 | { |
692 | m_scenePresencesLock.ExitWriteLock(); | 668 | m_scenePresencesLock.ExitWriteLock(); |
693 | } | 669 | } |
670 | |||
671 | return presence; | ||
694 | } | 672 | } |
695 | 673 | ||
696 | /// <summary> | 674 | /// <summary> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index c70342f..c5c083a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs | |||
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
420 | return false; | 420 | return false; |
421 | } | 421 | } |
422 | 422 | ||
423 | /// <summary> | ||
424 | /// Set the debug packet level on each current scene. This level governs which packets are printed out to the | ||
425 | /// console. | ||
426 | /// </summary> | ||
427 | /// <param name="newDebug"></param> | ||
428 | /// <param name="name">Name of avatar to debug</param> | ||
429 | public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name) | ||
430 | { | ||
431 | ForEachSelectedScene(scene => | ||
432 | scene.ForEachScenePresence(sp => | ||
433 | { | ||
434 | if (name == null || sp.Name == name) | ||
435 | { | ||
436 | m_log.DebugFormat( | ||
437 | "Packet debug for {0} ({1}) set to {2}", | ||
438 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug); | ||
439 | |||
440 | sp.ControllingClient.DebugPacketLevel = newDebug; | ||
441 | } | ||
442 | }) | ||
443 | ); | ||
444 | } | ||
445 | |||
446 | public List<ScenePresence> GetCurrentSceneAvatars() | 423 | public List<ScenePresence> GetCurrentSceneAvatars() |
447 | { | 424 | { |
448 | List<ScenePresence> avatars = new List<ScenePresence>(); | 425 | List<ScenePresence> avatars = new List<ScenePresence>(); |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index f8624e7..8c50a81 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | |||
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
67 | { | 67 | { |
68 | int scriptsStarted = 0; | 68 | int scriptsStarted = 0; |
69 | 69 | ||
70 | if (m_scene == null) | ||
71 | { | ||
72 | m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances"); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
70 | // Don't start scripts if they're turned off in the region! | 76 | // Don't start scripts if they're turned off in the region! |
71 | if (!m_scene.RegionInfo.RegionSettings.DisableScripts) | 77 | if (!m_scene.RegionInfo.RegionSettings.DisableScripts) |
72 | { | 78 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 86f60bb..cfa862e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -111,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
111 | STATUS_ROTATE_Z = 0x008, | 111 | STATUS_ROTATE_Z = 0x008, |
112 | } | 112 | } |
113 | 113 | ||
114 | // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm | ||
115 | public static readonly uint SLAM = 16; | ||
116 | |||
114 | // private PrimCountTaintedDelegate handlerPrimCountTainted = null; | 117 | // private PrimCountTaintedDelegate handlerPrimCountTainted = null; |
115 | 118 | ||
116 | /// <summary> | 119 | /// <summary> |
@@ -506,9 +509,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
506 | { | 509 | { |
507 | return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); | 510 | return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); |
508 | } | 511 | } |
509 | 512 | ||
510 | |||
511 | |||
512 | private struct avtocrossInfo | 513 | private struct avtocrossInfo |
513 | { | 514 | { |
514 | public ScenePresence av; | 515 | public ScenePresence av; |
@@ -660,12 +661,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
660 | } | 661 | } |
661 | } | 662 | } |
662 | 663 | ||
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()) | 664 | if (RootPart.GetStatusSandbox()) |
670 | { | 665 | { |
671 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 666 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
@@ -751,7 +746,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
751 | } | 746 | } |
752 | 747 | ||
753 | agent.ParentUUID = UUID.Zero; | 748 | agent.ParentUUID = UUID.Zero; |
754 | |||
755 | // agent.Reset(); | 749 | // agent.Reset(); |
756 | // else // Not successful | 750 | // else // Not successful |
757 | // agent.RestoreInCurrentScene(); | 751 | // agent.RestoreInCurrentScene(); |
@@ -1667,7 +1661,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1667 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); | 1661 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); |
1668 | if (avatar == null) | 1662 | if (avatar == null) |
1669 | return; | 1663 | return; |
1670 | 1664 | m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State; | |
1665 | m_rootPart.AttachedPos = m_rootPart.OffsetPosition; | ||
1671 | avatar.RemoveAttachment(this); | 1666 | avatar.RemoveAttachment(this); |
1672 | 1667 | ||
1673 | Vector3 detachedpos = new Vector3(127f,127f,127f); | 1668 | Vector3 detachedpos = new Vector3(127f,127f,127f); |
@@ -1868,11 +1863,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1868 | /// <summary> | 1863 | /// <summary> |
1869 | /// Delete this group from its scene. | 1864 | /// Delete this group from its scene. |
1870 | /// </summary> | 1865 | /// </summary> |
1871 | /// | 1866 | /// <remarks> |
1872 | /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood | 1867 | /// 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 | 1868 | /// up and all avatars receive notification of its removal. Removal of the scene object from database backup |
1874 | /// must be handled by the caller. | 1869 | /// must be handled by the caller. |
1875 | /// | 1870 | /// </remarks> |
1876 | /// <param name="silent">If true then deletion is not broadcast to clients</param> | 1871 | /// <param name="silent">If true then deletion is not broadcast to clients</param> |
1877 | public void DeleteGroupFromScene(bool silent) | 1872 | public void DeleteGroupFromScene(bool silent) |
1878 | { | 1873 | { |
@@ -1901,7 +1896,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1901 | if (!IsAttachment | 1896 | if (!IsAttachment |
1902 | || AttachedAvatar == avatar.ControllingClient.AgentId | 1897 | || AttachedAvatar == avatar.ControllingClient.AgentId |
1903 | || !HasPrivateAttachmentPoint) | 1898 | || !HasPrivateAttachmentPoint) |
1904 | avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); | 1899 | avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); |
1905 | } | 1900 | } |
1906 | } | 1901 | } |
1907 | }); | 1902 | }); |
@@ -2109,6 +2104,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2109 | 2104 | ||
2110 | if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) | 2105 | if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) |
2111 | { | 2106 | { |
2107 | RootPart.Shape.LastAttachPoint = RootPart.Shape.State; | ||
2112 | RootPart.Shape.State = 0; | 2108 | RootPart.Shape.State = 0; |
2113 | ScheduleGroupForFullUpdate(); | 2109 | ScheduleGroupForFullUpdate(); |
2114 | } | 2110 | } |
@@ -2210,7 +2206,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2210 | if (!userExposed) | 2206 | if (!userExposed) |
2211 | dupe.IsAttachment = true; | 2207 | dupe.IsAttachment = true; |
2212 | 2208 | ||
2213 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); | 2209 | dupe.m_sittingAvatars = new List<UUID>(); |
2214 | 2210 | ||
2215 | if (!userExposed) | 2211 | if (!userExposed) |
2216 | { | 2212 | { |
@@ -3813,20 +3809,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3813 | /// <summary> | 3809 | /// <summary> |
3814 | /// Update just the root prim position in a linkset | 3810 | /// Update just the root prim position in a linkset |
3815 | /// </summary> | 3811 | /// </summary> |
3816 | /// <param name="pos"></param> | 3812 | /// <param name="newPos"></param> |
3817 | public void UpdateRootPosition(Vector3 pos) | 3813 | public void UpdateRootPosition(Vector3 newPos) |
3818 | { | 3814 | { |
3819 | // needs to be called with phys building true | 3815 | // needs to be called with phys building true |
3820 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3816 | Vector3 oldPos; |
3821 | Vector3 oldPos = | 3817 | |
3822 | new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, | 3818 | if (IsAttachment) |
3823 | AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, | 3819 | 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); | 3820 | else |
3821 | oldPos = AbsolutePosition + m_rootPart.OffsetPosition; | ||
3822 | |||
3825 | Vector3 diff = oldPos - newPos; | 3823 | Vector3 diff = oldPos - newPos; |
3826 | Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z); | ||
3827 | Quaternion partRotation = m_rootPart.RotationOffset; | 3824 | Quaternion partRotation = m_rootPart.RotationOffset; |
3828 | axDiff *= Quaternion.Inverse(partRotation); | 3825 | diff *= Quaternion.Inverse(partRotation); |
3829 | diff = axDiff; | ||
3830 | 3826 | ||
3831 | SceneObjectPart[] parts = m_parts.GetArray(); | 3827 | SceneObjectPart[] parts = m_parts.GetArray(); |
3832 | for (int i = 0; i < parts.Length; i++) | 3828 | for (int i = 0; i < parts.Length; i++) |
@@ -3837,6 +3833,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3837 | } | 3833 | } |
3838 | 3834 | ||
3839 | AbsolutePosition = newPos; | 3835 | AbsolutePosition = newPos; |
3836 | |||
3837 | if (IsAttachment) | ||
3838 | m_rootPart.AttachedPos = newPos; | ||
3840 | 3839 | ||
3841 | HasGroupChanged = true; | 3840 | HasGroupChanged = true; |
3842 | if (m_rootPart.Undoing) | 3841 | if (m_rootPart.Undoing) |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 261e958..ce9baaa 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
231 | 231 | ||
232 | public double SoundRadius; | 232 | public double SoundRadius; |
233 | 233 | ||
234 | /// <summary> | ||
235 | /// Should sounds played from this prim be queued? | ||
236 | /// </summary> | ||
237 | /// <remarks> | ||
238 | /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting. | ||
239 | /// </remarks> | ||
240 | public bool SoundQueueing { get; set; } | ||
234 | 241 | ||
235 | public uint TimeStampFull; | 242 | public uint TimeStampFull; |
236 | 243 | ||
@@ -383,8 +390,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
383 | 390 | ||
384 | private SOPVehicle m_vehicleParams = null; | 391 | private SOPVehicle m_vehicleParams = null; |
385 | 392 | ||
386 | private KeyframeMotion m_keyframeMotion = null; | ||
387 | |||
388 | public KeyframeMotion KeyframeMotion | 393 | public KeyframeMotion KeyframeMotion |
389 | { | 394 | { |
390 | get; set; | 395 | get; set; |
@@ -506,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
506 | { | 511 | { |
507 | get | 512 | get |
508 | { | 513 | { |
509 | if (CreatorData != null && CreatorData != string.Empty) | 514 | if (!string.IsNullOrEmpty(CreatorData)) |
510 | return CreatorID.ToString() + ';' + CreatorData; | 515 | return CreatorID.ToString() + ';' + CreatorData; |
511 | else | 516 | else |
512 | return CreatorID.ToString(); | 517 | return CreatorID.ToString(); |
@@ -536,7 +541,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
536 | CreatorID = uuid; | 541 | CreatorID = uuid; |
537 | } | 542 | } |
538 | if (parts.Length >= 2) | 543 | if (parts.Length >= 2) |
544 | { | ||
539 | CreatorData = parts[1]; | 545 | CreatorData = parts[1]; |
546 | if (!CreatorData.EndsWith("/")) | ||
547 | CreatorData += "/"; | ||
548 | } | ||
540 | if (parts.Length >= 3) | 549 | if (parts.Length >= 3) |
541 | name = parts[2]; | 550 | name = parts[2]; |
542 | 551 | ||
@@ -815,7 +824,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
815 | } | 824 | } |
816 | 825 | ||
817 | // Tell the physics engines that this prim changed. | 826 | // Tell the physics engines that this prim changed. |
818 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | 827 | if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null) |
828 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | ||
819 | } | 829 | } |
820 | catch (Exception e) | 830 | catch (Exception e) |
821 | { | 831 | { |
@@ -933,7 +943,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
933 | //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); | 943 | //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); |
934 | } | 944 | } |
935 | 945 | ||
936 | if (ParentGroup != null) | 946 | if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null) |
937 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | 947 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); |
938 | //} | 948 | //} |
939 | } | 949 | } |
@@ -1218,23 +1228,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1218 | // the mappings more consistant. | 1228 | // the mappings more consistant. |
1219 | public Vector3 SitTargetPositionLL | 1229 | public Vector3 SitTargetPositionLL |
1220 | { | 1230 | { |
1221 | get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } | 1231 | get { return m_sitTargetPosition; } |
1222 | set { m_sitTargetPosition = value; } | 1232 | set { m_sitTargetPosition = value; } |
1223 | } | 1233 | } |
1224 | 1234 | ||
1225 | public Quaternion SitTargetOrientationLL | 1235 | public Quaternion SitTargetOrientationLL |
1226 | { | 1236 | { |
1227 | get | 1237 | get { return m_sitTargetOrientation; } |
1228 | { | 1238 | set { m_sitTargetOrientation = value; } |
1229 | return new Quaternion( | ||
1230 | m_sitTargetOrientation.X, | ||
1231 | m_sitTargetOrientation.Y, | ||
1232 | m_sitTargetOrientation.Z, | ||
1233 | m_sitTargetOrientation.W | ||
1234 | ); | ||
1235 | } | ||
1236 | |||
1237 | set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); } | ||
1238 | } | 1239 | } |
1239 | 1240 | ||
1240 | public bool Stopped | 1241 | public bool Stopped |
@@ -2959,6 +2960,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2959 | //ParentGroup.RootPart.m_groupPosition = newpos; | 2960 | //ParentGroup.RootPart.m_groupPosition = newpos; |
2960 | } | 2961 | } |
2961 | 2962 | ||
2963 | if (pa != null && ParentID != 0 && ParentGroup != null) | ||
2964 | { | ||
2965 | // Special case where a child object is requesting property updates. | ||
2966 | // This happens when linksets are modified to use flexible links rather than | ||
2967 | // the default links. | ||
2968 | // The simulator code presumes that child parts are only modified by scripts | ||
2969 | // so the logic for changing position/rotation/etc does not take into | ||
2970 | // account the physical object actually moving. | ||
2971 | // This code updates the offset position and rotation of the child and then | ||
2972 | // lets the update code push the update to the viewer. | ||
2973 | // Since physics engines do not normally generate this event for linkset children, | ||
2974 | // this code will not be active unless you have a specially configured | ||
2975 | // physics engine. | ||
2976 | Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset)); | ||
2977 | m_offsetPosition = pa.Position - m_groupPosition; | ||
2978 | RotationOffset = pa.Orientation * invRootRotation; | ||
2979 | // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", | ||
2980 | // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); | ||
2981 | } | ||
2982 | |||
2962 | ScheduleTerseUpdate(); | 2983 | ScheduleTerseUpdate(); |
2963 | } | 2984 | } |
2964 | 2985 | ||
@@ -3137,7 +3158,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3137 | return; | 3158 | return; |
3138 | 3159 | ||
3139 | // This was pulled from SceneViewer. Attachments always receive full updates. | 3160 | // This was pulled from SceneViewer. Attachments always receive full updates. |
3140 | // I could not verify if this is a requirement but this maintains existing behavior | 3161 | // This is needed because otherwise if only the root prim changes position, then |
3162 | // it looks as if the entire object has moved (including the other prims). | ||
3141 | if (ParentGroup.IsAttachment) | 3163 | if (ParentGroup.IsAttachment) |
3142 | { | 3164 | { |
3143 | ScheduleFullUpdate(); | 3165 | ScheduleFullUpdate(); |
@@ -4350,30 +4372,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
4350 | } | 4372 | } |
4351 | } | 4373 | } |
4352 | 4374 | ||
4353 | public void UpdateGroupPosition(Vector3 pos) | 4375 | public void UpdateGroupPosition(Vector3 newPos) |
4354 | { | 4376 | { |
4355 | if ((pos.X != GroupPosition.X) || | 4377 | Vector3 oldPos = GroupPosition; |
4356 | (pos.Y != GroupPosition.Y) || | 4378 | |
4357 | (pos.Z != GroupPosition.Z)) | 4379 | if ((newPos.X != oldPos.X) || |
4380 | (newPos.Y != oldPos.Y) || | ||
4381 | (newPos.Z != oldPos.Z)) | ||
4358 | { | 4382 | { |
4359 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | ||
4360 | GroupPosition = newPos; | 4383 | GroupPosition = newPos; |
4361 | ScheduleTerseUpdate(); | 4384 | ScheduleTerseUpdate(); |
4362 | } | 4385 | } |
4363 | } | 4386 | } |
4364 | 4387 | ||
4365 | /// <summary> | 4388 | /// <summary> |
4366 | /// | 4389 | /// Update this part's offset position. |
4367 | /// </summary> | 4390 | /// </summary> |
4368 | /// <param name="pos"></param> | 4391 | /// <param name="pos"></param> |
4369 | public void UpdateOffSet(Vector3 pos) | 4392 | public void UpdateOffSet(Vector3 newPos) |
4370 | { | 4393 | { |
4371 | if ((pos.X != OffsetPosition.X) || | 4394 | Vector3 oldPos = OffsetPosition; |
4372 | (pos.Y != OffsetPosition.Y) || | ||
4373 | (pos.Z != OffsetPosition.Z)) | ||
4374 | { | ||
4375 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | ||
4376 | 4395 | ||
4396 | if ((newPos.X != oldPos.X) || | ||
4397 | (newPos.Y != oldPos.Y) || | ||
4398 | (newPos.Z != oldPos.Z)) | ||
4399 | { | ||
4377 | if (ParentGroup.RootPart.GetStatusSandbox()) | 4400 | if (ParentGroup.RootPart.GetStatusSandbox()) |
4378 | { | 4401 | { |
4379 | if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) | 4402 | if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) |
@@ -4520,7 +4543,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4520 | // For now, we use the NINJA naming scheme for identifying joints. | 4543 | // For now, we use the NINJA naming scheme for identifying joints. |
4521 | // In the future, we can support other joint specification schemes such as a | 4544 | // In the future, we can support other joint specification schemes such as a |
4522 | // custom checkbox in the viewer GUI. | 4545 | // custom checkbox in the viewer GUI. |
4523 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | 4546 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) |
4524 | { | 4547 | { |
4525 | return IsHingeJoint() || IsBallJoint(); | 4548 | return IsHingeJoint() || IsBallJoint(); |
4526 | } | 4549 | } |
@@ -4642,6 +4665,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
4642 | } | 4665 | } |
4643 | } | 4666 | } |
4644 | */ | 4667 | */ |
4668 | if (pa != null) | ||
4669 | { | ||
4670 | pa.SetMaterial(Material); | ||
4671 | DoPhysicsPropertyUpdate(UsePhysics, true); | ||
4672 | } | ||
4645 | } | 4673 | } |
4646 | else // it already has a physical representation | 4674 | else // it already has a physical representation |
4647 | { | 4675 | { |
@@ -5014,6 +5042,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
5014 | oldTex.DefaultTexture = fallbackOldFace; | 5042 | oldTex.DefaultTexture = fallbackOldFace; |
5015 | } | 5043 | } |
5016 | 5044 | ||
5045 | // Materials capable viewers can send a ObjectImage packet | ||
5046 | // when nothing in TE has changed. MaterialID should be updated | ||
5047 | // by the RenderMaterials CAP handler, so updating it here may cause a | ||
5048 | // race condtion. Therefore, if no non-materials TE fields have changed, | ||
5049 | // we should ignore any changes and not update Shape.TextureEntry | ||
5050 | |||
5051 | bool otherFieldsChanged = false; | ||
5052 | |||
5017 | for (int i = 0 ; i < GetNumberOfSides(); i++) | 5053 | for (int i = 0 ; i < GetNumberOfSides(); i++) |
5018 | { | 5054 | { |
5019 | 5055 | ||
@@ -5040,18 +5076,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
5040 | // Max change, skip the rest of testing | 5076 | // Max change, skip the rest of testing |
5041 | if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) | 5077 | if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) |
5042 | break; | 5078 | break; |
5079 | |||
5080 | if (!otherFieldsChanged) | ||
5081 | { | ||
5082 | if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true; | ||
5083 | if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true; | ||
5084 | if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true; | ||
5085 | if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true; | ||
5086 | if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true; | ||
5087 | if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true; | ||
5088 | if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true; | ||
5089 | if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true; | ||
5090 | if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true; | ||
5091 | if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true; | ||
5092 | if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true; | ||
5093 | } | ||
5043 | } | 5094 | } |
5044 | 5095 | ||
5045 | m_shape.TextureEntry = newTex.GetBytes(); | 5096 | if (changeFlags != 0 || otherFieldsChanged) |
5046 | if (changeFlags != 0) | 5097 | { |
5047 | TriggerScriptChangedEvent(changeFlags); | 5098 | m_shape.TextureEntry = newTex.GetBytes(); |
5048 | UpdateFlag = UpdateRequired.FULL; | 5099 | if (changeFlags != 0) |
5049 | ParentGroup.HasGroupChanged = true; | 5100 | TriggerScriptChangedEvent(changeFlags); |
5101 | UpdateFlag = UpdateRequired.FULL; | ||
5102 | ParentGroup.HasGroupChanged = true; | ||
5050 | 5103 | ||
5051 | //This is madness.. | 5104 | //This is madness.. |
5052 | //ParentGroup.ScheduleGroupForFullUpdate(); | 5105 | //ParentGroup.ScheduleGroupForFullUpdate(); |
5053 | //This is sparta | 5106 | //This is sparta |
5054 | ScheduleFullUpdate(); | 5107 | ScheduleFullUpdate(); |
5108 | } | ||
5055 | } | 5109 | } |
5056 | 5110 | ||
5057 | 5111 | ||
@@ -5239,6 +5293,64 @@ namespace OpenSim.Region.Framework.Scenes | |||
5239 | { | 5293 | { |
5240 | ParentGroup.AddScriptLPS(count); | 5294 | ParentGroup.AddScriptLPS(count); |
5241 | } | 5295 | } |
5296 | |||
5297 | /// <summary> | ||
5298 | /// Sets a prim's owner and permissions when it's rezzed. | ||
5299 | /// </summary> | ||
5300 | /// <param name="item">The inventory item from which the item was rezzed</param> | ||
5301 | /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param> | ||
5302 | /// <param name="scene">The scene the prim is being rezzed into</param> | ||
5303 | public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene) | ||
5304 | { | ||
5305 | if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)) | ||
5306 | { | ||
5307 | if (scene.Permissions.PropagatePermissions()) | ||
5308 | { | ||
5309 | if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) | ||
5310 | { | ||
5311 | // Apply the item's permissions to the object | ||
5312 | //LogPermissions("Before applying item permissions"); | ||
5313 | if (userInventory) | ||
5314 | { | ||
5315 | EveryoneMask = item.EveryOnePermissions; | ||
5316 | NextOwnerMask = item.NextPermissions; | ||
5317 | } | ||
5318 | else | ||
5319 | { | ||
5320 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | ||
5321 | EveryoneMask = item.EveryOnePermissions; | ||
5322 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) | ||
5323 | NextOwnerMask = item.NextPermissions; | ||
5324 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | ||
5325 | GroupMask = item.GroupPermissions; | ||
5326 | } | ||
5327 | //LogPermissions("After applying item permissions"); | ||
5328 | } | ||
5329 | } | ||
5330 | |||
5331 | GroupMask = 0; // DO NOT propagate here | ||
5332 | } | ||
5333 | |||
5334 | if (OwnerID != item.Owner) | ||
5335 | { | ||
5336 | //LogPermissions("Before ApplyNextOwnerPermissions"); | ||
5337 | ApplyNextOwnerPermissions(); | ||
5338 | //LogPermissions("After ApplyNextOwnerPermissions"); | ||
5339 | |||
5340 | LastOwnerID = OwnerID; | ||
5341 | OwnerID = item.Owner; | ||
5342 | Inventory.ChangeInventoryOwner(item.Owner); | ||
5343 | } | ||
5344 | } | ||
5345 | |||
5346 | /// <summary> | ||
5347 | /// Logs the prim's permissions. Useful when debugging permission problems. | ||
5348 | /// </summary> | ||
5349 | /// <param name="message"></param> | ||
5350 | private void LogPermissions(String message) | ||
5351 | { | ||
5352 | PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask); | ||
5353 | } | ||
5242 | 5354 | ||
5243 | public void ApplyNextOwnerPermissions() | 5355 | public void ApplyNextOwnerPermissions() |
5244 | { | 5356 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d04d87b..8893cc0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | |||
@@ -696,7 +696,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
696 | /// </param> | 696 | /// </param> |
697 | public void StopScriptInstance(TaskInventoryItem item) | 697 | public void StopScriptInstance(TaskInventoryItem item) |
698 | { | 698 | { |
699 | m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); | 699 | if (m_part.ParentGroup.Scene != null) |
700 | m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); | ||
700 | 701 | ||
701 | // At the moment, even stopped scripts are counted as active, which is probably wrong. | 702 | // At the moment, even stopped scripts are counted as active, which is probably wrong. |
702 | // m_part.ParentGroup.AddActiveScriptCount(-1); | 703 | // m_part.ParentGroup.AddActiveScriptCount(-1); |
@@ -880,8 +881,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
880 | 881 | ||
881 | return items; | 882 | return items; |
882 | } | 883 | } |
883 | 884 | ||
884 | public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) | 885 | public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist) |
885 | { | 886 | { |
886 | AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); | 887 | AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); |
887 | 888 | ||
@@ -890,70 +891,58 @@ namespace OpenSim.Region.Framework.Scenes | |||
890 | m_log.WarnFormat( | 891 | m_log.WarnFormat( |
891 | "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", | 892 | "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", |
892 | item.AssetID, item.Name, m_part.Name); | 893 | item.AssetID, item.Name, m_part.Name); |
893 | return null; | 894 | objlist = null; |
895 | veclist = null; | ||
896 | return false; | ||
894 | } | 897 | } |
895 | 898 | ||
896 | string xmlData = Utils.BytesToString(rezAsset.Data); | 899 | Vector3 bbox; |
897 | SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | 900 | float offsetHeight; |
898 | 901 | ||
899 | group.RootPart.AttachPoint = group.RootPart.Shape.State; | 902 | 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 | 903 | ||
903 | group.ResetIDs(); | 904 | for (int i = 0; i < objlist.Count; i++) |
904 | 905 | { | |
905 | SceneObjectPart rootPart = group.GetPart(group.UUID); | 906 | SceneObjectGroup group = objlist[i]; |
906 | 907 | ||
907 | // Since renaming the item in the inventory does not affect the name stored | 908 | group.RootPart.AttachPoint = group.RootPart.Shape.State; |
908 | // in the serialization, transfer the correct name from the inventory to the | 909 | group.RootPart.AttachOffset = group.AbsolutePosition; |
909 | // object itself before we rez. | 910 | group.RootPart.AttachRotation = group.GroupRotation; |
910 | rootPart.Name = item.Name; | ||
911 | rootPart.Description = item.Description; | ||
912 | 911 | ||
913 | SceneObjectPart[] partList = group.Parts; | 912 | group.ResetIDs(); |
914 | 913 | ||
915 | group.SetGroup(m_part.GroupID, null); | 914 | SceneObjectPart rootPart = group.GetPart(group.UUID); |
916 | 915 | ||
917 | // TODO: Remove magic number badness | 916 | // Since renaming the item in the inventory does not affect the name stored |
918 | if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number | 917 | // in the serialization, transfer the correct name from the inventory to the |
919 | { | 918 | // object itself before we rez. |
920 | if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) | 919 | // Only do these for the first object if we are rezzing a coalescence. |
920 | if (i == 0) | ||
921 | { | 921 | { |
922 | foreach (SceneObjectPart part in partList) | 922 | rootPart.Name = item.Name; |
923 | { | 923 | rootPart.Description = item.Description; |
924 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | ||
925 | part.EveryoneMask = item.EveryonePermissions; | ||
926 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) | ||
927 | part.NextOwnerMask = item.NextPermissions; | ||
928 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | ||
929 | part.GroupMask = item.GroupPermissions; | ||
930 | } | ||
931 | |||
932 | group.ApplyNextOwnerPermissions(); | ||
933 | } | 924 | } |
934 | } | ||
935 | 925 | ||
936 | foreach (SceneObjectPart part in partList) | 926 | group.SetGroup(m_part.GroupID, null); |
937 | { | 927 | |
938 | // TODO: Remove magic number badness | 928 | foreach (SceneObjectPart part in group.Parts) |
939 | if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number | ||
940 | { | 929 | { |
941 | part.LastOwnerID = part.OwnerID; | 930 | // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :) |
942 | part.OwnerID = item.OwnerID; | 931 | InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID); |
943 | part.Inventory.ChangeInventoryOwner(item.OwnerID); | 932 | dest.BasePermissions = item.BasePermissions; |
933 | dest.CurrentPermissions = item.CurrentPermissions; | ||
934 | dest.EveryOnePermissions = item.EveryonePermissions; | ||
935 | dest.GroupPermissions = item.GroupPermissions; | ||
936 | dest.NextPermissions = item.NextPermissions; | ||
937 | dest.Flags = item.Flags; | ||
938 | |||
939 | part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); | ||
944 | } | 940 | } |
945 | 941 | ||
946 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | 942 | 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 | } | 943 | } |
953 | 944 | ||
954 | rootPart.TrimPermissions(); | 945 | return true; |
955 | |||
956 | return group; | ||
957 | } | 946 | } |
958 | 947 | ||
959 | /// <summary> | 948 | /// <summary> |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7004d23..f57d4fe 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -29,7 +29,9 @@ using System; | |||
29 | using System.Xml; | 29 | using System.Xml; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
32 | using System.Timers; | 33 | using System.Timers; |
34 | using Timer = System.Timers.Timer; | ||
33 | using OpenMetaverse; | 35 | using OpenMetaverse; |
34 | using log4net; | 36 | using log4net; |
35 | using Nini.Config; | 37 | using Nini.Config; |
@@ -73,21 +75,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
73 | 75 | ||
74 | public class ScenePresence : EntityBase, IScenePresence | 76 | public class ScenePresence : EntityBase, IScenePresence |
75 | { | 77 | { |
78 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
79 | |||
76 | // ~ScenePresence() | 80 | // ~ScenePresence() |
77 | // { | 81 | // { |
78 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); | 82 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); |
79 | // } | 83 | // } |
80 | 84 | ||
81 | private void TriggerScenePresenceUpdated() | 85 | public void TriggerScenePresenceUpdated() |
82 | { | 86 | { |
83 | if (m_scene != null) | 87 | if (m_scene != null) |
84 | m_scene.EventManager.TriggerScenePresenceUpdated(this); | 88 | m_scene.EventManager.TriggerScenePresenceUpdated(this); |
85 | } | 89 | } |
86 | 90 | ||
87 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
88 | |||
89 | public PresenceType PresenceType { get; private set; } | 91 | public PresenceType PresenceType { get; private set; } |
90 | 92 | ||
93 | private ScenePresenceStateMachine m_stateMachine; | ||
94 | |||
95 | /// <summary> | ||
96 | /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine | ||
97 | /// for more details. | ||
98 | /// </summary> | ||
99 | public ScenePresenceState LifecycleState | ||
100 | { | ||
101 | get | ||
102 | { | ||
103 | return m_stateMachine.GetState(); | ||
104 | } | ||
105 | |||
106 | set | ||
107 | { | ||
108 | m_stateMachine.SetState(value); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | /// <summary> | ||
113 | /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and | ||
114 | /// the viewer fires these in quick succession. | ||
115 | /// </summary> | ||
116 | /// <remarks> | ||
117 | /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement | ||
118 | /// regulation done there. | ||
119 | /// </remarks> | ||
120 | private object m_completeMovementLock = new object(); | ||
121 | |||
91 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); | 122 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); |
92 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); | 123 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); |
93 | private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); | 124 | private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); |
@@ -142,6 +173,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
142 | private Vector3 m_lastVelocity; | 173 | private Vector3 m_lastVelocity; |
143 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); | 174 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); |
144 | 175 | ||
176 | private bool m_followCamAuto = false; | ||
177 | |||
145 | 178 | ||
146 | private Vector3? m_forceToApply; | 179 | private Vector3? m_forceToApply; |
147 | private int m_userFlags; | 180 | private int m_userFlags; |
@@ -200,7 +233,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
200 | private float m_sitAvatarHeight = 2.0f; | 233 | private float m_sitAvatarHeight = 2.0f; |
201 | 234 | ||
202 | private Vector3 m_lastChildAgentUpdatePosition; | 235 | private Vector3 m_lastChildAgentUpdatePosition; |
203 | private Vector3 m_lastChildAgentUpdateCamPosition; | 236 | // private Vector3 m_lastChildAgentUpdateCamPosition; |
204 | 237 | ||
205 | private const int LAND_VELOCITYMAG_MAX = 12; | 238 | private const int LAND_VELOCITYMAG_MAX = 12; |
206 | 239 | ||
@@ -290,9 +323,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
290 | /// </summary> | 323 | /// </summary> |
291 | private Vector3 posLastSignificantMove; | 324 | private Vector3 posLastSignificantMove; |
292 | 325 | ||
293 | // For teleports and crossings callbacks | 326 | #region For teleports and crossings callbacks |
294 | string m_callbackURI; | 327 | |
295 | UUID m_originRegionID; | 328 | /// <summary> |
329 | /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address. | ||
330 | /// </summary> | ||
331 | private string m_callbackURI; | ||
332 | |||
333 | /// <summary> | ||
334 | /// Records the region from which this presence originated, if not from login. | ||
335 | /// </summary> | ||
336 | /// <remarks> | ||
337 | /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered | ||
338 | /// CompleteMovement and made the previous child agent a root agent. | ||
339 | /// </remarks> | ||
340 | private UUID m_originRegionID; | ||
341 | |||
342 | /// <summary> | ||
343 | /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing | ||
344 | /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as | ||
345 | /// it is a value type. | ||
346 | /// </summary> | ||
347 | private object m_originRegionIDAccessLock = new object(); | ||
348 | |||
349 | /// <summary> | ||
350 | /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent | ||
351 | /// teleport is reusing the connection. | ||
352 | /// </summary> | ||
353 | /// <remarks>May be refactored or move somewhere else soon.</remarks> | ||
354 | public bool DoNotCloseAfterTeleport { get; set; } | ||
355 | |||
356 | #endregion | ||
296 | 357 | ||
297 | /// <value> | 358 | /// <value> |
298 | /// Script engines present in the scene | 359 | /// Script engines present in the scene |
@@ -309,15 +370,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
309 | /// <summary> | 370 | /// <summary> |
310 | /// Record user movement inputs. | 371 | /// Record user movement inputs. |
311 | /// </summary> | 372 | /// </summary> |
312 | public byte MovementFlag { get; private set; } | 373 | public uint MovementFlag { get; private set; } |
313 | 374 | ||
314 | private bool m_updateflag; | 375 | /// <summary> |
315 | 376 | /// Is the agent stop control flag currently active? | |
316 | public bool Updated | 377 | /// </summary> |
317 | { | 378 | public bool AgentControlStopActive { get; private set; } |
318 | set { m_updateflag = value; } | ||
319 | get { return m_updateflag; } | ||
320 | } | ||
321 | 379 | ||
322 | private bool m_invulnerable = true; | 380 | private bool m_invulnerable = true; |
323 | 381 | ||
@@ -462,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
462 | } | 520 | } |
463 | else | 521 | else |
464 | { | 522 | { |
523 | // m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name); | ||
465 | // Obtain the correct position of a seated avatar. | 524 | // Obtain the correct position of a seated avatar. |
466 | // In addition to providing the correct position while | 525 | // In addition to providing the correct position while |
467 | // the avatar is seated, this value will also | 526 | // the avatar is seated, this value will also |
@@ -485,7 +544,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
485 | } | 544 | } |
486 | set | 545 | set |
487 | { | 546 | { |
488 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); | 547 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name); |
489 | // Util.PrintCallStack(); | 548 | // Util.PrintCallStack(); |
490 | 549 | ||
491 | if (PhysicsActor != null) | 550 | if (PhysicsActor != null) |
@@ -502,10 +561,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
502 | 561 | ||
503 | // Don't update while sitting. The PhysicsActor above is null whilst sitting. | 562 | // Don't update while sitting. The PhysicsActor above is null whilst sitting. |
504 | if (ParentID == 0) | 563 | if (ParentID == 0) |
505 | { | ||
506 | m_pos = value; | 564 | m_pos = value; |
507 | // ParentPosition = Vector3.Zero; | ||
508 | } | ||
509 | 565 | ||
510 | //m_log.DebugFormat( | 566 | //m_log.DebugFormat( |
511 | // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", | 567 | // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", |
@@ -768,6 +824,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
768 | set { m_speedModifier = value; } | 824 | set { m_speedModifier = value; } |
769 | } | 825 | } |
770 | 826 | ||
827 | /// <summary> | ||
828 | /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running | ||
829 | /// </summary> | ||
830 | /// <remarks> | ||
831 | /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. | ||
832 | /// </remarks> | ||
833 | private float AgentControlStopSlowWhilstMoving = 0.5f; | ||
834 | |||
771 | private bool m_forceFly; | 835 | private bool m_forceFly; |
772 | 836 | ||
773 | public bool ForceFly | 837 | public bool ForceFly |
@@ -795,7 +859,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
795 | 859 | ||
796 | public ScenePresence( | 860 | public ScenePresence( |
797 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) | 861 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) |
798 | { | 862 | { |
799 | AttachmentsSyncLock = new Object(); | 863 | AttachmentsSyncLock = new Object(); |
800 | AllowMovement = true; | 864 | AllowMovement = true; |
801 | IsChildAgent = true; | 865 | IsChildAgent = true; |
@@ -841,6 +905,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
841 | SetDirectionVectors(); | 905 | SetDirectionVectors(); |
842 | 906 | ||
843 | Appearance = appearance; | 907 | Appearance = appearance; |
908 | |||
909 | m_stateMachine = new ScenePresenceStateMachine(this); | ||
844 | } | 910 | } |
845 | 911 | ||
846 | private void RegionHeartbeatEnd(Scene scene) | 912 | private void RegionHeartbeatEnd(Scene scene) |
@@ -874,6 +940,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
874 | { | 940 | { |
875 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; | 941 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; |
876 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; | 942 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; |
943 | ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate; | ||
877 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; | 944 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; |
878 | ControllingClient.OnAgentSit += HandleAgentSit; | 945 | ControllingClient.OnAgentSit += HandleAgentSit; |
879 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; | 946 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; |
@@ -927,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
927 | /// <summary> | 994 | /// <summary> |
928 | /// Turns a child agent into a root agent. | 995 | /// Turns a child agent into a root agent. |
929 | /// </summary> | 996 | /// </summary> |
997 | /// <remarks> | ||
930 | /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the | 998 | /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the |
931 | /// avatar is actual in the sim. They can perform all actions. | 999 | /// avatar is actual in the sim. They can perform all actions. |
932 | /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, | 1000 | /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, |
@@ -934,48 +1002,56 @@ namespace OpenSim.Region.Framework.Scenes | |||
934 | /// | 1002 | /// |
935 | /// This method is on the critical path for transferring an avatar from one region to another. Delay here | 1003 | /// This method is on the critical path for transferring an avatar from one region to another. Delay here |
936 | /// delays that crossing. | 1004 | /// delays that crossing. |
937 | /// </summary> | 1005 | /// </remarks> |
938 | public void MakeRootAgent(Vector3 pos, bool isFlying) | 1006 | private bool MakeRootAgent(Vector3 pos, bool isFlying) |
939 | { | 1007 | { |
940 | m_log.DebugFormat( | 1008 | lock (m_completeMovementLock) |
941 | "[SCENE]: Upgrading child to root agent for {0} in {1}", | ||
942 | Name, m_scene.RegionInfo.RegionName); | ||
943 | |||
944 | if (ParentUUID != UUID.Zero) | ||
945 | { | 1009 | { |
946 | m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); | 1010 | if (!IsChildAgent) |
947 | SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); | 1011 | return false; |
948 | if (part == null) | 1012 | |
1013 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | ||
1014 | |||
1015 | // m_log.InfoFormat( | ||
1016 | // "[SCENE]: Upgrading child to root agent for {0} in {1}", | ||
1017 | // Name, m_scene.RegionInfo.RegionName); | ||
1018 | |||
1019 | if (ParentUUID != UUID.Zero) | ||
949 | { | 1020 | { |
950 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); | 1021 | m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); |
1022 | SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); | ||
1023 | if (part == null) | ||
1024 | { | ||
1025 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); | ||
1026 | } | ||
1027 | else | ||
1028 | { | ||
1029 | part.ParentGroup.AddAvatar(UUID); | ||
1030 | if (part.SitTargetPosition != Vector3.Zero) | ||
1031 | part.SitTargetAvatar = UUID; | ||
1032 | // ParentPosition = part.GetWorldPosition(); | ||
1033 | ParentID = part.LocalId; | ||
1034 | ParentPart = part; | ||
1035 | m_pos = PrevSitOffset; | ||
1036 | // pos = ParentPosition; | ||
1037 | pos = part.GetWorldPosition(); | ||
1038 | } | ||
1039 | ParentUUID = UUID.Zero; | ||
1040 | |||
1041 | // Animator.TrySetMovementAnimation("SIT"); | ||
951 | } | 1042 | } |
952 | else | 1043 | else |
953 | { | 1044 | { |
954 | part.ParentGroup.AddAvatar(UUID); | 1045 | IsLoggingIn = false; |
955 | if (part.SitTargetPosition != Vector3.Zero) | ||
956 | part.SitTargetAvatar = UUID; | ||
957 | // ParentPosition = part.GetWorldPosition(); | ||
958 | ParentID = part.LocalId; | ||
959 | ParentPart = part; | ||
960 | m_pos = PrevSitOffset; | ||
961 | // pos = ParentPosition; | ||
962 | pos = part.GetWorldPosition(); | ||
963 | } | 1046 | } |
964 | ParentUUID = UUID.Zero; | ||
965 | 1047 | ||
966 | IsChildAgent = false; | 1048 | IsChildAgent = false; |
967 | |||
968 | // Animator.TrySetMovementAnimation("SIT"); | ||
969 | } | 1049 | } |
970 | else | ||
971 | { | ||
972 | IsChildAgent = false; | ||
973 | IsLoggingIn = false; | ||
974 | } | ||
975 | |||
976 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | ||
977 | 1050 | ||
978 | IsChildAgent = false; | 1051 | // Must reset this here so that a teleport to a region next to an existing region does not keep the flag |
1052 | // set and prevent the close of the connection on a subsequent re-teleport. | ||
1053 | // Should not be needed if we are not trying to tell this region to close | ||
1054 | // DoNotCloseAfterTeleport = false; | ||
979 | 1055 | ||
980 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 1056 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
981 | if (gm != null) | 1057 | if (gm != null) |
@@ -1116,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
1116 | // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently | 1192 | // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently |
1117 | // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are | 1193 | // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are |
1118 | // not transporting the required data. | 1194 | // not transporting the required data. |
1119 | lock (m_attachments) | 1195 | // |
1196 | // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT | ||
1197 | // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently | ||
1198 | // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are | ||
1199 | // not transporting the required data. | ||
1200 | // | ||
1201 | // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of | ||
1202 | // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here | ||
1203 | // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status. | ||
1204 | // | ||
1205 | // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts(). | ||
1206 | // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing | ||
1207 | // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the | ||
1208 | // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine. | ||
1209 | // | ||
1210 | // One cannot simply iterate over attachments in a fire and forget thread because this would no longer | ||
1211 | // be locked, allowing race conditions if other code changes the attachments list. | ||
1212 | List<SceneObjectGroup> attachments = GetAttachments(); | ||
1213 | |||
1214 | if (attachments.Count > 0) | ||
1120 | { | 1215 | { |
1121 | if (HasAttachments()) | 1216 | m_log.DebugFormat( |
1122 | { | 1217 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); |
1123 | m_log.DebugFormat( | ||
1124 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | ||
1125 | 1218 | ||
1126 | // Resume scripts | 1219 | // Resume scripts |
1127 | Util.FireAndForget(delegate(object x) { | 1220 | foreach (SceneObjectGroup sog in attachments) |
1128 | foreach (SceneObjectGroup sog in m_attachments) | 1221 | { |
1129 | { | 1222 | sog.ScheduleGroupForFullUpdate(); |
1130 | sog.ScheduleGroupForFullUpdate(); | 1223 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); |
1131 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | 1224 | sog.ResumeScripts(); |
1132 | sog.ResumeScripts(); | ||
1133 | } | ||
1134 | }); | ||
1135 | } | 1225 | } |
1136 | } | 1226 | } |
1137 | } | 1227 | } |
@@ -1153,7 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1153 | 1243 | ||
1154 | m_scene.EventManager.TriggerOnMakeRootAgent(this); | 1244 | m_scene.EventManager.TriggerOnMakeRootAgent(this); |
1155 | 1245 | ||
1156 | m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; | 1246 | return true; |
1157 | } | 1247 | } |
1158 | 1248 | ||
1159 | public int GetStateSource() | 1249 | public int GetStateSource() |
@@ -1306,7 +1396,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
1306 | 1396 | ||
1307 | public void StopFlying() | 1397 | public void StopFlying() |
1308 | { | 1398 | { |
1309 | ControllingClient.StopFlying(this); | 1399 | Vector3 pos = AbsolutePosition; |
1400 | if (Appearance.AvatarHeight != 127.0f) | ||
1401 | pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); | ||
1402 | else | ||
1403 | pos += new Vector3(0f, 0f, (1.56f / 6f)); | ||
1404 | |||
1405 | AbsolutePosition = pos; | ||
1406 | |||
1407 | // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. | ||
1408 | // Collision plane below the avatar's position a 6th of the avatar's height is suitable. | ||
1409 | // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a | ||
1410 | // certain amount.. because the LLClient wouldn't land in that situation anyway. | ||
1411 | |||
1412 | // why are we still testing for this really old height value default??? | ||
1413 | if (Appearance.AvatarHeight != 127.0f) | ||
1414 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f); | ||
1415 | else | ||
1416 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); | ||
1417 | |||
1418 | ControllingClient.SendAgentTerseUpdate(this); | ||
1310 | } | 1419 | } |
1311 | 1420 | ||
1312 | /// <summary> | 1421 | /// <summary> |
@@ -1480,6 +1589,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
1480 | 1589 | ||
1481 | } | 1590 | } |
1482 | 1591 | ||
1592 | private bool WaitForUpdateAgent(IClientAPI client) | ||
1593 | { | ||
1594 | // Before the source region executes UpdateAgent | ||
1595 | // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, | ||
1596 | // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the | ||
1597 | // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero | ||
1598 | int count = 50; | ||
1599 | UUID originID; | ||
1600 | |||
1601 | lock (m_originRegionIDAccessLock) | ||
1602 | originID = m_originRegionID; | ||
1603 | |||
1604 | while (originID.Equals(UUID.Zero) && count-- > 0) | ||
1605 | { | ||
1606 | lock (m_originRegionIDAccessLock) | ||
1607 | originID = m_originRegionID; | ||
1608 | |||
1609 | m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name); | ||
1610 | Thread.Sleep(200); | ||
1611 | } | ||
1612 | |||
1613 | if (originID.Equals(UUID.Zero)) | ||
1614 | { | ||
1615 | // Movement into region will fail | ||
1616 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); | ||
1617 | return false; | ||
1618 | } | ||
1619 | |||
1620 | return true; | ||
1621 | } | ||
1622 | |||
1483 | /// <summary> | 1623 | /// <summary> |
1484 | /// Complete Avatar's movement into the region. | 1624 | /// Complete Avatar's movement into the region. |
1485 | /// </summary> | 1625 | /// </summary> |
@@ -1493,9 +1633,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1493 | { | 1633 | { |
1494 | // DateTime startTime = DateTime.Now; | 1634 | // DateTime startTime = DateTime.Now; |
1495 | 1635 | ||
1496 | m_log.DebugFormat( | 1636 | m_log.InfoFormat( |
1497 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", | 1637 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", |
1498 | client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); | 1638 | client.Name, Scene.Name, AbsolutePosition); |
1639 | |||
1640 | // Make sure it's not a login agent. We don't want to wait for updates during login | ||
1641 | if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) | ||
1642 | { | ||
1643 | // Let's wait until UpdateAgent (called by departing region) is done | ||
1644 | if (!WaitForUpdateAgent(client)) | ||
1645 | // The sending region never sent the UpdateAgent data, we have to refuse | ||
1646 | return; | ||
1647 | } | ||
1499 | 1648 | ||
1500 | Vector3 look = Velocity; | 1649 | Vector3 look = Velocity; |
1501 | 1650 | ||
@@ -1517,12 +1666,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
1517 | } | 1666 | } |
1518 | 1667 | ||
1519 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1668 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1520 | MakeRootAgent(AbsolutePosition, flying); | 1669 | if (!MakeRootAgent(AbsolutePosition, flying)) |
1670 | { | ||
1671 | m_log.DebugFormat( | ||
1672 | "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", | ||
1673 | Name, Scene.Name); | ||
1674 | |||
1675 | return; | ||
1676 | } | ||
1677 | |||
1678 | // Tell the client that we're totally ready | ||
1521 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | 1679 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); |
1522 | 1680 | ||
1681 | // Remember in HandleUseCircuitCode, we delayed this to here | ||
1682 | if (m_teleportFlags > 0) | ||
1683 | SendInitialDataToMe(); | ||
1684 | |||
1523 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); | 1685 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); |
1524 | 1686 | ||
1525 | if ((m_callbackURI != null) && !m_callbackURI.Equals("")) | 1687 | if (!string.IsNullOrEmpty(m_callbackURI)) |
1526 | { | 1688 | { |
1527 | // We cannot sleep here since this would hold up the inbound packet processing thread, as | 1689 | // We cannot sleep here since this would hold up the inbound packet processing thread, as |
1528 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release | 1690 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release |
@@ -1535,7 +1697,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1535 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | 1697 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", |
1536 | client.Name, client.AgentId, m_callbackURI); | 1698 | client.Name, client.AgentId, m_callbackURI); |
1537 | 1699 | ||
1538 | Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); | 1700 | UUID originID; |
1701 | |||
1702 | lock (m_originRegionIDAccessLock) | ||
1703 | originID = m_originRegionID; | ||
1704 | |||
1705 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | ||
1539 | m_callbackURI = null; | 1706 | m_callbackURI = null; |
1540 | } | 1707 | } |
1541 | // else | 1708 | // else |
@@ -1550,7 +1717,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1550 | // Create child agents in neighbouring regions | 1717 | // Create child agents in neighbouring regions |
1551 | if (openChildAgents && !IsChildAgent) | 1718 | if (openChildAgents && !IsChildAgent) |
1552 | { | 1719 | { |
1553 | |||
1554 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 1720 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); |
1555 | if (m_agentTransfer != null) | 1721 | if (m_agentTransfer != null) |
1556 | m_agentTransfer.EnableChildAgents(this); | 1722 | m_agentTransfer.EnableChildAgents(this); |
@@ -1573,6 +1739,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1573 | // m_log.DebugFormat( | 1739 | // m_log.DebugFormat( |
1574 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", | 1740 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", |
1575 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); | 1741 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); |
1742 | |||
1576 | } | 1743 | } |
1577 | 1744 | ||
1578 | /// <summary> | 1745 | /// <summary> |
@@ -1653,9 +1820,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1653 | /// </summary> | 1820 | /// </summary> |
1654 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | 1821 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) |
1655 | { | 1822 | { |
1656 | // m_log.DebugFormat( | 1823 | //m_log.DebugFormat( |
1657 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", | 1824 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", |
1658 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | 1825 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); |
1659 | 1826 | ||
1660 | if (IsChildAgent) | 1827 | if (IsChildAgent) |
1661 | { | 1828 | { |
@@ -1663,10 +1830,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1663 | return; | 1830 | return; |
1664 | } | 1831 | } |
1665 | 1832 | ||
1666 | ++m_movementUpdateCount; | ||
1667 | if (m_movementUpdateCount < 1) | ||
1668 | m_movementUpdateCount = 1; | ||
1669 | |||
1670 | #region Sanity Checking | 1833 | #region Sanity Checking |
1671 | 1834 | ||
1672 | // This is irritating. Really. | 1835 | // This is irritating. Really. |
@@ -1697,21 +1860,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1697 | 1860 | ||
1698 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | 1861 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; |
1699 | 1862 | ||
1700 | // Camera location in world. We'll need to raytrace | ||
1701 | // from this location from time to time. | ||
1702 | CameraPosition = agentData.CameraCenter; | ||
1703 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
1704 | { | ||
1705 | ReprioritizeUpdates(); | ||
1706 | m_lastCameraPosition = CameraPosition; | ||
1707 | } | ||
1708 | |||
1709 | // Use these three vectors to figure out what the agent is looking at | ||
1710 | // Convert it to a Matrix and/or Quaternion | ||
1711 | CameraAtAxis = agentData.CameraAtAxis; | ||
1712 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
1713 | CameraUpAxis = agentData.CameraUpAxis; | ||
1714 | |||
1715 | // The Agent's Draw distance setting | 1863 | // The Agent's Draw distance setting |
1716 | // When we get to the point of re-computing neighbors everytime this | 1864 | // When we get to the point of re-computing neighbors everytime this |
1717 | // changes, then start using the agent's drawdistance rather than the | 1865 | // changes, then start using the agent's drawdistance rather than the |
@@ -1783,9 +1931,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1783 | // Here's where you get them. | 1931 | // Here's where you get them. |
1784 | m_AgentControlFlags = flags; | 1932 | m_AgentControlFlags = flags; |
1785 | m_headrotation = agentData.HeadRotation; | 1933 | m_headrotation = agentData.HeadRotation; |
1934 | byte oldState = State; | ||
1786 | State = agentData.State; | 1935 | State = agentData.State; |
1787 | 1936 | ||
1937 | // We need to send this back to the client in order to stop the edit beams | ||
1938 | if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) | ||
1939 | ControllingClient.SendAgentTerseUpdate(this); | ||
1940 | |||
1788 | PhysicsActor actor = PhysicsActor; | 1941 | PhysicsActor actor = PhysicsActor; |
1942 | |||
1943 | // This will be the case if the agent is sitting on the groudn or on an object. | ||
1789 | if (actor == null) | 1944 | if (actor == null) |
1790 | { | 1945 | { |
1791 | SendControlsToScripts(flagsForScripts); | 1946 | SendControlsToScripts(flagsForScripts); |
@@ -1794,12 +1949,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1794 | 1949 | ||
1795 | if (AllowMovement && !SitGround) | 1950 | if (AllowMovement && !SitGround) |
1796 | { | 1951 | { |
1797 | Quaternion bodyRotation = agentData.BodyRotation; | 1952 | // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); |
1953 | |||
1798 | bool update_rotation = false; | 1954 | bool update_rotation = false; |
1799 | 1955 | ||
1800 | if (bodyRotation != Rotation) | 1956 | if (agentData.BodyRotation != Rotation) |
1801 | { | 1957 | { |
1802 | Rotation = bodyRotation; | 1958 | Rotation = agentData.BodyRotation; |
1803 | update_rotation = true; | 1959 | update_rotation = true; |
1804 | } | 1960 | } |
1805 | 1961 | ||
@@ -1845,10 +2001,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1845 | else | 2001 | else |
1846 | dirVectors = Dir_Vectors; | 2002 | dirVectors = Dir_Vectors; |
1847 | 2003 | ||
1848 | // The fact that MovementFlag is a byte needs to be fixed | ||
1849 | // it really should be a uint | ||
1850 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. | 2004 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. |
1851 | uint nudgehack = 250; | ||
1852 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) | 2005 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) |
1853 | { | 2006 | { |
1854 | if (((uint)flags & (uint)DCF) != 0) | 2007 | if (((uint)flags & (uint)DCF) != 0) |
@@ -1865,29 +2018,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1865 | // Why did I get this? | 2018 | // Why did I get this? |
1866 | } | 2019 | } |
1867 | 2020 | ||
1868 | if ((MovementFlag & (byte)(uint)DCF) == 0) | 2021 | if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) |
1869 | { | 2022 | { |
1870 | if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || | ||
1871 | DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) | ||
1872 | { | ||
1873 | MovementFlag |= (byte)nudgehack; | ||
1874 | } | ||
1875 | |||
1876 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); | 2023 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); |
1877 | MovementFlag += (byte)(uint)DCF; | 2024 | MovementFlag += (uint)DCF; |
1878 | update_movementflag = true; | 2025 | update_movementflag = true; |
1879 | } | 2026 | } |
1880 | } | 2027 | } |
1881 | else | 2028 | else |
1882 | { | 2029 | { |
1883 | if ((MovementFlag & (byte)(uint)DCF) != 0 || | 2030 | if ((MovementFlag & (uint)DCF) != 0) |
1884 | ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || | ||
1885 | DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) | ||
1886 | && ((MovementFlag & (byte)nudgehack) == nudgehack)) | ||
1887 | ) // This or is for Nudge forward | ||
1888 | { | 2031 | { |
1889 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); | 2032 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); |
1890 | MovementFlag -= ((byte)(uint)DCF); | 2033 | MovementFlag -= (uint)DCF; |
1891 | update_movementflag = true; | 2034 | update_movementflag = true; |
1892 | 2035 | ||
1893 | /* | 2036 | /* |
@@ -1907,6 +2050,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1907 | i++; | 2050 | i++; |
1908 | } | 2051 | } |
1909 | 2052 | ||
2053 | // Detect AGENT_CONTROL_STOP state changes | ||
2054 | if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0)) | ||
2055 | { | ||
2056 | AgentControlStopActive = !AgentControlStopActive; | ||
2057 | update_movementflag = true; | ||
2058 | } | ||
2059 | |||
1910 | if (MovingToTarget) | 2060 | if (MovingToTarget) |
1911 | { | 2061 | { |
1912 | // If the user has pressed a key then we want to cancel any move to target. | 2062 | // If the user has pressed a key then we want to cancel any move to target. |
@@ -1932,53 +2082,79 @@ namespace OpenSim.Region.Framework.Scenes | |||
1932 | // Only do this if we're flying | 2082 | // Only do this if we're flying |
1933 | if (Flying && !ForceFly) | 2083 | if (Flying && !ForceFly) |
1934 | { | 2084 | { |
1935 | // Landing detection code | 2085 | // Need to stop in mid air if user holds down AGENT_CONTROL_STOP |
1936 | 2086 | if (AgentControlStopActive) | |
1937 | // Are the landing controls requirements filled? | ||
1938 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | ||
1939 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | ||
1940 | |||
1941 | //m_log.Debug("[CONTROL]: " +flags); | ||
1942 | // Applies a satisfying roll effect to the avatar when flying. | ||
1943 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||
1944 | { | ||
1945 | ApplyFlyingRoll( | ||
1946 | FLY_ROLL_RADIANS_PER_UPDATE, | ||
1947 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
1948 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1949 | } | ||
1950 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||
1951 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||
1952 | { | 2087 | { |
1953 | ApplyFlyingRoll( | 2088 | agent_control_v3 = Vector3.Zero; |
1954 | -FLY_ROLL_RADIANS_PER_UPDATE, | ||
1955 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
1956 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1957 | } | 2089 | } |
1958 | else | 2090 | else |
1959 | { | 2091 | { |
1960 | if (m_AngularVelocity.Z != 0) | 2092 | // Landing detection code |
1961 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||
1962 | } | ||
1963 | 2093 | ||
1964 | if (Flying && IsColliding && controlland) | 2094 | // Are the landing controls requirements filled? |
1965 | { | 2095 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || |
1966 | // nesting this check because LengthSquared() is expensive and we don't | 2096 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); |
1967 | // want to do it every step when flying. | 2097 | |
1968 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | 2098 | //m_log.Debug("[CONTROL]: " +flags); |
1969 | StopFlying(); | 2099 | // Applies a satisfying roll effect to the avatar when flying. |
2100 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||
2101 | { | ||
2102 | ApplyFlyingRoll( | ||
2103 | FLY_ROLL_RADIANS_PER_UPDATE, | ||
2104 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
2105 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
2106 | } | ||
2107 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||
2108 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||
2109 | { | ||
2110 | ApplyFlyingRoll( | ||
2111 | -FLY_ROLL_RADIANS_PER_UPDATE, | ||
2112 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
2113 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
2114 | } | ||
2115 | else | ||
2116 | { | ||
2117 | if (m_AngularVelocity.Z != 0) | ||
2118 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||
2119 | } | ||
2120 | |||
2121 | if (Flying && IsColliding && controlland) | ||
2122 | { | ||
2123 | // nesting this check because LengthSquared() is expensive and we don't | ||
2124 | // want to do it every step when flying. | ||
2125 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | ||
2126 | StopFlying(); | ||
2127 | } | ||
1970 | } | 2128 | } |
1971 | } | 2129 | } |
1972 | 2130 | ||
2131 | // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); | ||
2132 | |||
1973 | // If the agent update does move the avatar, then calculate the force ready for the velocity update, | 2133 | // If the agent update does move the avatar, then calculate the force ready for the velocity update, |
1974 | // which occurs later in the main scene loop | 2134 | // which occurs later in the main scene loop |
1975 | if (update_movementflag || (update_rotation && DCFlagKeyPressed)) | 2135 | // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they |
2136 | // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update | ||
2137 | // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the | ||
2138 | // avatar location in place). | ||
2139 | if (update_movementflag | ||
2140 | || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) | ||
1976 | { | 2141 | { |
1977 | // m_log.DebugFormat( | 2142 | // if (update_movementflag || !AgentControlStopActive || MovementFlag != 0) |
1978 | // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", | 2143 | // { |
1979 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); | 2144 | // m_log.DebugFormat( |
2145 | // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}", | ||
2146 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name, | ||
2147 | // update_movementflag, MovementFlag, update_rotation); | ||
1980 | 2148 | ||
1981 | AddNewMovement(agent_control_v3); | 2149 | float speedModifier; |
2150 | |||
2151 | if (AgentControlStopActive) | ||
2152 | speedModifier = AgentControlStopSlowWhilstMoving; | ||
2153 | else | ||
2154 | speedModifier = 1; | ||
2155 | |||
2156 | AddNewMovement(agent_control_v3, speedModifier); | ||
2157 | // } | ||
1982 | } | 2158 | } |
1983 | // else | 2159 | // else |
1984 | // { | 2160 | // { |
@@ -1991,15 +2167,86 @@ namespace OpenSim.Region.Framework.Scenes | |||
1991 | // } | 2167 | // } |
1992 | 2168 | ||
1993 | if (update_movementflag && ParentID == 0) | 2169 | if (update_movementflag && ParentID == 0) |
2170 | { | ||
2171 | // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); | ||
1994 | Animator.UpdateMovementAnimations(); | 2172 | Animator.UpdateMovementAnimations(); |
2173 | } | ||
1995 | 2174 | ||
1996 | SendControlsToScripts(flagsForScripts); | 2175 | SendControlsToScripts(flagsForScripts); |
1997 | } | 2176 | } |
1998 | 2177 | ||
2178 | // We need to send this back to the client in order to see the edit beams | ||
2179 | if ((State & (uint)AgentState.Editing) != 0) | ||
2180 | ControllingClient.SendAgentTerseUpdate(this); | ||
2181 | |||
1999 | m_scene.EventManager.TriggerOnClientMovement(this); | 2182 | m_scene.EventManager.TriggerOnClientMovement(this); |
2000 | TriggerScenePresenceUpdated(); | ||
2001 | } | 2183 | } |
2002 | 2184 | ||
2185 | |||
2186 | /// <summary> | ||
2187 | /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. | ||
2188 | /// </summary> | ||
2189 | private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||
2190 | { | ||
2191 | //m_log.DebugFormat( | ||
2192 | // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}", | ||
2193 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | ||
2194 | |||
2195 | if (IsChildAgent) | ||
2196 | { | ||
2197 | // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); | ||
2198 | return; | ||
2199 | } | ||
2200 | |||
2201 | ++m_movementUpdateCount; | ||
2202 | if (m_movementUpdateCount < 1) | ||
2203 | m_movementUpdateCount = 1; | ||
2204 | |||
2205 | // AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | ||
2206 | |||
2207 | // Camera location in world. We'll need to raytrace | ||
2208 | // from this location from time to time. | ||
2209 | CameraPosition = agentData.CameraCenter; | ||
2210 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
2211 | { | ||
2212 | ReprioritizeUpdates(); | ||
2213 | m_lastCameraPosition = CameraPosition; | ||
2214 | } | ||
2215 | |||
2216 | // Use these three vectors to figure out what the agent is looking at | ||
2217 | // Convert it to a Matrix and/or Quaternion | ||
2218 | CameraAtAxis = agentData.CameraAtAxis; | ||
2219 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
2220 | CameraUpAxis = agentData.CameraUpAxis; | ||
2221 | |||
2222 | // The Agent's Draw distance setting | ||
2223 | // When we get to the point of re-computing neighbors everytime this | ||
2224 | // changes, then start using the agent's drawdistance rather than the | ||
2225 | // region's draw distance. | ||
2226 | // DrawDistance = agentData.Far; | ||
2227 | DrawDistance = Scene.DefaultDrawDistance; | ||
2228 | |||
2229 | // Check if Client has camera in 'follow cam' or 'build' mode. | ||
2230 | Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); | ||
2231 | |||
2232 | m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) | ||
2233 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; | ||
2234 | |||
2235 | |||
2236 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); | ||
2237 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | ||
2238 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) | ||
2239 | { | ||
2240 | if (m_followCamAuto) | ||
2241 | { | ||
2242 | Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; | ||
2243 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); | ||
2244 | } | ||
2245 | } | ||
2246 | |||
2247 | TriggerScenePresenceUpdated(); | ||
2248 | } | ||
2249 | |||
2003 | /// <summary> | 2250 | /// <summary> |
2004 | /// Calculate an update to move the presence to the set target. | 2251 | /// Calculate an update to move the presence to the set target. |
2005 | /// </summary> | 2252 | /// </summary> |
@@ -2252,17 +2499,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2252 | { | 2499 | { |
2253 | // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); | 2500 | // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); |
2254 | 2501 | ||
2502 | bool satOnObject = IsSatOnObject; | ||
2503 | SceneObjectPart part = ParentPart; | ||
2255 | SitGround = false; | 2504 | SitGround = false; |
2256 | 2505 | ||
2257 | /* move this down so avatar gets physical in the new position and not where it is siting | 2506 | if (satOnObject) |
2258 | if (PhysicsActor == null) | ||
2259 | AddToPhysicalScene(false); | ||
2260 | */ | ||
2261 | |||
2262 | if (ParentID != 0) | ||
2263 | { | 2507 | { |
2264 | PrevSitOffset = m_pos; // Save sit offset | 2508 | PrevSitOffset = m_pos; // Save sit offset |
2265 | SceneObjectPart part = ParentPart; | ||
2266 | UnRegisterSeatControls(part.ParentGroup.UUID); | 2509 | UnRegisterSeatControls(part.ParentGroup.UUID); |
2267 | 2510 | ||
2268 | TaskInventoryDictionary taskIDict = part.TaskInventory; | 2511 | TaskInventoryDictionary taskIDict = part.TaskInventory; |
@@ -2281,34 +2524,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2281 | } | 2524 | } |
2282 | 2525 | ||
2283 | part.ParentGroup.DeleteAvatar(UUID); | 2526 | part.ParentGroup.DeleteAvatar(UUID); |
2284 | // ParentPosition = part.GetWorldPosition(); | 2527 | Vector3 sitPartWorldPosition = part.GetWorldPosition(); |
2285 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); | 2528 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); |
2286 | 2529 | ||
2287 | // m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | ||
2288 | // ParentPosition = Vector3.Zero; | ||
2289 | m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | ||
2290 | if (part.SitTargetAvatar == UUID) | ||
2291 | m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation; | ||
2292 | |||
2293 | ParentID = 0; | 2530 | ParentID = 0; |
2294 | ParentPart = null; | 2531 | ParentPart = null; |
2295 | 2532 | ||
2296 | if (PhysicsActor == null) | 2533 | Quaternion standRotation; |
2297 | AddToPhysicalScene(false); | ||
2298 | 2534 | ||
2535 | if (part.SitTargetAvatar == UUID) | ||
2536 | { | ||
2537 | standRotation = part.GetWorldRotation(); | ||
2538 | |||
2539 | if (!part.IsRoot) | ||
2540 | standRotation = standRotation * part.SitTargetOrientation; | ||
2541 | // standRotation = part.RotationOffset * part.SitTargetOrientation; | ||
2542 | // else | ||
2543 | // standRotation = part.SitTargetOrientation; | ||
2544 | |||
2545 | } | ||
2546 | else | ||
2547 | { | ||
2548 | standRotation = Rotation; | ||
2549 | } | ||
2550 | |||
2551 | //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | ||
2552 | //Vector3 standPos = ParentPosition; | ||
2553 | |||
2554 | // Vector3 standPositionAdjustment | ||
2555 | // = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f); | ||
2556 | Vector3 adjustmentForSitPosition = part.SitTargetPosition * part.GetWorldRotation(); | ||
2557 | |||
2558 | // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than | ||
2559 | // hardcoding here. | ||
2560 | Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation; | ||
2561 | |||
2562 | Vector3 standPos = sitPartWorldPosition + adjustmentForSitPosition + adjustmentForSitPose; | ||
2563 | |||
2564 | // m_log.DebugFormat( | ||
2565 | // "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}", | ||
2566 | // standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name); | ||
2567 | |||
2568 | Rotation = standRotation; | ||
2569 | AbsolutePosition = standPos; | ||
2570 | } | ||
2571 | |||
2572 | // We need to wait until we have calculated proper stand positions before sitting up the physical | ||
2573 | // avatar to avoid race conditions. | ||
2574 | if (PhysicsActor == null) | ||
2575 | AddToPhysicalScene(false); | ||
2576 | |||
2577 | if (satOnObject) | ||
2578 | { | ||
2299 | SendAvatarDataToAllAgents(); | 2579 | SendAvatarDataToAllAgents(); |
2300 | m_requestedSitTargetID = 0; | 2580 | m_requestedSitTargetID = 0; |
2301 | 2581 | ||
2302 | part.RemoveSittingAvatar(UUID); | 2582 | part.RemoveSittingAvatar(UUID); |
2303 | 2583 | ||
2304 | if (part != null) | 2584 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
2305 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | ||
2306 | } | 2585 | } |
2307 | 2586 | ||
2308 | else if (PhysicsActor == null) | 2587 | else if (PhysicsActor == null) |
2309 | AddToPhysicalScene(false); | 2588 | AddToPhysicalScene(false); |
2310 | 2589 | ||
2311 | Animator.TrySetMovementAnimation("STAND"); | 2590 | Animator.TrySetMovementAnimation("STAND"); |
2591 | TriggerScenePresenceUpdated(); | ||
2312 | } | 2592 | } |
2313 | 2593 | ||
2314 | private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) | 2594 | private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) |
@@ -2359,7 +2639,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2359 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; | 2639 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; |
2360 | 2640 | ||
2361 | bool canSit = false; | 2641 | bool canSit = false; |
2362 | Vector3 pos = part.AbsolutePosition + offset; | ||
2363 | 2642 | ||
2364 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) | 2643 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) |
2365 | { | 2644 | { |
@@ -2369,6 +2648,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2369 | 2648 | ||
2370 | offset = part.SitTargetPosition; | 2649 | offset = part.SitTargetPosition; |
2371 | sitOrientation = part.SitTargetOrientation; | 2650 | sitOrientation = part.SitTargetOrientation; |
2651 | |||
2652 | if (!part.IsRoot) | ||
2653 | { | ||
2654 | // m_log.DebugFormat("Old sit orient {0}", sitOrientation); | ||
2655 | sitOrientation = part.RotationOffset * sitOrientation; | ||
2656 | // m_log.DebugFormat("New sit orient {0}", sitOrientation); | ||
2657 | // m_log.DebugFormat("Old sit offset {0}", offset); | ||
2658 | offset = offset * part.RotationOffset; | ||
2659 | // m_log.DebugFormat("New sit offset {0}", offset); | ||
2660 | } | ||
2661 | |||
2372 | canSit = true; | 2662 | canSit = true; |
2373 | } | 2663 | } |
2374 | else | 2664 | else |
@@ -2376,9 +2666,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2376 | if (PhysicsSit(part,offset)) // physics engine | 2666 | if (PhysicsSit(part,offset)) // physics engine |
2377 | return; | 2667 | return; |
2378 | 2668 | ||
2669 | Vector3 pos = part.AbsolutePosition + offset; | ||
2670 | |||
2379 | if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) | 2671 | if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) |
2380 | { | 2672 | { |
2381 | |||
2382 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); | 2673 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); |
2383 | canSit = true; | 2674 | canSit = true; |
2384 | } | 2675 | } |
@@ -2404,10 +2695,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2404 | cameraEyeOffset = part.GetCameraEyeOffset(); | 2695 | cameraEyeOffset = part.GetCameraEyeOffset(); |
2405 | forceMouselook = part.GetForceMouselook(); | 2696 | forceMouselook = part.GetForceMouselook(); |
2406 | 2697 | ||
2698 | // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is | ||
2699 | // being sat upon. | ||
2700 | offset += part.OffsetPosition; | ||
2701 | |||
2407 | ControllingClient.SendSitResponse( | 2702 | ControllingClient.SendSitResponse( |
2408 | part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | 2703 | part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); |
2409 | 2704 | ||
2410 | m_requestedSitTargetUUID = targetID; | 2705 | m_requestedSitTargetUUID = part.UUID; |
2411 | 2706 | ||
2412 | HandleAgentSit(ControllingClient, UUID); | 2707 | HandleAgentSit(ControllingClient, UUID); |
2413 | 2708 | ||
@@ -2435,7 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2435 | if (part != null) | 2730 | if (part != null) |
2436 | { | 2731 | { |
2437 | m_requestedSitTargetID = part.LocalId; | 2732 | m_requestedSitTargetID = part.LocalId; |
2438 | m_requestedSitTargetUUID = targetID; | 2733 | m_requestedSitTargetUUID = part.UUID; |
2439 | 2734 | ||
2440 | } | 2735 | } |
2441 | else | 2736 | else |
@@ -2554,6 +2849,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2554 | 2849 | ||
2555 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) | 2850 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) |
2556 | { | 2851 | { |
2852 | if (IsChildAgent) | ||
2853 | return; | ||
2854 | |||
2557 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 2855 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2558 | 2856 | ||
2559 | if (part != null) | 2857 | if (part != null) |
@@ -2603,24 +2901,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
2603 | Vector3 up = new Vector3((float)x, (float)y, (float)z); | 2901 | Vector3 up = new Vector3((float)x, (float)y, (float)z); |
2604 | Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; | 2902 | Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; |
2605 | 2903 | ||
2606 | m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; | 2904 | Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; |
2905 | Quaternion newRot; | ||
2906 | |||
2907 | if (part.IsRoot) | ||
2908 | { | ||
2909 | newRot = sitTargetOrient; | ||
2910 | } | ||
2911 | else | ||
2912 | { | ||
2913 | newPos = newPos * part.RotationOffset; | ||
2914 | newRot = part.RotationOffset * sitTargetOrient; | ||
2915 | } | ||
2916 | |||
2917 | newPos += part.OffsetPosition; | ||
2918 | |||
2919 | m_pos = newPos; | ||
2920 | Rotation = newRot; | ||
2607 | 2921 | ||
2608 | // m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset; | ||
2609 | Rotation = sitTargetOrient; | ||
2610 | // ParentPosition = part.AbsolutePosition; | 2922 | // ParentPosition = part.AbsolutePosition; |
2611 | part.ParentGroup.AddAvatar(UUID); | ||
2612 | } | 2923 | } |
2613 | else | 2924 | else |
2614 | { | 2925 | { |
2615 | m_pos -= part.AbsolutePosition; | 2926 | // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is |
2927 | // being sat upon. | ||
2928 | m_pos -= part.GroupPosition; | ||
2929 | |||
2616 | // ParentPosition = part.AbsolutePosition; | 2930 | // ParentPosition = part.AbsolutePosition; |
2617 | part.ParentGroup.AddAvatar(UUID); | ||
2618 | 2931 | ||
2619 | // m_log.DebugFormat( | 2932 | // m_log.DebugFormat( |
2620 | // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", | 2933 | // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", |
2621 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); | 2934 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); |
2622 | } | 2935 | } |
2623 | 2936 | ||
2937 | part.ParentGroup.AddAvatar(UUID); | ||
2624 | ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 2938 | ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2625 | ParentID = m_requestedSitTargetID; | 2939 | ParentID = m_requestedSitTargetID; |
2626 | m_AngularVelocity = Vector3.Zero; | 2940 | m_AngularVelocity = Vector3.Zero; |
@@ -2634,14 +2948,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2634 | } | 2948 | } |
2635 | Animator.TrySetMovementAnimation(sitAnimation); | 2949 | Animator.TrySetMovementAnimation(sitAnimation); |
2636 | SendAvatarDataToAllAgents(); | 2950 | SendAvatarDataToAllAgents(); |
2951 | TriggerScenePresenceUpdated(); | ||
2637 | } | 2952 | } |
2638 | } | 2953 | } |
2639 | 2954 | ||
2640 | public void HandleAgentSitOnGround() | 2955 | public void HandleAgentSitOnGround() |
2641 | { | 2956 | { |
2957 | if (IsChildAgent) | ||
2958 | return; | ||
2959 | |||
2642 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. | 2960 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. |
2643 | m_AngularVelocity = Vector3.Zero; | 2961 | m_AngularVelocity = Vector3.Zero; |
2644 | Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | 2962 | Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); |
2963 | TriggerScenePresenceUpdated(); | ||
2645 | SitGround = true; | 2964 | SitGround = true; |
2646 | RemoveFromPhysicalScene(); | 2965 | RemoveFromPhysicalScene(); |
2647 | } | 2966 | } |
@@ -2658,11 +2977,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2658 | public void HandleStartAnim(IClientAPI remoteClient, UUID animID) | 2977 | public void HandleStartAnim(IClientAPI remoteClient, UUID animID) |
2659 | { | 2978 | { |
2660 | Animator.AddAnimation(animID, UUID.Zero); | 2979 | Animator.AddAnimation(animID, UUID.Zero); |
2980 | TriggerScenePresenceUpdated(); | ||
2661 | } | 2981 | } |
2662 | 2982 | ||
2663 | public void HandleStopAnim(IClientAPI remoteClient, UUID animID) | 2983 | public void HandleStopAnim(IClientAPI remoteClient, UUID animID) |
2664 | { | 2984 | { |
2665 | Animator.RemoveAnimation(animID, false); | 2985 | Animator.RemoveAnimation(animID, false); |
2986 | TriggerScenePresenceUpdated(); | ||
2666 | } | 2987 | } |
2667 | 2988 | ||
2668 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) | 2989 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) |
@@ -2676,10 +2997,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2676 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector | 2997 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector |
2677 | /// </summary> | 2998 | /// </summary> |
2678 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> | 2999 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> |
2679 | public void AddNewMovement(Vector3 vec) | 3000 | /// <param name="thisAddSpeedModifier"> |
3001 | /// Optional additional speed modifier for this particular add. Default is 1</param> | ||
3002 | public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) | ||
2680 | { | 3003 | { |
2681 | // m_log.DebugFormat( | 3004 | // m_log.DebugFormat( |
2682 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); | 3005 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", |
3006 | // vec, Rotation, thisAddSpeedModifier, Name); | ||
2683 | 3007 | ||
2684 | Vector3 direc = vec * Rotation; | 3008 | Vector3 direc = vec * Rotation; |
2685 | direc.Normalize(); | 3009 | direc.Normalize(); |
@@ -2697,7 +3021,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2697 | if ((vec.Z == 0f) && !Flying) | 3021 | if ((vec.Z == 0f) && !Flying) |
2698 | direc.Z = 0f; // Prevent camera WASD up. | 3022 | direc.Z = 0f; // Prevent camera WASD up. |
2699 | 3023 | ||
2700 | direc *= 0.03f * 128f * SpeedModifier; | 3024 | direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; |
2701 | 3025 | ||
2702 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); | 3026 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); |
2703 | 3027 | ||
@@ -2843,6 +3167,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2843 | lastTerseUpdateToAllClientsTick = currentTick; | 3167 | lastTerseUpdateToAllClientsTick = currentTick; |
2844 | lastPositionSentToAllClients = OffsetPosition; | 3168 | lastPositionSentToAllClients = OffsetPosition; |
2845 | 3169 | ||
3170 | // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); | ||
2846 | m_scene.ForEachClient(SendTerseUpdateToClient); | 3171 | m_scene.ForEachClient(SendTerseUpdateToClient); |
2847 | } | 3172 | } |
2848 | TriggerScenePresenceUpdated(); | 3173 | TriggerScenePresenceUpdated(); |
@@ -2880,11 +3205,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | SendOtherAgentsAppearanceToMe(); | 3205 | SendOtherAgentsAppearanceToMe(); |
2881 | 3206 | ||
2882 | EntityBase[] entities = Scene.Entities.GetEntities(); | 3207 | EntityBase[] entities = Scene.Entities.GetEntities(); |
2883 | foreach(EntityBase e in entities) | 3208 | foreach (EntityBase e in entities) |
2884 | { | 3209 | { |
2885 | if (e != null && e is SceneObjectGroup) | 3210 | if (e != null && e is SceneObjectGroup) |
2886 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); | 3211 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); |
2887 | } | 3212 | } |
3213 | |||
2888 | }); | 3214 | }); |
2889 | } | 3215 | } |
2890 | 3216 | ||
@@ -2919,12 +3245,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2919 | // again here... this comes after the cached appearance check because the avatars | 3245 | // again here... this comes after the cached appearance check because the avatars |
2920 | // appearance goes into the avatar update packet | 3246 | // appearance goes into the avatar update packet |
2921 | SendAvatarDataToAllAgents(); | 3247 | SendAvatarDataToAllAgents(); |
3248 | |||
3249 | // This invocation always shows up in the viewer logs as an error. Is it needed? | ||
2922 | SendAppearanceToAgent(this); | 3250 | SendAppearanceToAgent(this); |
2923 | 3251 | ||
2924 | // If we are using the the cached appearance then send it out to everyone | 3252 | // If we are using the the cached appearance then send it out to everyone |
2925 | if (cachedappearance) | 3253 | if (cachedappearance) |
2926 | { | 3254 | { |
2927 | m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); | 3255 | m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name); |
2928 | 3256 | ||
2929 | // If the avatars baked textures are all in the cache, then we have a | 3257 | // If the avatars baked textures are all in the cache, then we have a |
2930 | // complete appearance... send it out, if not, then we'll send it when | 3258 | // complete appearance... send it out, if not, then we'll send it when |
@@ -3079,11 +3407,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3079 | } | 3407 | } |
3080 | 3408 | ||
3081 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m | 3409 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m |
3082 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || | 3410 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance) |
3083 | Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) | ||
3084 | { | 3411 | { |
3085 | m_lastChildAgentUpdatePosition = AbsolutePosition; | 3412 | m_lastChildAgentUpdatePosition = AbsolutePosition; |
3086 | m_lastChildAgentUpdateCamPosition = CameraPosition; | 3413 | // m_lastChildAgentUpdateCamPosition = CameraPosition; |
3087 | 3414 | ||
3088 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); | 3415 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); |
3089 | cadu.ActiveGroupID = UUID.Zero.Guid; | 3416 | cadu.ActiveGroupID = UUID.Zero.Guid; |
@@ -3110,7 +3437,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3110 | cadu.Velocity = Velocity; | 3437 | cadu.Velocity = Velocity; |
3111 | 3438 | ||
3112 | AgentPosition agentpos = new AgentPosition(); | 3439 | AgentPosition agentpos = new AgentPosition(); |
3113 | agentpos.CopyFrom(cadu); | 3440 | agentpos.CopyFrom(cadu, ControllingClient.SessionId); |
3114 | 3441 | ||
3115 | // Let's get this out of the update loop | 3442 | // Let's get this out of the update loop |
3116 | Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); | 3443 | Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); |
@@ -3294,11 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3294 | } | 3621 | } |
3295 | } | 3622 | } |
3296 | 3623 | ||
3297 | public void RestoreInCurrentScene() | ||
3298 | { | ||
3299 | AddToPhysicalScene(false); // not exactly false | ||
3300 | } | ||
3301 | |||
3302 | public void Reset() | 3624 | public void Reset() |
3303 | { | 3625 | { |
3304 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); | 3626 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); |
@@ -3348,10 +3670,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3348 | if (byebyeRegions.Count > 0) | 3670 | if (byebyeRegions.Count > 0) |
3349 | { | 3671 | { |
3350 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); | 3672 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); |
3351 | Util.FireAndForget(delegate | 3673 | |
3352 | { | 3674 | AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID); |
3353 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); | 3675 | string auth = string.Empty; |
3354 | }); | 3676 | if (acd != null) |
3677 | auth = acd.SessionID.ToString(); | ||
3678 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); | ||
3355 | } | 3679 | } |
3356 | 3680 | ||
3357 | foreach (ulong handle in byebyeRegions) | 3681 | foreach (ulong handle in byebyeRegions) |
@@ -3392,7 +3716,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3392 | 3716 | ||
3393 | #region Child Agent Updates | 3717 | #region Child Agent Updates |
3394 | 3718 | ||
3395 | public void ChildAgentDataUpdate(AgentData cAgentData) | 3719 | public void UpdateChildAgent(AgentData cAgentData) |
3396 | { | 3720 | { |
3397 | // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); | 3721 | // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); |
3398 | if (!IsChildAgent) | 3722 | if (!IsChildAgent) |
@@ -3402,15 +3726,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3402 | } | 3726 | } |
3403 | 3727 | ||
3404 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); | 3728 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); |
3729 | |||
3405 | private void RaiseUpdateThrottles() | 3730 | private void RaiseUpdateThrottles() |
3406 | { | 3731 | { |
3407 | m_scene.EventManager.TriggerThrottleUpdate(this); | 3732 | m_scene.EventManager.TriggerThrottleUpdate(this); |
3408 | } | 3733 | } |
3734 | |||
3409 | /// <summary> | 3735 | /// <summary> |
3410 | /// This updates important decision making data about a child agent | 3736 | /// This updates important decision making data about a child agent |
3411 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region | 3737 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region |
3412 | /// </summary> | 3738 | /// </summary> |
3413 | public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) | 3739 | public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) |
3414 | { | 3740 | { |
3415 | if (!IsChildAgent) | 3741 | if (!IsChildAgent) |
3416 | return; | 3742 | return; |
@@ -3452,6 +3778,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3452 | 3778 | ||
3453 | cAgent.AgentID = UUID; | 3779 | cAgent.AgentID = UUID; |
3454 | cAgent.RegionID = Scene.RegionInfo.RegionID; | 3780 | cAgent.RegionID = Scene.RegionInfo.RegionID; |
3781 | cAgent.SessionID = ControllingClient.SessionId; | ||
3455 | 3782 | ||
3456 | cAgent.Position = AbsolutePosition; | 3783 | cAgent.Position = AbsolutePosition; |
3457 | cAgent.Velocity = m_velocity; | 3784 | cAgent.Velocity = m_velocity; |
@@ -3517,7 +3844,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3517 | 3844 | ||
3518 | private void CopyFrom(AgentData cAgent) | 3845 | private void CopyFrom(AgentData cAgent) |
3519 | { | 3846 | { |
3520 | m_originRegionID = cAgent.RegionID; | 3847 | lock (m_originRegionIDAccessLock) |
3848 | m_originRegionID = cAgent.RegionID; | ||
3521 | 3849 | ||
3522 | m_callbackURI = cAgent.CallbackURI; | 3850 | m_callbackURI = cAgent.CallbackURI; |
3523 | // m_log.DebugFormat( | 3851 | // m_log.DebugFormat( |
@@ -3611,8 +3939,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3611 | { | 3939 | { |
3612 | Vector3 force = m_forceToApply.Value; | 3940 | Vector3 force = m_forceToApply.Value; |
3613 | 3941 | ||
3614 | Updated = true; | ||
3615 | |||
3616 | Velocity = force; | 3942 | Velocity = force; |
3617 | 3943 | ||
3618 | m_forceToApply = null; | 3944 | m_forceToApply = null; |
@@ -3694,7 +4020,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3694 | 4020 | ||
3695 | // if (m_updateCount > 0) | 4021 | // if (m_updateCount > 0) |
3696 | // { | 4022 | // { |
3697 | Animator.UpdateMovementAnimations(); | 4023 | if (Animator.UpdateMovementAnimations()) |
4024 | TriggerScenePresenceUpdated(); | ||
3698 | // m_updateCount--; | 4025 | // m_updateCount--; |
3699 | // } | 4026 | // } |
3700 | 4027 | ||
@@ -3858,6 +4185,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3858 | // Animator.Close(); | 4185 | // Animator.Close(); |
3859 | Animator = null; | 4186 | Animator = null; |
3860 | 4187 | ||
4188 | LifecycleState = ScenePresenceState.Removed; | ||
3861 | } | 4189 | } |
3862 | 4190 | ||
3863 | public void AddAttachment(SceneObjectGroup gobj) | 4191 | public void AddAttachment(SceneObjectGroup gobj) |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs new file mode 100644 index 0000000..cae7fe5 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | |||
30 | namespace 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..5372360 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -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); |
@@ -443,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
443 | m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); | 444 | m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); |
444 | m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); | 445 | m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); |
445 | m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); | 446 | m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); |
447 | m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach); | ||
446 | m_ShapeXmlProcessors.Add("State", ProcessShpState); | 448 | m_ShapeXmlProcessors.Add("State", ProcessShpState); |
447 | m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); | 449 | m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); |
448 | m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); | 450 | m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); |
@@ -798,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
798 | obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); | 800 | obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); |
799 | } | 801 | } |
800 | 802 | ||
803 | private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader) | ||
804 | { | ||
805 | obj.AttachedPos = Util.ReadVector(reader, "AttachedPos"); | ||
806 | } | ||
807 | |||
801 | private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) | 808 | private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) |
802 | { | 809 | { |
803 | obj.DynAttrs.ReadXml(reader); | 810 | obj.DynAttrs.ReadXml(reader); |
@@ -1099,6 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1099 | shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); | 1106 | shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); |
1100 | } | 1107 | } |
1101 | 1108 | ||
1109 | private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader) | ||
1110 | { | ||
1111 | shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty); | ||
1112 | } | ||
1113 | |||
1102 | private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) | 1114 | private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) |
1103 | { | 1115 | { |
1104 | shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); | 1116 | shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); |
@@ -1267,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1267 | 1279 | ||
1268 | WriteUUID(writer, "CreatorID", sop.CreatorID, options); | 1280 | WriteUUID(writer, "CreatorID", sop.CreatorID, options); |
1269 | 1281 | ||
1270 | if (sop.CreatorData != null && sop.CreatorData != string.Empty) | 1282 | if (!string.IsNullOrEmpty(sop.CreatorData)) |
1271 | writer.WriteElementString("CreatorData", sop.CreatorData); | 1283 | writer.WriteElementString("CreatorData", sop.CreatorData); |
1272 | else if (options.ContainsKey("home")) | 1284 | else if (options.ContainsKey("home")) |
1273 | { | 1285 | { |
@@ -1345,8 +1357,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1345 | writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); | 1357 | writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); |
1346 | if (sop.MediaUrl != null) | 1358 | if (sop.MediaUrl != null) |
1347 | writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); | 1359 | writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); |
1360 | WriteVector(writer, "AttachedPos", sop.AttachedPos); | ||
1348 | 1361 | ||
1349 | if (sop.DynAttrs.Count > 0) | 1362 | if (sop.DynAttrs.CountNamespaces > 0) |
1350 | { | 1363 | { |
1351 | writer.WriteStartElement("DynAttrs"); | 1364 | writer.WriteStartElement("DynAttrs"); |
1352 | sop.DynAttrs.WriteXml(writer); | 1365 | sop.DynAttrs.WriteXml(writer); |
@@ -1451,7 +1464,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1451 | 1464 | ||
1452 | WriteUUID(writer, "CreatorID", item.CreatorID, options); | 1465 | WriteUUID(writer, "CreatorID", item.CreatorID, options); |
1453 | 1466 | ||
1454 | if (item.CreatorData != null && item.CreatorData != string.Empty) | 1467 | if (!string.IsNullOrEmpty(item.CreatorData)) |
1455 | writer.WriteElementString("CreatorData", item.CreatorData); | 1468 | writer.WriteElementString("CreatorData", item.CreatorData); |
1456 | else if (options.ContainsKey("home")) | 1469 | else if (options.ContainsKey("home")) |
1457 | { | 1470 | { |
@@ -1539,6 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1539 | writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); | 1552 | writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); |
1540 | writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); | 1553 | writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); |
1541 | writer.WriteElementString("State", shp.State.ToString()); | 1554 | writer.WriteElementString("State", shp.State.ToString()); |
1555 | writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString()); | ||
1542 | 1556 | ||
1543 | WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); | 1557 | WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); |
1544 | WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); | 1558 | 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; | |||
33 | using OpenMetaverse; | 33 | using OpenMetaverse; |
34 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
35 | using OpenSim.Framework.Communications; | 35 | using OpenSim.Framework.Communications; |
36 | using OpenSim.Region.CoreModules.Framework.EntityTransfer; | ||
36 | using OpenSim.Region.CoreModules.Framework.InventoryAccess; | 37 | using OpenSim.Region.CoreModules.Framework.InventoryAccess; |
38 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | ||
37 | using OpenSim.Region.CoreModules.World.Permissions; | 39 | using OpenSim.Region.CoreModules.World.Permissions; |
38 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
39 | using OpenSim.Services.Interfaces; | 41 | using 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using System.Text; | ||
32 | using System.Threading; | ||
33 | using System.Timers; | ||
34 | using Timer = System.Timers.Timer; | ||
35 | using Nini.Config; | ||
36 | using NUnit.Framework; | ||
37 | using OpenMetaverse; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Communications; | ||
40 | using OpenSim.Framework.Servers; | ||
41 | using OpenSim.Framework.Servers.HttpServer; | ||
42 | using OpenSim.Region.ClientStack.Linden; | ||
43 | using OpenSim.Region.CoreModules.Framework; | ||
44 | using OpenSim.Region.CoreModules.Framework.EntityTransfer; | ||
45 | using OpenSim.Region.CoreModules.World.Serialiser; | ||
46 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | ||
47 | using OpenSim.Region.Framework.Scenes; | ||
48 | using OpenSim.Region.Framework.Interfaces; | ||
49 | using OpenSim.Tests.Common; | ||
50 | using OpenSim.Tests.Common.Mock; | ||
51 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | ||
52 | |||
53 | namespace 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; | |||
38 | using OpenSim.Region.CoreModules.Framework; | 38 | using OpenSim.Region.CoreModules.Framework; |
39 | using OpenSim.Region.CoreModules.Framework.EntityTransfer; | 39 | using OpenSim.Region.CoreModules.Framework.EntityTransfer; |
40 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | 40 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; |
41 | using OpenSim.Region.CoreModules.World.Permissions; | ||
41 | using OpenSim.Tests.Common; | 42 | using OpenSim.Tests.Common; |
42 | using OpenSim.Tests.Common.Mock; | 43 | using 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; | |||
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Net; | 31 | using System.Net; |
32 | using System.Text; | 32 | using System.Text; |
33 | using System.Threading; | ||
33 | using Nini.Config; | 34 | using Nini.Config; |
34 | using NUnit.Framework; | 35 | using NUnit.Framework; |
35 | using OpenMetaverse; | 36 | using 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using NUnit.Framework; | ||
32 | using OpenMetaverse; | ||
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Framework.Communications; | ||
35 | using OpenSim.Region.Framework.Scenes; | ||
36 | using OpenSim.Tests.Common; | ||
37 | using OpenSim.Tests.Common.Mock; | ||
38 | |||
39 | namespace 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 | |||
25 | using System; | ||
26 | using Nini.Config; | ||
27 | using NUnit.Framework; | ||
28 | using OpenMetaverse; | ||
29 | using OpenSim.Framework; | ||
30 | using OpenSim.Region.CoreModules.World.Estate; | ||
31 | using OpenSim.Region.Framework.Scenes; | ||
32 | using OpenSim.Region.Framework.Interfaces; | ||
33 | using OpenSim.Services.Interfaces; | ||
34 | using OpenSim.Tests.Common; | ||
35 | using OpenSim.Tests.Common.Mock; | ||
36 | |||
37 | namespace 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; | |||
34 | using log4net; | 34 | using log4net; |
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenMetaverse.Assets; | 36 | using OpenMetaverse.Assets; |
37 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
38 | using OpenSim.Region.Framework.Scenes.Serialization; | 39 | using OpenSim.Region.Framework.Scenes.Serialization; |
39 | using OpenSim.Services.Interfaces; | 40 | using OpenSim.Services.Interfaces; |
41 | using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType; | ||
40 | 42 | ||
41 | namespace OpenSim.Region.Framework.Scenes | 43 | namespace 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 |