diff options
Diffstat (limited to 'OpenSim/Region/Framework')
46 files changed, 6288 insertions, 2817 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs index af4b23d..3d2e083 100644 --- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs | |||
@@ -1,9 +1,30 @@ | |||
1 | //////////////////////////////////////////////////////////////// | 1 | /* |
2 | // | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | // (c) 2009, 2010 Careminster Limited and Melanie Thielker | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | // | 4 | * |
5 | // All rights reserved | 5 | * Redistribution and use in source and binary forms, with or without |
6 | // | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
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..84cdc15 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs | |||
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Scenes; | |||
36 | namespace OpenSim.Region.Framework.Interfaces | 36 | namespace OpenSim.Region.Framework.Interfaces |
37 | { | 37 | { |
38 | public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); | 38 | public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); |
39 | public delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying); | ||
39 | 40 | ||
40 | public interface IEntityTransferModule | 41 | public interface IEntityTransferModule |
41 | { | 42 | { |
@@ -47,13 +48,33 @@ namespace OpenSim.Region.Framework.Interfaces | |||
47 | /// The handle of the destination region. If it's the same as the region currently | 48 | /// The handle of the destination region. If it's the same as the region currently |
48 | /// occupied by the agent then the teleport will be within that region. | 49 | /// occupied by the agent then the teleport will be within that region. |
49 | /// </param> | 50 | /// </param> |
51 | /// <param name='agent'></param> | ||
52 | /// <param name='regionHandle'></param> | ||
50 | /// <param name='position'></param> | 53 | /// <param name='position'></param> |
51 | /// <param name='lookAt'></param> | 54 | /// <param name='lookAt'></param> |
52 | /// <param name='teleportFlags'></param> | 55 | /// <param name='teleportFlags'></param> |
53 | void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); | 56 | void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); |
54 | 57 | ||
58 | /// <summary> | ||
59 | /// Teleports the agent for the given client to their home destination. | ||
60 | /// </summary> | ||
61 | /// <param name='id'></param> | ||
62 | /// <param name='client'></param> | ||
55 | bool TeleportHome(UUID id, IClientAPI client); | 63 | bool TeleportHome(UUID id, IClientAPI client); |
56 | 64 | ||
65 | /// <summary> | ||
66 | /// Teleport an agent directly to a given region without checking whether the region should be substituted. | ||
67 | /// </summary> | ||
68 | /// <remarks> | ||
69 | /// Please use Teleport() instead unless you know exactly what you're doing. | ||
70 | /// Do not use for same region teleports. | ||
71 | /// </remarks> | ||
72 | /// <param name='sp'></param> | ||
73 | /// <param name='reg'></param> | ||
74 | /// <param name='finalDestination'>/param> | ||
75 | /// <param name='position'></param> | ||
76 | /// <param name='lookAt'></param> | ||
77 | /// <param name='teleportFlags'></param> | ||
57 | void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, | 78 | void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, |
58 | Vector3 position, Vector3 lookAt, uint teleportFlags); | 79 | Vector3 position, Vector3 lookAt, uint teleportFlags); |
59 | 80 | ||
@@ -72,9 +93,11 @@ namespace OpenSim.Region.Framework.Interfaces | |||
72 | 93 | ||
73 | void EnableChildAgent(ScenePresence agent, GridRegion region); | 94 | void EnableChildAgent(ScenePresence agent, GridRegion region); |
74 | 95 | ||
75 | GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos); | 96 | GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos); |
76 | 97 | GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos); | |
98 | bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason); | ||
77 | void Cross(SceneObjectGroup sog, Vector3 position, bool silent); | 99 | void Cross(SceneObjectGroup sog, Vector3 position, bool silent); |
100 | bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent); | ||
78 | 101 | ||
79 | ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); | 102 | ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); |
80 | 103 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 292efa4..944c66b 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs | |||
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
40 | 40 | ||
41 | uint GetRegionFlags(); | 41 | uint GetRegionFlags(); |
42 | bool IsManager(UUID avatarID); | 42 | bool IsManager(UUID avatarID); |
43 | 43 | ||
44 | /// <summary> | 44 | /// <summary> |
45 | /// Tell all clients about the current state of the region (terrain textures, water height, etc.). | 45 | /// Tell all clients about the current state of the region (terrain textures, water height, etc.). |
46 | /// </summary> | 46 | /// </summary> |
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces | |||
54 | 54 | ||
55 | void setEstateTerrainBaseTexture(int level, UUID texture); | 55 | void setEstateTerrainBaseTexture(int level, UUID texture); |
56 | void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); | 56 | void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); |
57 | |||
58 | /// <summary> | ||
59 | /// Returns whether the transfer ID is being used for a terrain transfer. | ||
60 | /// </summary> | ||
61 | bool IsTerrainXfer(ulong xferID); | ||
57 | } | 62 | } |
58 | } | 63 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs index 5512642..dfc269e 100644 --- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs +++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs | |||
@@ -39,21 +39,22 @@ namespace OpenSim.Region.Framework.Interfaces | |||
39 | 39 | ||
40 | // These are required to decouple Scenes from EventQueueHelper | 40 | // These are required to decouple Scenes from EventQueueHelper |
41 | void DisableSimulator(ulong handle, UUID avatarID); | 41 | void DisableSimulator(ulong handle, UUID avatarID); |
42 | void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID); | 42 | void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY); |
43 | void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, | 43 | void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, |
44 | string capsPath); | 44 | string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY); |
45 | void TeleportFinishEvent(ulong regionHandle, byte simAccess, | 45 | void TeleportFinishEvent(ulong regionHandle, byte simAccess, |
46 | IPEndPoint regionExternalEndPoint, | 46 | IPEndPoint regionExternalEndPoint, |
47 | uint locationID, uint flags, string capsURL, | 47 | uint locationID, uint flags, string capsURL, |
48 | UUID agentID); | 48 | UUID agentID, int regionSizeX, int regionSizeY); |
49 | void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, | 49 | void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, |
50 | IPEndPoint newRegionExternalEndPoint, | 50 | IPEndPoint newRegionExternalEndPoint, |
51 | string capsURL, UUID avatarID, UUID sessionID); | 51 | string capsURL, UUID avatarID, UUID sessionID, |
52 | int regionSizeX, int regionSizeY); | ||
52 | void ChatterboxInvitation(UUID sessionID, string sessionName, | 53 | void ChatterboxInvitation(UUID sessionID, string sessionName, |
53 | UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, | 54 | UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, |
54 | uint timeStamp, bool offline, int parentEstateID, Vector3 position, | 55 | uint timeStamp, bool offline, int parentEstateID, Vector3 position, |
55 | uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); | 56 | uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); |
56 | void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, | 57 | void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat, |
57 | bool isModerator, bool textMute); | 58 | bool isModerator, bool textMute); |
58 | void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); | 59 | void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); |
59 | void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); | 60 | void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); |
diff --git a/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs new file mode 100644 index 0000000..a730cfd --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
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..f7c6513 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs | |||
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
95 | /// <param name="radius">Sound radius</param> | 95 | /// <param name="radius">Sound radius</param> |
96 | /// <param name="isMaster">Set object to sync master if true</param> | 96 | /// <param name="isMaster">Set object to sync master if true</param> |
97 | void LoopSound(UUID objectID, UUID soundID, double gain, | 97 | void LoopSound(UUID objectID, UUID soundID, double gain, |
98 | double radius, bool isMaster); | 98 | double radius, bool isMaster, bool isSlave); |
99 | 99 | ||
100 | /// <summary> | 100 | /// <summary> |
101 | /// Trigger or play an attached sound in this part's inventory. | 101 | /// Trigger or play an attached sound in this part's inventory. |
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
104 | /// <param name="sound">Sound asset ID</param> | 104 | /// <param name="sound">Sound asset ID</param> |
105 | /// <param name="volume">Sound volume</param> | 105 | /// <param name="volume">Sound volume</param> |
106 | /// <param name="triggered">Triggered or not.</param> | 106 | /// <param name="triggered">Triggered or not.</param> |
107 | /// <param name="flags"></param> | ||
108 | /// <param name="radius">Sound radius</param> | 107 | /// <param name="radius">Sound radius</param> |
109 | /// <param name="useMaster">Play using sound master</param> | 108 | /// <param name="useMaster">Play using sound master</param> |
110 | /// <param name="isMaster">Play as sound master</param> | 109 | /// <param name="isMaster">Play as sound master</param> |
@@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces | |||
123 | /// <param name="max">AABB top north-east corner</param> | 122 | /// <param name="max">AABB top north-east corner</param> |
124 | void TriggerSoundLimited(UUID objectID, UUID sound, double volume, | 123 | void TriggerSoundLimited(UUID objectID, UUID sound, double volume, |
125 | Vector3 min, Vector3 max); | 124 | Vector3 min, Vector3 max); |
125 | |||
126 | /// <summary> | ||
127 | /// Set whether sounds on the given prim should be queued. | ||
128 | /// </summary> | ||
129 | /// <param name='objectID'></param> | ||
130 | /// <param name='shouldQueue'></param> | ||
131 | void SetSoundQueueing(UUID objectID, bool shouldQueue); | ||
126 | } | 132 | } |
127 | } \ No newline at end of file | 133 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs index 167c248..a2a99d4 100644 --- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs | |||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices; | |||
29 | // Build Number | 29 | // Build Number |
30 | // Revision | 30 | // Revision |
31 | // | 31 | // |
32 | [assembly: AssemblyVersion("0.7.6.*")] | 32 | [assembly: AssemblyVersion("0.8.0.*")] |
33 | 33 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 66edfed..b7400ea 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | |||
@@ -28,8 +28,11 @@ | |||
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/MovementAnimationOverrides.cs b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs new file mode 100644 index 0000000..31fdb2c --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Xml; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Reflection; | ||
32 | using System.Threading; | ||
33 | using System.Timers; | ||
34 | using Timer = System.Timers.Timer; | ||
35 | using OpenMetaverse; | ||
36 | using log4net; | ||
37 | using Nini.Config; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Client; | ||
40 | using OpenSim.Region.Framework.Interfaces; | ||
41 | using OpenSim.Region.Framework.Scenes.Animation; | ||
42 | using OpenSim.Region.Framework.Scenes.Types; | ||
43 | using OpenSim.Region.Physics.Manager; | ||
44 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | ||
45 | using OpenSim.Services.Interfaces; | ||
46 | using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags; | ||
47 | |||
48 | namespace OpenSim.Region.Framework.Scenes | ||
49 | { | ||
50 | public class MovementAnimationOverrides | ||
51 | { | ||
52 | private static readonly ILog m_log = | ||
53 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
54 | |||
55 | private Dictionary<string, UUID> m_overrides = new Dictionary<string, UUID>(); | ||
56 | public void SetOverride(string state, UUID animID) | ||
57 | { | ||
58 | if (animID == UUID.Zero) | ||
59 | { | ||
60 | if (state == "ALL") | ||
61 | m_overrides.Clear(); | ||
62 | else | ||
63 | m_overrides.Remove(state); | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | m_log.DebugFormat("Setting override for {0} to {1}", state, animID); | ||
68 | |||
69 | lock (m_overrides) | ||
70 | m_overrides[state] = animID; | ||
71 | } | ||
72 | |||
73 | public UUID GetOverriddenAnimation(string state) | ||
74 | { | ||
75 | lock (m_overrides) | ||
76 | { | ||
77 | if (m_overrides.ContainsKey(state)) | ||
78 | return m_overrides[state]; | ||
79 | } | ||
80 | |||
81 | return UUID.Zero; | ||
82 | } | ||
83 | |||
84 | public Dictionary<string, UUID> CloneAOPairs() | ||
85 | { | ||
86 | lock (m_overrides) | ||
87 | { | ||
88 | return new Dictionary<string, UUID>(m_overrides); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | public void CopyAOPairsFrom(Dictionary<string, UUID> src) | ||
93 | { | ||
94 | lock (m_overrides) | ||
95 | { | ||
96 | m_overrides.Clear(); | ||
97 | m_overrides = new Dictionary<string, UUID>(src); | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | } | ||
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 65c279e..ade908d 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
48 | 48 | ||
49 | public AnimationSet Animations | 49 | public AnimationSet Animations |
50 | { | 50 | { |
51 | get { return m_animations; } | 51 | get { return m_animations; } |
52 | } | 52 | } |
53 | protected AnimationSet m_animations = new AnimationSet(); | 53 | protected AnimationSet m_animations = new AnimationSet(); |
54 | 54 | ||
@@ -56,25 +56,27 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
56 | /// The current movement animation | 56 | /// The current movement animation |
57 | /// </value> | 57 | /// </value> |
58 | public string CurrentMovementAnimation { get; private set; } | 58 | public string CurrentMovementAnimation { get; private set; } |
59 | 59 | ||
60 | private int m_animTickFall; | 60 | private int m_animTickFall; |
61 | public int m_animTickJump; // ScenePresence has to see this to control +Z force | 61 | private int m_animTickLand; |
62 | public bool m_jumping = false; | 62 | private int m_animTickJump; |
63 | public float m_jumpVelocity = 0f; | 63 | |
64 | // private int m_landing = 0; | 64 | public bool m_jumping = false; |
65 | |||
66 | // private int m_landing = 0; | ||
65 | 67 | ||
66 | /// <summary> | 68 | /// <summary> |
67 | /// Is the avatar falling? | 69 | /// Is the avatar falling? |
68 | /// </summary> | 70 | /// </summary> |
69 | public bool Falling { get; private set; } | 71 | public bool Falling { get; private set; } |
70 | 72 | ||
71 | private float m_fallHeight; | 73 | private float m_lastFallVelocity; |
72 | 74 | ||
73 | /// <value> | 75 | /// <value> |
74 | /// The scene presence that this animator applies to | 76 | /// The scene presence that this animator applies to |
75 | /// </value> | 77 | /// </value> |
76 | protected ScenePresence m_scenePresence; | 78 | protected ScenePresence m_scenePresence; |
77 | 79 | ||
78 | public ScenePresenceAnimator(ScenePresence sp) | 80 | public ScenePresenceAnimator(ScenePresence sp) |
79 | { | 81 | { |
80 | m_scenePresence = sp; | 82 | m_scenePresence = sp; |
@@ -89,11 +91,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
89 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name); | 91 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name); |
90 | if (m_scenePresence.Scene.DebugAnimations) | 92 | if (m_scenePresence.Scene.DebugAnimations) |
91 | m_log.DebugFormat( | 93 | m_log.DebugFormat( |
92 | "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", | 94 | "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", |
93 | GetAnimName(animID), animID, m_scenePresence.Name); | 95 | GetAnimName(animID), animID, m_scenePresence.Name); |
94 | 96 | ||
95 | if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) | 97 | if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) |
98 | { | ||
96 | SendAnimPack(); | 99 | SendAnimPack(); |
100 | m_scenePresence.TriggerScenePresenceUpdated(); | ||
101 | } | ||
97 | } | 102 | } |
98 | 103 | ||
99 | // Called from scripts | 104 | // Called from scripts |
@@ -108,7 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
108 | if (animID == UUID.Zero) | 113 | if (animID == UUID.Zero) |
109 | return; | 114 | return; |
110 | 115 | ||
111 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name); | 116 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name); |
112 | 117 | ||
113 | AddAnimation(animID, objectID); | 118 | AddAnimation(animID, objectID); |
114 | } | 119 | } |
@@ -128,11 +133,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
128 | 133 | ||
129 | if (m_scenePresence.Scene.DebugAnimations) | 134 | if (m_scenePresence.Scene.DebugAnimations) |
130 | m_log.DebugFormat( | 135 | m_log.DebugFormat( |
131 | "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}", | 136 | "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}", |
132 | GetAnimName(animID), animID, m_scenePresence.Name); | 137 | GetAnimName(animID), animID, m_scenePresence.Name); |
133 | 138 | ||
134 | if (m_animations.Remove(animID, allowNoDefault)) | 139 | if (m_animations.Remove(animID, allowNoDefault)) |
140 | { | ||
135 | SendAnimPack(); | 141 | SendAnimPack(); |
142 | m_scenePresence.TriggerScenePresenceUpdated(); | ||
143 | } | ||
136 | } | 144 | } |
137 | 145 | ||
138 | public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) | 146 | public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) |
@@ -145,9 +153,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
145 | if (addRemove) | 153 | if (addRemove) |
146 | m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero); | 154 | m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero); |
147 | else | 155 | else |
148 | m_animations.Remove(animID, true); | 156 | m_animations.Remove(animID, false); |
149 | } | 157 | } |
150 | if(sendPack) | 158 | if (sendPack) |
151 | SendAnimPack(); | 159 | SendAnimPack(); |
152 | } | 160 | } |
153 | 161 | ||
@@ -175,29 +183,72 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
175 | 183 | ||
176 | m_animations.Clear(); | 184 | m_animations.Clear(); |
177 | } | 185 | } |
178 | 186 | ||
187 | |||
188 | UUID aoSitGndAnim = UUID.Zero; | ||
189 | |||
179 | /// <summary> | 190 | /// <summary> |
180 | /// The movement animation is reserved for "main" animations | 191 | /// The movement animation is reserved for "main" animations |
181 | /// that are mutually exclusive, e.g. flying and sitting. | 192 | /// that are mutually exclusive, e.g. flying and sitting. |
182 | /// </summary> | 193 | /// </summary> |
183 | public void TrySetMovementAnimation(string anim) | 194 | /// <returns>'true' if the animation was updated</returns> |
195 | /// | ||
196 | |||
197 | |||
198 | |||
199 | public bool TrySetMovementAnimation(string anim) | ||
184 | { | 200 | { |
201 | bool ret = false; | ||
185 | if (!m_scenePresence.IsChildAgent) | 202 | if (!m_scenePresence.IsChildAgent) |
186 | { | 203 | { |
187 | // m_log.DebugFormat( | 204 | // m_log.DebugFormat( |
188 | // "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", | 205 | // "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", |
189 | // anim, m_scenePresence.Name); | 206 | // anim, m_scenePresence.Name); |
190 | 207 | ||
191 | if (m_animations.TrySetDefaultAnimation( | 208 | if (aoSitGndAnim != UUID.Zero) |
192 | anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) | 209 | { |
210 | avnChangeAnim(aoSitGndAnim, false, true); | ||
211 | aoSitGndAnim = UUID.Zero; | ||
212 | } | ||
213 | |||
214 | UUID overridenAnim = m_scenePresence.Overrides.GetOverriddenAnimation(anim); | ||
215 | if (overridenAnim != UUID.Zero) | ||
216 | { | ||
217 | if (anim == "SITGROUND") | ||
218 | { | ||
219 | UUID defsit = DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]; | ||
220 | if (defsit == UUID.Zero) | ||
221 | return false; | ||
222 | m_animations.SetDefaultAnimation(defsit, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID); | ||
223 | aoSitGndAnim = overridenAnim; | ||
224 | avnChangeAnim(overridenAnim, true, false); | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | m_animations.SetDefaultAnimation(overridenAnim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID); | ||
229 | } | ||
230 | m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION }); | ||
231 | SendAnimPack(); | ||
232 | ret = true; | ||
233 | } | ||
234 | else | ||
193 | { | 235 | { |
236 | // translate sit and sitground state animations | ||
237 | if (anim == "SIT" || anim == "SITGROUND") | ||
238 | anim = m_scenePresence.sitAnimation; | ||
239 | |||
240 | if (m_animations.TrySetDefaultAnimation( | ||
241 | anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) | ||
242 | { | ||
194 | // m_log.DebugFormat( | 243 | // m_log.DebugFormat( |
195 | // "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}", | 244 | // "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}", |
196 | // anim, m_scenePresence.Name); | 245 | // anim, m_scenePresence.Name); |
197 | 246 | ||
198 | // 16384 is CHANGED_ANIMATION | 247 | // 16384 is CHANGED_ANIMATION |
199 | m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); | 248 | m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION }); |
200 | SendAnimPack(); | 249 | SendAnimPack(); |
250 | ret = true; | ||
251 | } | ||
201 | } | 252 | } |
202 | } | 253 | } |
203 | else | 254 | else |
@@ -206,80 +257,122 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
206 | "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", | 257 | "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", |
207 | anim, m_scenePresence.Name); | 258 | anim, m_scenePresence.Name); |
208 | } | 259 | } |
260 | return ret; | ||
261 | } | ||
262 | |||
263 | public enum motionControlStates : byte | ||
264 | { | ||
265 | sitted = 0, | ||
266 | flying, | ||
267 | falling, | ||
268 | jumping, | ||
269 | landing, | ||
270 | onsurface | ||
209 | } | 271 | } |
210 | 272 | ||
273 | public motionControlStates currentControlState = motionControlStates.onsurface; | ||
274 | |||
211 | /// <summary> | 275 | /// <summary> |
212 | /// This method determines the proper movement related animation | 276 | /// This method determines the proper movement related animation |
213 | /// </summary> | 277 | /// </summary> |
214 | private string DetermineMovementAnimation() | 278 | private string DetermineMovementAnimation() |
215 | { | 279 | { |
216 | const float FALL_DELAY = 800f; | 280 | const int FALL_DELAY = 800; |
217 | const float PREJUMP_DELAY = 200f; | 281 | const int PREJUMP_DELAY = 200; |
218 | const float JUMP_PERIOD = 800f; | 282 | const int JUMP_PERIOD = 800; |
219 | #region Inputs | 283 | #region Inputs |
220 | 284 | ||
285 | if (m_scenePresence.IsInTransit) | ||
286 | return CurrentMovementAnimation; | ||
287 | |||
288 | if (m_scenePresence.SitGround) | ||
289 | { | ||
290 | currentControlState = motionControlStates.sitted; | ||
291 | return "SITGROUND"; | ||
292 | } | ||
293 | if (m_scenePresence.ParentID != 0 || m_scenePresence.ParentUUID != UUID.Zero) | ||
294 | { | ||
295 | currentControlState = motionControlStates.sitted; | ||
296 | return "SIT"; | ||
297 | } | ||
298 | |||
221 | AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; | 299 | AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; |
222 | PhysicsActor actor = m_scenePresence.PhysicsActor; | 300 | PhysicsActor actor = m_scenePresence.PhysicsActor; |
223 | 301 | ||
224 | // Create forward and left vectors from the current avatar rotation | 302 | const AgentManager.ControlFlags ANYXYMASK = ( |
225 | Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation); | 303 | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | |
226 | Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix); | 304 | AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG | |
227 | Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); | 305 | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS | |
306 | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | ||
307 | ); | ||
228 | 308 | ||
229 | // Check control flags | 309 | // Check control flags |
230 | bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); | 310 | /* not in use |
231 | bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); | 311 | bool heldForward = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)) != 0); |
232 | bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); | 312 | bool heldBack = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG)) != 0); |
233 | bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); | 313 | bool heldLeft = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS)) != 0); |
314 | bool heldRight = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG)) != 0); | ||
315 | */ | ||
234 | bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; | 316 | bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; |
235 | bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; | 317 | bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; |
236 | bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; | 318 | // bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS)) != 0); |
237 | bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; | 319 | // excluded nudge up so it doesn't trigger jump state |
320 | bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS)) != 0); | ||
321 | bool heldDown = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG)) != 0); | ||
238 | //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY; | 322 | //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY; |
239 | //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK; | 323 | //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK; |
240 | if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown) | 324 | |
325 | bool heldOnXY = ((controlFlags & ANYXYMASK) != 0); | ||
326 | if (heldOnXY || heldUp || heldDown) | ||
241 | { | 327 | { |
242 | heldTurnLeft = false; | 328 | heldTurnLeft = false; |
243 | heldTurnRight = false; | 329 | heldTurnRight = false; |
244 | } | 330 | } |
245 | 331 | ||
246 | // Direction in which the avatar is trying to move | ||
247 | Vector3 move = Vector3.Zero; | ||
248 | if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; } | ||
249 | if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; } | ||
250 | if (heldLeft) { move.X += left.X; move.Y += left.Y; } | ||
251 | if (heldRight) { move.X -= left.X; move.Y -= left.Y; } | ||
252 | if (heldUp) { move.Z += 1; } | ||
253 | if (heldDown) { move.Z -= 1; } | ||
254 | |||
255 | // Is the avatar trying to move? | ||
256 | // bool moving = (move != Vector3.Zero); | ||
257 | #endregion Inputs | 332 | #endregion Inputs |
258 | 333 | ||
334 | // no physics actor case | ||
335 | if (actor == null) | ||
336 | { | ||
337 | // well what to do? | ||
338 | |||
339 | currentControlState = motionControlStates.onsurface; | ||
340 | if (heldOnXY) | ||
341 | return "WALK"; | ||
342 | |||
343 | return "STAND"; | ||
344 | } | ||
345 | |||
259 | #region Flying | 346 | #region Flying |
260 | 347 | ||
261 | if (actor != null && actor.Flying) | 348 | bool isColliding = actor.IsColliding; |
349 | |||
350 | if (actor.Flying) | ||
262 | { | 351 | { |
263 | m_animTickFall = 0; | 352 | m_animTickFall = 0; |
264 | m_animTickJump = 0; | 353 | m_animTickJump = 0; |
265 | m_jumping = false; | 354 | m_jumping = false; |
266 | Falling = false; | 355 | Falling = false; |
267 | m_jumpVelocity = 0f; | ||
268 | actor.Selected = false; | ||
269 | m_fallHeight = actor.Position.Z; // save latest flying height | ||
270 | 356 | ||
271 | if (move.X != 0f || move.Y != 0f) | 357 | currentControlState = motionControlStates.flying; |
358 | |||
359 | if (heldOnXY) | ||
272 | { | 360 | { |
273 | return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); | 361 | return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); |
274 | } | 362 | } |
275 | else if (move.Z > 0f) | 363 | else if (heldUp) |
276 | { | 364 | { |
277 | return "HOVER_UP"; | 365 | return "HOVER_UP"; |
278 | } | 366 | } |
279 | else if (move.Z < 0f) | 367 | else if (heldDown) |
280 | { | 368 | { |
281 | if (actor != null && actor.IsColliding) | 369 | if (isColliding) |
370 | { | ||
371 | actor.Flying = false; | ||
372 | currentControlState = motionControlStates.landing; | ||
373 | m_animTickLand = Environment.TickCount; | ||
282 | return "LAND"; | 374 | return "LAND"; |
375 | } | ||
283 | else | 376 | else |
284 | return "HOVER_DOWN"; | 377 | return "HOVER_DOWN"; |
285 | } | 378 | } |
@@ -288,139 +381,161 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
288 | return "HOVER"; | 381 | return "HOVER"; |
289 | } | 382 | } |
290 | } | 383 | } |
384 | else | ||
385 | { | ||
386 | if (isColliding && currentControlState == motionControlStates.flying) | ||
387 | { | ||
388 | currentControlState = motionControlStates.landing; | ||
389 | m_animTickLand = Environment.TickCount; | ||
390 | return "LAND"; | ||
391 | } | ||
392 | } | ||
291 | 393 | ||
292 | #endregion Flying | 394 | #endregion Flying |
293 | 395 | ||
294 | #region Falling/Floating/Landing | 396 | #region Falling/Floating/Landing |
295 | 397 | ||
296 | if ((actor == null || !actor.IsColliding) && !m_jumping) | 398 | if (!isColliding && currentControlState != motionControlStates.jumping) |
297 | { | 399 | { |
298 | float fallElapsed = (float)(Environment.TickCount - m_animTickFall); | 400 | float fallVelocity = actor.Velocity.Z; |
299 | float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; | ||
300 | 401 | ||
301 | if (!m_jumping && (fallVelocity < -3.0f)) | 402 | if (fallVelocity < -2.5f) |
302 | Falling = true; | 403 | Falling = true; |
303 | 404 | ||
304 | if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) | 405 | if (m_animTickFall == 0 || (fallVelocity >= -0.5f)) |
305 | { | 406 | { |
306 | // not falling yet, or going up | ||
307 | // reset start of fall time | ||
308 | m_animTickFall = Environment.TickCount; | 407 | m_animTickFall = Environment.TickCount; |
309 | } | 408 | } |
310 | else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) | 409 | else |
311 | { | 410 | { |
312 | // Falling long enough to trigger the animation | 411 | int fallElapsed = (Environment.TickCount - m_animTickFall); |
313 | return "FALLDOWN"; | 412 | if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f)) |
413 | { | ||
414 | currentControlState = motionControlStates.falling; | ||
415 | m_lastFallVelocity = fallVelocity; | ||
416 | // Falling long enough to trigger the animation | ||
417 | return "FALLDOWN"; | ||
418 | } | ||
314 | } | 419 | } |
315 | 420 | ||
316 | // Check if the user has stopped walking just now | 421 | // Check if the user has stopped walking just now |
317 | if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) | 422 | if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp) |
318 | return "STAND"; | 423 | return "STAND"; |
319 | 424 | ||
320 | return CurrentMovementAnimation; | 425 | return CurrentMovementAnimation; |
321 | } | 426 | } |
322 | 427 | ||
323 | #endregion Falling/Floating/Landing | 428 | m_animTickFall = 0; |
324 | 429 | ||
430 | #endregion Falling/Floating/Landing | ||
325 | 431 | ||
326 | #region Jumping // section added for jumping... | 432 | #region Jumping // section added for jumping... |
327 | 433 | ||
328 | int jumptime; | 434 | if (isColliding && heldUp && currentControlState != motionControlStates.jumping) |
329 | jumptime = Environment.TickCount - m_animTickJump; | ||
330 | |||
331 | if ((move.Z > 0f) && (!m_jumping)) | ||
332 | { | 435 | { |
333 | // Start jumping, prejump | 436 | // Start jumping, prejump |
334 | m_animTickFall = 0; | 437 | currentControlState = motionControlStates.jumping; |
335 | m_jumping = true; | 438 | m_jumping = true; |
336 | Falling = false; | 439 | Falling = false; |
337 | actor.Selected = true; // borrowed for jumping flag | ||
338 | m_animTickJump = Environment.TickCount; | 440 | m_animTickJump = Environment.TickCount; |
339 | m_jumpVelocity = 0.35f; | ||
340 | return "PREJUMP"; | 441 | return "PREJUMP"; |
341 | } | 442 | } |
342 | 443 | ||
343 | if (m_jumping) | 444 | if (currentControlState == motionControlStates.jumping) |
344 | { | 445 | { |
446 | int jumptime = Environment.TickCount - m_animTickJump; | ||
345 | if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) | 447 | if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) |
346 | { | 448 | { |
347 | // end jumping | 449 | // end jumping |
348 | m_jumping = false; | 450 | m_jumping = false; |
349 | Falling = false; | 451 | Falling = false; |
350 | actor.Selected = false; // borrowed for jumping flag | 452 | actor.Selected = false; // borrowed for jumping flag |
351 | m_jumpVelocity = 0f; | 453 | m_animTickLand = Environment.TickCount; |
352 | m_animTickFall = Environment.TickCount; | 454 | currentControlState = motionControlStates.landing; |
353 | return "LAND"; | 455 | return "LAND"; |
354 | } | 456 | } |
355 | else if (jumptime > JUMP_PERIOD) | 457 | else if (jumptime > JUMP_PERIOD) |
356 | { | 458 | { |
357 | // jump down | 459 | // jump down |
358 | m_jumpVelocity = 0f; | ||
359 | return "JUMP"; | 460 | return "JUMP"; |
360 | } | 461 | } |
361 | else if (jumptime > PREJUMP_DELAY) | 462 | else if (jumptime > PREJUMP_DELAY) |
362 | { | 463 | { |
363 | // jump up | 464 | // jump up |
364 | m_jumping = true; | 465 | m_jumping = true; |
365 | m_jumpVelocity = 10f; | ||
366 | return "JUMP"; | 466 | return "JUMP"; |
367 | } | 467 | } |
468 | return CurrentMovementAnimation; | ||
368 | } | 469 | } |
369 | 470 | ||
370 | #endregion Jumping | 471 | #endregion Jumping |
371 | 472 | ||
372 | #region Ground Movement | 473 | #region Ground Movement |
373 | 474 | ||
374 | if (CurrentMovementAnimation == "FALLDOWN") | 475 | if (currentControlState == motionControlStates.falling) |
375 | { | 476 | { |
376 | Falling = false; | 477 | Falling = false; |
377 | m_animTickFall = Environment.TickCount; | 478 | currentControlState = motionControlStates.landing; |
479 | m_animTickLand = Environment.TickCount; | ||
378 | // TODO: SOFT_LAND support | 480 | // TODO: SOFT_LAND support |
379 | float fallHeight = m_fallHeight - actor.Position.Z; | 481 | float fallVsq = m_lastFallVelocity * m_lastFallVelocity; |
380 | if (fallHeight > 15.0f) | 482 | if (fallVsq > 300f) // aprox 20*h |
381 | return "STANDUP"; | 483 | return "STANDUP"; |
382 | else if (fallHeight > 8.0f) | 484 | else if (fallVsq > 160f) |
383 | return "SOFT_LAND"; | 485 | return "SOFT_LAND"; |
384 | else | 486 | else |
385 | return "LAND"; | 487 | return "LAND"; |
386 | } | 488 | } |
387 | else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) | 489 | |
490 | |||
491 | if (currentControlState == motionControlStates.landing) | ||
388 | { | 492 | { |
389 | int landElapsed = Environment.TickCount - m_animTickFall; | 493 | Falling = false; |
494 | int landElapsed = Environment.TickCount - m_animTickLand; | ||
390 | int limit = 1000; | 495 | int limit = 1000; |
391 | if (CurrentMovementAnimation == "LAND") | 496 | if (CurrentMovementAnimation == "LAND") |
392 | limit = 350; | 497 | limit = 350; |
393 | // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client | 498 | // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client |
394 | 499 | ||
395 | if ((m_animTickFall != 0) && (landElapsed <= limit)) | 500 | if ((m_animTickLand != 0) && (landElapsed <= limit)) |
396 | { | 501 | { |
397 | return CurrentMovementAnimation; | 502 | return CurrentMovementAnimation; |
398 | } | 503 | } |
399 | else | 504 | else |
400 | { | 505 | { |
401 | m_fallHeight = actor.Position.Z; // save latest flying height | 506 | currentControlState = motionControlStates.onsurface; |
507 | m_animTickLand = 0; | ||
402 | return "STAND"; | 508 | return "STAND"; |
403 | } | 509 | } |
404 | } | 510 | } |
405 | 511 | ||
406 | // next section moved outside paren. and realigned for jumping | 512 | // next section moved outside paren. and realigned for jumping |
407 | if (move.X != 0f || move.Y != 0f) | 513 | |
514 | if (heldOnXY) | ||
408 | { | 515 | { |
409 | m_fallHeight = actor.Position.Z; // save latest flying height | 516 | currentControlState = motionControlStates.onsurface; |
410 | Falling = false; | 517 | Falling = false; |
411 | // Walking / crouchwalking / running | 518 | // Walking / crouchwalking / running |
412 | if (move.Z < 0f) | 519 | if (heldDown) |
520 | { | ||
413 | return "CROUCHWALK"; | 521 | return "CROUCHWALK"; |
414 | else if (m_scenePresence.SetAlwaysRun) | 522 | } |
415 | return "RUN"; | 523 | // We need to prevent these animations if the user tries to make their avatar walk or run whilst |
416 | else | 524 | // specifying AGENT_CONTROL_STOP (pressing down space on viewers). |
417 | return "WALK"; | 525 | else if (!m_scenePresence.AgentControlStopActive) |
526 | { | ||
527 | if (m_scenePresence.SetAlwaysRun) | ||
528 | return "RUN"; | ||
529 | else | ||
530 | return "WALK"; | ||
531 | } | ||
418 | } | 532 | } |
419 | else if (!m_jumping) | 533 | else |
420 | { | 534 | { |
535 | currentControlState = motionControlStates.onsurface; | ||
421 | Falling = false; | 536 | Falling = false; |
422 | // Not walking | 537 | // Not walking |
423 | if (move.Z < 0) | 538 | if (heldDown) |
424 | return "CROUCH"; | 539 | return "CROUCH"; |
425 | else if (heldTurnLeft) | 540 | else if (heldTurnLeft) |
426 | return "TURNLEFT"; | 541 | return "TURNLEFT"; |
@@ -431,22 +546,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
431 | } | 546 | } |
432 | #endregion Ground Movement | 547 | #endregion Ground Movement |
433 | 548 | ||
434 | Falling = false; | ||
435 | |||
436 | return CurrentMovementAnimation; | 549 | return CurrentMovementAnimation; |
437 | } | 550 | } |
438 | 551 | ||
439 | /// <summary> | 552 | /// <summary> |
440 | /// Update the movement animation of this avatar according to its current state | 553 | /// Update the movement animation of this avatar according to its current state |
441 | /// </summary> | 554 | /// </summary> |
442 | public void UpdateMovementAnimations() | 555 | /// <returns>'true' if the animation was changed</returns> |
556 | public bool UpdateMovementAnimations() | ||
443 | { | 557 | { |
558 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name); | ||
559 | |||
560 | bool ret = false; | ||
444 | lock (m_animations) | 561 | lock (m_animations) |
445 | { | 562 | { |
446 | string newMovementAnimation = DetermineMovementAnimation(); | 563 | string newMovementAnimation = DetermineMovementAnimation(); |
447 | if (CurrentMovementAnimation != newMovementAnimation) | 564 | if (CurrentMovementAnimation != newMovementAnimation) |
448 | { | 565 | { |
449 | CurrentMovementAnimation = DetermineMovementAnimation(); | 566 | CurrentMovementAnimation = newMovementAnimation; |
450 | 567 | ||
451 | // m_log.DebugFormat( | 568 | // m_log.DebugFormat( |
452 | // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", | 569 | // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", |
@@ -454,9 +571,28 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
454 | 571 | ||
455 | // Only set it if it's actually changed, give a script | 572 | // Only set it if it's actually changed, give a script |
456 | // a chance to stop a default animation | 573 | // a chance to stop a default animation |
457 | TrySetMovementAnimation(CurrentMovementAnimation); | 574 | ret = TrySetMovementAnimation(CurrentMovementAnimation); |
458 | } | 575 | } |
459 | } | 576 | } |
577 | return ret; | ||
578 | } | ||
579 | |||
580 | public bool ForceUpdateMovementAnimations() | ||
581 | { | ||
582 | lock (m_animations) | ||
583 | { | ||
584 | CurrentMovementAnimation = DetermineMovementAnimation(); | ||
585 | return TrySetMovementAnimation(CurrentMovementAnimation); | ||
586 | } | ||
587 | } | ||
588 | |||
589 | public bool SetMovementAnimations(string motionState) | ||
590 | { | ||
591 | lock (m_animations) | ||
592 | { | ||
593 | CurrentMovementAnimation = motionState; | ||
594 | return TrySetMovementAnimation(CurrentMovementAnimation); | ||
595 | } | ||
460 | } | 596 | } |
461 | 597 | ||
462 | public UUID[] GetAnimationArray() | 598 | public UUID[] GetAnimationArray() |
@@ -467,19 +603,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
467 | m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); | 603 | m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); |
468 | return animIDs; | 604 | return animIDs; |
469 | } | 605 | } |
470 | 606 | ||
471 | public BinBVHAnimation GenerateRandomAnimation() | 607 | public BinBVHAnimation GenerateRandomAnimation() |
472 | { | 608 | { |
473 | int rnditerations = 3; | 609 | int rnditerations = 3; |
474 | BinBVHAnimation anim = new BinBVHAnimation(); | 610 | BinBVHAnimation anim = new BinBVHAnimation(); |
475 | List<string> parts = new List<string>(); | 611 | List<string> parts = new List<string>(); |
476 | parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); | 612 | parts.Add("mPelvis"); parts.Add("mHead"); parts.Add("mTorso"); |
477 | parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft"); | 613 | parts.Add("mHipLeft"); parts.Add("mHipRight"); parts.Add("mHipLeft"); parts.Add("mKneeLeft"); |
478 | parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck"); | 614 | parts.Add("mKneeRight"); parts.Add("mCollarLeft"); parts.Add("mCollarRight"); parts.Add("mNeck"); |
479 | parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight"); | 615 | parts.Add("mElbowLeft"); parts.Add("mElbowRight"); parts.Add("mWristLeft"); parts.Add("mWristRight"); |
480 | parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight"); | 616 | parts.Add("mShoulderLeft"); parts.Add("mShoulderRight"); parts.Add("mAnkleLeft"); parts.Add("mAnkleRight"); |
481 | parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight"); | 617 | parts.Add("mEyeRight"); parts.Add("mChest"); parts.Add("mToeLeft"); parts.Add("mToeRight"); |
482 | parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); | 618 | parts.Add("mFootLeft"); parts.Add("mFootRight"); parts.Add("mEyeLeft"); |
483 | anim.HandPose = 1; | 619 | anim.HandPose = 1; |
484 | anim.InPoint = 0; | 620 | anim.InPoint = 0; |
485 | anim.OutPoint = (rnditerations * .10f); | 621 | anim.OutPoint = (rnditerations * .10f); |
@@ -503,12 +639,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
503 | for (int i = 0; i < rnditerations; i++) | 639 | for (int i = 0; i < rnditerations; i++) |
504 | { | 640 | { |
505 | anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); | 641 | anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); |
506 | anim.Joints[j].rotationkeys[i].time = (i*.10f); | 642 | anim.Joints[j].rotationkeys[i].time = (i * .10f); |
507 | anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1); | 643 | anim.Joints[j].rotationkeys[i].key_element.X = ((float)rnd.NextDouble() * 2 - 1); |
508 | anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1); | 644 | anim.Joints[j].rotationkeys[i].key_element.Y = ((float)rnd.NextDouble() * 2 - 1); |
509 | anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1); | 645 | anim.Joints[j].rotationkeys[i].key_element.Z = ((float)rnd.NextDouble() * 2 - 1); |
510 | anim.Joints[j].positionkeys[i] = new binBVHJointKey(); | 646 | anim.Joints[j].positionkeys[i] = new binBVHJointKey(); |
511 | anim.Joints[j].positionkeys[i].time = (i*.10f); | 647 | anim.Joints[j].positionkeys[i].time = (i * .10f); |
512 | anim.Joints[j].positionkeys[i].key_element.X = 0; | 648 | anim.Joints[j].positionkeys[i].key_element.X = 0; |
513 | anim.Joints[j].positionkeys[i].key_element.Y = 0; | 649 | anim.Joints[j].positionkeys[i].key_element.Y = 0; |
514 | anim.Joints[j].positionkeys[i].key_element.Z = 0; | 650 | anim.Joints[j].positionkeys[i].key_element.Z = 0; |
@@ -535,20 +671,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
535 | /// <param name="objectIDs"></param> | 671 | /// <param name="objectIDs"></param> |
536 | public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) | 672 | public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) |
537 | { | 673 | { |
538 | if (m_scenePresence.IsChildAgent) | 674 | m_scenePresence.SendAnimPack(animations, seqs, objectIDs); |
539 | return; | 675 | } |
540 | 676 | ||
541 | // m_log.DebugFormat( | 677 | public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs) |
542 | // "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'", | 678 | { |
543 | // string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), | 679 | animIDs = null; |
544 | // string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), | 680 | sequenceNums = null; |
545 | // string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); | 681 | objectIDs = null; |
546 | 682 | ||
547 | m_scenePresence.Scene.ForEachClient( | 683 | if (m_animations != null) |
548 | delegate(IClientAPI client) | 684 | m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); |
549 | { | ||
550 | client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs); | ||
551 | }); | ||
552 | } | 685 | } |
553 | 686 | ||
554 | public void SendAnimPackToClient(IClientAPI client) | 687 | public void SendAnimPackToClient(IClientAPI client) |
@@ -570,7 +703,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
570 | public void SendAnimPack() | 703 | public void SendAnimPack() |
571 | { | 704 | { |
572 | //m_log.Debug("Sending animation pack to all"); | 705 | //m_log.Debug("Sending animation pack to all"); |
573 | 706 | ||
574 | if (m_scenePresence.IsChildAgent) | 707 | if (m_scenePresence.IsChildAgent) |
575 | return; | 708 | return; |
576 | 709 | ||
@@ -580,7 +713,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
580 | 713 | ||
581 | m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); | 714 | m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); |
582 | 715 | ||
583 | SendAnimPack(animIDs, sequenceNums, objectIDs); | 716 | // SendAnimPack(animIDs, sequenceNums, objectIDs); |
717 | m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs); | ||
584 | } | 718 | } |
585 | 719 | ||
586 | public string GetAnimName(UUID animId) | 720 | public string GetAnimName(UUID animId) |
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index f555b49..11a0146 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs | |||
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
104 | // better than losing the object for now. | 104 | // better than losing the object for now. |
105 | if (permissionToDelete) | 105 | if (permissionToDelete) |
106 | { | 106 | { |
107 | List<uint> killIDs = new List<uint>(); | ||
108 | |||
109 | foreach (SceneObjectGroup g in objectGroups) | 107 | foreach (SceneObjectGroup g in objectGroups) |
110 | { killIDs.Add(g.LocalId); | 108 | g.DeleteGroupFromScene(false); |
111 | g.DeleteGroupFromScene(true); | ||
112 | } | ||
113 | |||
114 | m_scene.SendKillObject(killIDs); | ||
115 | } | 109 | } |
116 | } | 110 | } |
117 | 111 | ||
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
160 | if (x.permissionToDelete) | 154 | if (x.permissionToDelete) |
161 | { | 155 | { |
162 | foreach (SceneObjectGroup g in x.objectGroups) | 156 | foreach (SceneObjectGroup g in x.objectGroups) |
163 | m_scene.DeleteSceneObject(g, false); | 157 | m_scene.DeleteSceneObject(g, true); |
164 | } | 158 | } |
165 | } | 159 | } |
166 | catch (Exception e) | 160 | catch (Exception e) |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 4733547..692e0c9 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
148 | /// Triggered when a new presence is added to the scene | 148 | /// Triggered when a new presence is added to the scene |
149 | /// </summary> | 149 | /// </summary> |
150 | /// <remarks> | 150 | /// <remarks> |
151 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both | 151 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both |
152 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> | 152 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> |
153 | /// </remarks> | 153 | /// </remarks> |
154 | public event OnNewPresenceDelegate OnNewPresence; | 154 | public event OnNewPresenceDelegate OnNewPresence; |
@@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
159 | /// Triggered when a presence is removed from the scene | 159 | /// Triggered when a presence is removed from the scene |
160 | /// </summary> | 160 | /// </summary> |
161 | /// <remarks> | 161 | /// <remarks> |
162 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both | 162 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both |
163 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> | 163 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> |
164 | /// | 164 | /// |
165 | /// Triggered under per-agent lock. So if you want to perform any long-running operations, please | 165 | /// Triggered under per-agent lock. So if you want to perform any long-running operations, please |
@@ -743,7 +743,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
743 | public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; | 743 | public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; |
744 | public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); | 744 | public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); |
745 | 745 | ||
746 | public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); | 746 | public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel); |
747 | 747 | ||
748 | public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; | 748 | public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; |
749 | 749 | ||
@@ -974,6 +974,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
974 | public delegate void RegionStarted(Scene scene); | 974 | public delegate void RegionStarted(Scene scene); |
975 | public event RegionStarted OnRegionStarted; | 975 | public event RegionStarted OnRegionStarted; |
976 | 976 | ||
977 | public delegate void RegionHeartbeatStart(Scene scene); | ||
978 | public event RegionHeartbeatStart OnRegionHeartbeatStart; | ||
977 | public delegate void RegionHeartbeatEnd(Scene scene); | 979 | public delegate void RegionHeartbeatEnd(Scene scene); |
978 | public event RegionHeartbeatEnd OnRegionHeartbeatEnd; | 980 | public event RegionHeartbeatEnd OnRegionHeartbeatEnd; |
979 | 981 | ||
@@ -1024,6 +1026,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1024 | /// </remarks> | 1026 | /// </remarks> |
1025 | public event TeleportFail OnTeleportFail; | 1027 | public event TeleportFail OnTeleportFail; |
1026 | 1028 | ||
1029 | // public delegate void GatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids); | ||
1030 | // | ||
1031 | // /// <summary> | ||
1032 | // /// Triggered when UUIDs referenced by a scene object are being gathered for archiving, hg transfer, etc. | ||
1033 | // /// </summary> | ||
1034 | // /// <remarks> | ||
1035 | // /// The listener should add references to the IDictionary<UUID, AssetType> as appropriate. | ||
1036 | // /// </remarks> | ||
1037 | // public event GatherUuids OnGatherUuids; | ||
1038 | |||
1027 | public class MoneyTransferArgs : EventArgs | 1039 | public class MoneyTransferArgs : EventArgs |
1028 | { | 1040 | { |
1029 | public UUID sender; | 1041 | public UUID sender; |
@@ -1095,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1095 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> | 1107 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> |
1096 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> | 1108 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> |
1097 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> | 1109 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> |
1098 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> | 1110 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> |
1099 | /// </remarks> | 1111 | /// </remarks> |
1100 | public event MoneyTransferEvent OnMoneyTransfer; | 1112 | public event MoneyTransferEvent OnMoneyTransfer; |
1101 | 1113 | ||
@@ -1354,7 +1366,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1354 | { | 1366 | { |
1355 | try | 1367 | try |
1356 | { | 1368 | { |
1369 | // m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate: {0}",d.Target.ToString()); | ||
1357 | d(agentId); | 1370 | d(agentId); |
1371 | // m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate done "); | ||
1358 | } | 1372 | } |
1359 | catch (Exception e) | 1373 | catch (Exception e) |
1360 | { | 1374 | { |
@@ -2025,7 +2039,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2025 | { | 2039 | { |
2026 | try | 2040 | try |
2027 | { | 2041 | { |
2042 | // m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed: {0}", d.Target.ToString()); | ||
2028 | d(ClientID, scene); | 2043 | d(ClientID, scene); |
2044 | // m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed done "); | ||
2045 | |||
2029 | } | 2046 | } |
2030 | catch (Exception e) | 2047 | catch (Exception e) |
2031 | { | 2048 | { |
@@ -2160,7 +2177,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2160 | } | 2177 | } |
2161 | } | 2178 | } |
2162 | 2179 | ||
2163 | public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) | 2180 | public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel) |
2164 | { | 2181 | { |
2165 | NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; | 2182 | NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; |
2166 | if (handlerNewInventoryItemUpdateComplete != null) | 2183 | if (handlerNewInventoryItemUpdateComplete != null) |
@@ -2169,7 +2186,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2169 | { | 2186 | { |
2170 | try | 2187 | try |
2171 | { | 2188 | { |
2172 | d(agentID, AssetID, AssetName, userlevel); | 2189 | d(agentID, type, AssetID, AssetName, userlevel); |
2173 | } | 2190 | } |
2174 | catch (Exception e) | 2191 | catch (Exception e) |
2175 | { | 2192 | { |
@@ -3096,6 +3113,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
3096 | } | 3113 | } |
3097 | } | 3114 | } |
3098 | 3115 | ||
3116 | public void TriggerRegionHeartbeatStart(Scene scene) | ||
3117 | { | ||
3118 | RegionHeartbeatStart handler = OnRegionHeartbeatStart; | ||
3119 | |||
3120 | if (handler != null) | ||
3121 | { | ||
3122 | foreach (RegionHeartbeatStart d in handler.GetInvocationList()) | ||
3123 | { | ||
3124 | try | ||
3125 | { | ||
3126 | d(scene); | ||
3127 | } | ||
3128 | catch (Exception e) | ||
3129 | { | ||
3130 | m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}", | ||
3131 | e.Message, e.StackTrace); | ||
3132 | } | ||
3133 | } | ||
3134 | } | ||
3135 | } | ||
3136 | |||
3099 | public void TriggerRegionHeartbeatEnd(Scene scene) | 3137 | public void TriggerRegionHeartbeatEnd(Scene scene) |
3100 | { | 3138 | { |
3101 | RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; | 3139 | RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; |
@@ -3251,5 +3289,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
3251 | handler(scenePresence); | 3289 | handler(scenePresence); |
3252 | } | 3290 | } |
3253 | } | 3291 | } |
3292 | |||
3293 | // public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids) | ||
3294 | // { | ||
3295 | // GatherUuids handler = OnGatherUuids; | ||
3296 | // | ||
3297 | // if (handler != null) | ||
3298 | // { | ||
3299 | // foreach (GatherUuids d in handler.GetInvocationList()) | ||
3300 | // { | ||
3301 | // try | ||
3302 | // { | ||
3303 | // d(sop, assetUuids); | ||
3304 | // } | ||
3305 | // catch (Exception e) | ||
3306 | // { | ||
3307 | // m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}", | ||
3308 | // e.Message, e.StackTrace); | ||
3309 | // } | ||
3310 | // } | ||
3311 | // } | ||
3312 | // } | ||
3254 | } | 3313 | } |
3255 | } | 3314 | } |
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index f0e639d..e3f979f 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | |||
@@ -1,6 +1,29 @@ | |||
1 | // Proprietary code of Avination Virtual Limited | 1 | /* |
2 | // (c) 2012 Melanie Thielker | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | // | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
4 | 27 | ||
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 | { |
@@ -303,22 +323,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
303 | m_group = grp; | 323 | m_group = grp; |
304 | m_scene = grp.Scene; | 324 | m_scene = grp.Scene; |
305 | 325 | ||
306 | Vector3 grppos = grp.AbsolutePosition; | 326 | lock (m_frames) |
307 | Vector3 offset = grppos - m_serializedPosition; | 327 | { |
308 | // avoid doing it more than once | 328 | Vector3 grppos = grp.AbsolutePosition; |
309 | // current this will happen draging a prim to other region | 329 | Vector3 offset = grppos - m_serializedPosition; |
310 | m_serializedPosition = grppos; | 330 | // avoid doing it more than once |
331 | // current this will happen draging a prim to other region | ||
332 | m_serializedPosition = grppos; | ||
311 | 333 | ||
312 | m_basePosition += offset; | 334 | m_basePosition += offset; |
313 | m_currentFrame.Position += offset; | 335 | m_currentFrame.Position += offset; |
314 | 336 | ||
315 | m_nextPosition += offset; | 337 | m_nextPosition += offset; |
316 | 338 | ||
317 | for (int i = 0; i < m_frames.Count; i++) | 339 | for (int i = 0; i < m_frames.Count; i++) |
318 | { | 340 | { |
319 | Keyframe k = m_frames[i]; | 341 | Keyframe k = m_frames[i]; |
320 | k.Position += offset; | 342 | k.Position += offset; |
321 | m_frames[i]=k; | 343 | m_frames[i] = k; |
344 | } | ||
322 | } | 345 | } |
323 | 346 | ||
324 | if (m_running) | 347 | if (m_running) |
@@ -363,25 +386,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
363 | m_keyframes.CopyTo(newmotion.m_keyframes, 0); | 386 | m_keyframes.CopyTo(newmotion.m_keyframes, 0); |
364 | } | 387 | } |
365 | 388 | ||
366 | newmotion.m_frames = new List<Keyframe>(m_frames); | 389 | lock (m_frames) |
390 | { | ||
391 | newmotion.m_frames = new List<Keyframe>(m_frames); | ||
367 | 392 | ||
368 | newmotion.m_basePosition = m_basePosition; | 393 | newmotion.m_basePosition = m_basePosition; |
369 | newmotion.m_baseRotation = m_baseRotation; | 394 | newmotion.m_baseRotation = m_baseRotation; |
370 | 395 | ||
371 | if (m_selected) | 396 | if (m_selected) |
372 | newmotion.m_serializedPosition = m_serializedPosition; | ||
373 | else | ||
374 | { | ||
375 | if (m_group != null) | ||
376 | newmotion.m_serializedPosition = m_group.AbsolutePosition; | ||
377 | else | ||
378 | newmotion.m_serializedPosition = m_serializedPosition; | 397 | newmotion.m_serializedPosition = m_serializedPosition; |
379 | } | 398 | else |
399 | { | ||
400 | if (m_group != null) | ||
401 | newmotion.m_serializedPosition = m_group.AbsolutePosition; | ||
402 | else | ||
403 | newmotion.m_serializedPosition = m_serializedPosition; | ||
404 | } | ||
380 | 405 | ||
381 | newmotion.m_currentFrame = m_currentFrame; | 406 | newmotion.m_currentFrame = m_currentFrame; |
382 | 407 | ||
383 | newmotion.m_iterations = m_iterations; | 408 | newmotion.m_iterations = m_iterations; |
384 | newmotion.m_running = m_running; | 409 | newmotion.m_running = m_running; |
410 | } | ||
385 | 411 | ||
386 | if (m_running && !m_waitingCrossing) | 412 | if (m_running && !m_waitingCrossing) |
387 | StartTimer(); | 413 | StartTimer(); |
@@ -598,7 +624,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
598 | return; | 624 | return; |
599 | } | 625 | } |
600 | 626 | ||
601 | |||
602 | if (m_group == null) | 627 | if (m_group == null) |
603 | return; | 628 | return; |
604 | 629 | ||
@@ -610,7 +635,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
610 | { | 635 | { |
611 | m_group.RootPart.Velocity = Vector3.Zero; | 636 | m_group.RootPart.Velocity = Vector3.Zero; |
612 | m_group.SendGroupRootTerseUpdate(); | 637 | m_group.SendGroupRootTerseUpdate(); |
613 | |||
614 | } | 638 | } |
615 | return; | 639 | return; |
616 | } | 640 | } |
@@ -633,28 +657,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
633 | 657 | ||
634 | if (m_frames.Count == 0) | 658 | if (m_frames.Count == 0) |
635 | { | 659 | { |
636 | GetNextList(); | 660 | lock (m_frames) |
637 | |||
638 | if (m_frames.Count == 0) | ||
639 | { | 661 | { |
640 | Done(); | 662 | GetNextList(); |
641 | Scene scene = m_group.Scene; | ||
642 | 663 | ||
643 | IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>(); | 664 | if (m_frames.Count == 0) |
644 | foreach (IScriptModule m in scriptModules) | ||
645 | { | 665 | { |
646 | if (m == null) | 666 | Done(); |
647 | continue; | 667 | Scene scene = m_group.Scene; |
648 | m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]); | ||
649 | } | ||
650 | 668 | ||
651 | return; | 669 | IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>(); |
652 | } | 670 | foreach (IScriptModule m in scriptModules) |
671 | { | ||
672 | if (m == null) | ||
673 | continue; | ||
674 | m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]); | ||
675 | } | ||
653 | 676 | ||
654 | m_currentFrame = m_frames[0]; | 677 | return; |
655 | m_currentFrame.TimeMS += (int)tickDuration; | 678 | } |
656 | 679 | ||
680 | m_currentFrame = m_frames[0]; | ||
681 | m_currentFrame.TimeMS += (int)tickDuration; | ||
682 | } | ||
657 | //force a update on a keyframe transition | 683 | //force a update on a keyframe transition |
684 | m_nextPosition = m_group.AbsolutePosition; | ||
658 | update = true; | 685 | update = true; |
659 | } | 686 | } |
660 | 687 | ||
@@ -662,7 +689,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
662 | 689 | ||
663 | // Do the frame processing | 690 | // Do the frame processing |
664 | double steps = (double)m_currentFrame.TimeMS / tickDuration; | 691 | double steps = (double)m_currentFrame.TimeMS / tickDuration; |
665 | 692 | ||
666 | if (steps <= 0.0) | 693 | if (steps <= 0.0) |
667 | { | 694 | { |
668 | m_group.RootPart.Velocity = Vector3.Zero; | 695 | m_group.RootPart.Velocity = Vector3.Zero; |
@@ -675,9 +702,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
675 | // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); | 702 | // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); |
676 | 703 | ||
677 | m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; | 704 | m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; |
678 | m_frames.RemoveAt(0); | 705 | |
679 | if (m_frames.Count > 0) | 706 | lock (m_frames) |
680 | m_currentFrame = m_frames[0]; | 707 | { |
708 | m_frames.RemoveAt(0); | ||
709 | if (m_frames.Count > 0) | ||
710 | m_currentFrame = m_frames[0]; | ||
711 | } | ||
681 | 712 | ||
682 | update = true; | 713 | update = true; |
683 | } | 714 | } |
@@ -689,15 +720,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
689 | Vector3 motionThisFrame = v / (float)steps; | 720 | Vector3 motionThisFrame = v / (float)steps; |
690 | v = v * 1000 / m_currentFrame.TimeMS; | 721 | v = v * 1000 / m_currentFrame.TimeMS; |
691 | 722 | ||
692 | if (Vector3.Mag(motionThisFrame) >= 0.05f) | 723 | m_nextPosition = m_group.AbsolutePosition + motionThisFrame; |
693 | { | ||
694 | // m_group.AbsolutePosition += motionThisFrame; | ||
695 | m_nextPosition = m_group.AbsolutePosition + motionThisFrame; | ||
696 | m_group.AbsolutePosition = m_nextPosition; | ||
697 | 724 | ||
698 | //m_group.RootPart.Velocity = v; | 725 | if (Vector3.Mag(motionThisFrame) >= 0.05f) |
699 | update = true; | 726 | update = true; |
700 | } | ||
701 | 727 | ||
702 | if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) | 728 | if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) |
703 | { | 729 | { |
@@ -705,43 +731,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
705 | 731 | ||
706 | Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); | 732 | Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); |
707 | step.Normalize(); | 733 | step.Normalize(); |
708 | /* use simpler change detection | 734 | /* use simpler change detection |
709 | * float angle = 0; | 735 | * float angle = 0; |
710 | 736 | ||
711 | float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; | 737 | float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; |
712 | float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; | 738 | float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; |
713 | float aa_bb = aa * bb; | 739 | float aa_bb = aa * bb; |
714 | 740 | ||
715 | if (aa_bb == 0) | 741 | if (aa_bb == 0) |
716 | { | 742 | { |
717 | angle = 0; | 743 | angle = 0; |
718 | } | 744 | } |
719 | else | 745 | else |
720 | { | 746 | { |
721 | float ab = current.X * step.X + | 747 | float ab = current.X * step.X + |
722 | current.Y * step.Y + | 748 | current.Y * step.Y + |
723 | current.Z * step.Z + | 749 | current.Z * step.Z + |
724 | current.W * step.W; | 750 | current.W * step.W; |
725 | float q = (ab * ab) / aa_bb; | 751 | float q = (ab * ab) / aa_bb; |
726 | 752 | ||
727 | if (q > 1.0f) | 753 | if (q > 1.0f) |
728 | { | 754 | { |
729 | angle = 0; | 755 | angle = 0; |
730 | } | 756 | } |
731 | else | 757 | else |
732 | { | 758 | { |
733 | angle = (float)Math.Acos(2 * q - 1); | 759 | angle = (float)Math.Acos(2 * q - 1); |
734 | } | 760 | } |
735 | } | 761 | } |
736 | 762 | ||
737 | if (angle > 0.01f) | 763 | if (angle > 0.01f) |
738 | */ | 764 | */ |
739 | if (Math.Abs(step.X - current.X) > 0.001f | 765 | if (Math.Abs(step.X - current.X) > 0.001f |
740 | || Math.Abs(step.Y - current.Y) > 0.001f | 766 | || Math.Abs(step.Y - current.Y) > 0.001f |
741 | || Math.Abs(step.Z - current.Z) > 0.001f) | 767 | || Math.Abs(step.Z - current.Z) > 0.001f) |
742 | // assuming w is a dependente var | 768 | // assuming w is a dependente var |
743 | { | 769 | { |
744 | // m_group.UpdateGroupRotationR(step); | 770 | // m_group.UpdateGroupRotationR(step); |
745 | m_group.RootPart.RotationOffset = step; | 771 | m_group.RootPart.RotationOffset = step; |
746 | 772 | ||
747 | //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); | 773 | //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); |
@@ -752,12 +778,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
752 | 778 | ||
753 | if (update) | 779 | if (update) |
754 | { | 780 | { |
781 | m_group.AbsolutePosition = m_nextPosition; | ||
755 | m_group.SendGroupRootTerseUpdate(); | 782 | m_group.SendGroupRootTerseUpdate(); |
756 | } | 783 | } |
757 | } | 784 | } |
758 | 785 | ||
759 | public Byte[] Serialize() | 786 | public Byte[] Serialize() |
760 | { | 787 | { |
788 | bool timerWasStopped; | ||
789 | lock (m_frames) | ||
790 | { | ||
791 | timerWasStopped = m_timerStopped; | ||
792 | } | ||
761 | StopTimer(); | 793 | StopTimer(); |
762 | MemoryStream ms = new MemoryStream(); | 794 | MemoryStream ms = new MemoryStream(); |
763 | 795 | ||
@@ -768,7 +800,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
768 | m_serializedPosition = tmp.AbsolutePosition; | 800 | m_serializedPosition = tmp.AbsolutePosition; |
769 | fmt.Serialize(ms, this); | 801 | fmt.Serialize(ms, this); |
770 | m_group = tmp; | 802 | m_group = tmp; |
771 | if (m_running && !m_waitingCrossing) | 803 | if (!timerWasStopped && m_running && !m_waitingCrossing) |
772 | StartTimer(); | 804 | StartTimer(); |
773 | 805 | ||
774 | return ms.ToArray(); | 806 | return ms.ToArray(); |
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index ddae073..c0405ad 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs | |||
@@ -91,6 +91,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
91 | return 0; | 91 | return 0; |
92 | 92 | ||
93 | uint priority; | 93 | uint priority; |
94 | |||
95 | |||
96 | // HACK | ||
97 | return GetPriorityByBestAvatarResponsiveness(client, entity); | ||
98 | |||
94 | 99 | ||
95 | switch (m_scene.UpdatePrioritizationScheme) | 100 | switch (m_scene.UpdatePrioritizationScheme) |
96 | { | 101 | { |
@@ -157,30 +162,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
157 | 162 | ||
158 | private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) | 163 | private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) |
159 | { | 164 | { |
160 | uint pqueue = ComputeDistancePriority(client,entity,false); | 165 | uint pqueue = 2; // keep compiler happy |
161 | 166 | ||
162 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); | 167 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); |
163 | if (presence != null) | 168 | if (presence != null) |
164 | { | 169 | { |
165 | if (!presence.IsChildAgent) | 170 | // All avatars other than our own go into pqueue 1 |
171 | if (entity is ScenePresence) | ||
172 | return 1; | ||
173 | |||
174 | if (entity is SceneObjectPart) | ||
166 | { | 175 | { |
167 | // All avatars other than our own go into pqueue 1 | 176 | // Attachments are high priority, |
168 | if (entity is ScenePresence) | 177 | if (((SceneObjectPart)entity).ParentGroup.IsAttachment) |
169 | return 1; | 178 | return 2; |
170 | 179 | ||
171 | if (entity is SceneObjectPart) | 180 | pqueue = ComputeDistancePriority(client, entity, false); |
172 | { | 181 | |
173 | // Attachments are high priority, | 182 | // Non physical prims are lower priority than physical prims |
174 | if (((SceneObjectPart)entity).ParentGroup.IsAttachment) | 183 | PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; |
175 | return 1; | 184 | if (physActor == null || !physActor.IsPhysical) |
176 | 185 | pqueue++; | |
177 | // Non physical prims are lower priority than physical prims | ||
178 | PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; | ||
179 | if (physActor == null || !physActor.IsPhysical) | ||
180 | pqueue++; | ||
181 | } | ||
182 | } | 186 | } |
183 | } | 187 | } |
188 | else | ||
189 | pqueue = ComputeDistancePriority(client, entity, false); | ||
184 | 190 | ||
185 | return pqueue; | 191 | return pqueue; |
186 | } | 192 | } |
@@ -227,16 +233,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
227 | 233 | ||
228 | // And convert the distance to a priority queue, this computation gives queues | 234 | // And convert the distance to a priority queue, this computation gives queues |
229 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m | 235 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m |
230 | uint pqueue = PriorityQueue.NumberOfImmediateQueues; | 236 | uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue |
231 | uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; | 237 | uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; |
232 | 238 | /* | |
233 | for (int i = 0; i < queues - 1; i++) | 239 | for (int i = 0; i < queues - 1; i++) |
234 | { | 240 | { |
235 | if (distance < 30 * Math.Pow(2.0,i)) | 241 | if (distance < 30 * Math.Pow(2.0,i)) |
236 | break; | 242 | break; |
237 | pqueue++; | 243 | pqueue++; |
238 | } | 244 | } |
239 | 245 | */ | |
246 | if (distance > 10f) | ||
247 | { | ||
248 | float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f; | ||
249 | // for a map identical to original: | ||
250 | // now | ||
251 | // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) | ||
252 | // 2st constant makes it be log2(distance/10) | ||
253 | pqueue += (uint)tmp; | ||
254 | if (pqueue > queues - 1) | ||
255 | pqueue = queues - 1; | ||
256 | } | ||
257 | |||
240 | // If this is a root agent, then determine front & back | 258 | // If this is a root agent, then determine front & back |
241 | // Bump up the priority queue (drop the priority) for any objects behind the avatar | 259 | // Bump up the priority queue (drop the priority) for any objects behind the avatar |
242 | if (useFrontBack && ! presence.IsChildAgent) | 260 | if (useFrontBack && ! presence.IsChildAgent) |
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs index c11174d..f208afb 100644 --- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs +++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs | |||
@@ -46,47 +46,33 @@ using OpenSim.Region.Framework.Scenes; | |||
46 | 46 | ||
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 d70aa45..746a5ce 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -31,6 +31,7 @@ using System.Collections; | |||
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 |
@@ -1005,6 +1023,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1005 | item.BasePermissions = baseMask; | 1023 | item.BasePermissions = baseMask; |
1006 | item.CreationDate = creationDate; | 1024 | item.CreationDate = creationDate; |
1007 | 1025 | ||
1026 | // special AnimationSet case | ||
1027 | if (item.InvType == (int)CustomInventoryType.AnimationSet) | ||
1028 | AnimationSet.enforceItemPermitions(item,true); | ||
1029 | |||
1008 | if (AddInventoryItem(item)) | 1030 | if (AddInventoryItem(item)) |
1009 | { | 1031 | { |
1010 | remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID); | 1032 | remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID); |
@@ -1213,9 +1235,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1213 | { | 1235 | { |
1214 | agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); | 1236 | agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); |
1215 | if (taskItem.InvType == (int)InventoryType.Object) | 1237 | if (taskItem.InvType == (int)InventoryType.Object) |
1216 | agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); | 1238 | { |
1217 | else | 1239 | uint perms = taskItem.BasePermissions & taskItem.NextPermissions; |
1218 | agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; | 1240 | PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms); |
1241 | // agentItem.BasePermissions = perms | (uint)PermissionMask.Move; | ||
1242 | // agentItem.CurrentPermissions = agentItem.BasePermissions; | ||
1243 | agentItem.BasePermissions = perms | (uint)PermissionMask.Move; | ||
1244 | } | ||
1245 | |||
1246 | agentItem.CurrentPermissions = agentItem.BasePermissions; | ||
1219 | 1247 | ||
1220 | agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; | 1248 | agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; |
1221 | agentItem.NextPermissions = taskItem.NextPermissions; | 1249 | agentItem.NextPermissions = taskItem.NextPermissions; |
@@ -2068,9 +2096,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2068 | // If child prims have invalid perms, fix them | 2096 | // If child prims have invalid perms, fix them |
2069 | grp.AdjustChildPrimPermissions(); | 2097 | grp.AdjustChildPrimPermissions(); |
2070 | 2098 | ||
2071 | // If child prims have invalid perms, fix them | ||
2072 | grp.AdjustChildPrimPermissions(); | ||
2073 | |||
2074 | if (remoteClient == null) | 2099 | if (remoteClient == null) |
2075 | { | 2100 | { |
2076 | // Autoreturn has a null client. Nothing else does. So | 2101 | // Autoreturn has a null client. Nothing else does. So |
@@ -2124,7 +2149,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2124 | { | 2149 | { |
2125 | // If we don't have permission, stop right here | 2150 | // If we don't have permission, stop right here |
2126 | if (!permissionToTakeCopy) | 2151 | if (!permissionToTakeCopy) |
2152 | { | ||
2153 | remoteClient.SendAlertMessage("You don't have permission to take the object"); | ||
2127 | return; | 2154 | return; |
2155 | } | ||
2128 | 2156 | ||
2129 | permissionToTake = true; | 2157 | permissionToTake = true; |
2130 | // Don't delete | 2158 | // Don't delete |
@@ -2277,6 +2305,88 @@ namespace OpenSim.Region.Framework.Scenes | |||
2277 | } | 2305 | } |
2278 | 2306 | ||
2279 | /// <summary> | 2307 | /// <summary> |
2308 | /// Returns the list of Scene Objects in an asset. | ||
2309 | /// </summary> | ||
2310 | /// <remarks> | ||
2311 | /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object. | ||
2312 | /// </remarks> | ||
2313 | /// <param name="assetData">Asset data</param> | ||
2314 | /// <param name="attachment">Whether the item is an attachment</param> | ||
2315 | /// <param name="objlist">The objects included in the asset</param> | ||
2316 | /// <param name="veclist">Relative positions of the objects</param> | ||
2317 | /// <param name="bbox">Bounding box of all the objects</param> | ||
2318 | /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box | ||
2319 | /// to the centre of the root prim (relevant only when returning a single object)</param> | ||
2320 | /// <returns>true = returning a single object; false = multiple objects</returns> | ||
2321 | public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, | ||
2322 | out Vector3 bbox, out float offsetHeight) | ||
2323 | { | ||
2324 | objlist = new List<SceneObjectGroup>(); | ||
2325 | veclist = new List<Vector3>(); | ||
2326 | |||
2327 | XmlDocument doc = new XmlDocument(); | ||
2328 | string xmlData = Utils.BytesToString(assetData); | ||
2329 | doc.LoadXml(xmlData); | ||
2330 | XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); | ||
2331 | |||
2332 | if (e == null || attachment) // Single | ||
2333 | { | ||
2334 | SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
2335 | /* | ||
2336 | if (!attachment) | ||
2337 | { | ||
2338 | g.RootPart.AttachPoint = g.RootPart.Shape.State; | ||
2339 | g.RootPart.AttachedPos = g.AbsolutePosition; | ||
2340 | g.RootPart.AttachRotation = g.GroupRotation; | ||
2341 | if (g.RootPart.Shape.PCode != (byte)PCode.NewTree && | ||
2342 | g.RootPart.Shape.PCode != (byte)PCode.Tree) | ||
2343 | g.RootPart.Shape.State = 0; | ||
2344 | } | ||
2345 | */ | ||
2346 | objlist.Add(g); | ||
2347 | veclist.Add(new Vector3(0, 0, 0)); | ||
2348 | bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); | ||
2349 | return true; | ||
2350 | } | ||
2351 | else | ||
2352 | { | ||
2353 | XmlElement coll = (XmlElement)e; | ||
2354 | float bx = Convert.ToSingle(coll.GetAttribute("x")); | ||
2355 | float by = Convert.ToSingle(coll.GetAttribute("y")); | ||
2356 | float bz = Convert.ToSingle(coll.GetAttribute("z")); | ||
2357 | bbox = new Vector3(bx, by, bz); | ||
2358 | offsetHeight = 0; | ||
2359 | |||
2360 | XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); | ||
2361 | foreach (XmlNode n in groups) | ||
2362 | { | ||
2363 | SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); | ||
2364 | /* | ||
2365 | g.RootPart.AttachPoint = g.RootPart.Shape.State; | ||
2366 | g.RootPart.AttachedPos = g.AbsolutePosition; | ||
2367 | g.RootPart.AttachRotation = g.GroupRotation; | ||
2368 | if (g.RootPart.Shape.PCode != (byte)PCode.NewTree && | ||
2369 | g.RootPart.Shape.PCode != (byte)PCode.Tree) | ||
2370 | g.RootPart.Shape.State = 0; | ||
2371 | */ | ||
2372 | objlist.Add(g); | ||
2373 | |||
2374 | XmlElement el = (XmlElement)n; | ||
2375 | string rawX = el.GetAttribute("offsetx"); | ||
2376 | string rawY = el.GetAttribute("offsety"); | ||
2377 | string rawZ = el.GetAttribute("offsetz"); | ||
2378 | |||
2379 | float x = Convert.ToSingle(rawX); | ||
2380 | float y = Convert.ToSingle(rawY); | ||
2381 | float z = Convert.ToSingle(rawZ); | ||
2382 | veclist.Add(new Vector3(x, y, z)); | ||
2383 | } | ||
2384 | } | ||
2385 | |||
2386 | return false; | ||
2387 | } | ||
2388 | |||
2389 | /// <summary> | ||
2280 | /// Event Handler Rez an object into a scene | 2390 | /// Event Handler Rez an object into a scene |
2281 | /// Calls the non-void event handler | 2391 | /// Calls the non-void event handler |
2282 | /// </summary> | 2392 | /// </summary> |
@@ -2351,19 +2461,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
2351 | /// will be used if it exists.</param> | 2461 | /// will be used if it exists.</param> |
2352 | /// <param name="vel">The velocity of the rezzed object.</param> | 2462 | /// <param name="vel">The velocity of the rezzed object.</param> |
2353 | /// <param name="param"></param> | 2463 | /// <param name="param"></param> |
2354 | /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> | 2464 | /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns> |
2355 | public virtual SceneObjectGroup RezObject( | 2465 | public virtual List<SceneObjectGroup> RezObject( |
2356 | SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) | 2466 | SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) |
2357 | { | 2467 | { |
2358 | if (null == item) | 2468 | if (null == item) |
2359 | return null; | 2469 | return null; |
2470 | |||
2471 | List<SceneObjectGroup> objlist; | ||
2472 | List<Vector3> veclist; | ||
2360 | 2473 | ||
2361 | SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); | 2474 | bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); |
2362 | 2475 | if (!success) | |
2363 | if (null == group) | ||
2364 | return null; | 2476 | return null; |
2365 | 2477 | ||
2366 | if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) | 2478 | int totalPrims = 0; |
2479 | foreach (SceneObjectGroup group in objlist) | ||
2480 | totalPrims += group.PrimCount; | ||
2481 | |||
2482 | if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos)) | ||
2367 | return null; | 2483 | return null; |
2368 | 2484 | ||
2369 | if (!Permissions.BypassPermissions()) | 2485 | if (!Permissions.BypassPermissions()) |
@@ -2372,16 +2488,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
2372 | sourcePart.Inventory.RemoveInventoryItem(item.ItemID); | 2488 | sourcePart.Inventory.RemoveInventoryItem(item.ItemID); |
2373 | } | 2489 | } |
2374 | 2490 | ||
2375 | group.FromPartID = sourcePart.UUID; | 2491 | for (int i = 0; i < objlist.Count; i++) |
2376 | AddNewSceneObject(group, true, pos, rot, vel); | 2492 | { |
2377 | 2493 | SceneObjectGroup group = objlist[i]; | |
2378 | // We can only call this after adding the scene object, since the scene object references the scene | 2494 | Vector3 curpos = pos + veclist[i]; |
2379 | // to find out if scripts should be activated at all. | 2495 | |
2380 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); | 2496 | if (group.IsAttachment == false && group.RootPart.Shape.State != 0) |
2381 | 2497 | { | |
2382 | group.ScheduleGroupForFullUpdate(); | 2498 | group.RootPart.AttachedPos = group.AbsolutePosition; |
2383 | 2499 | group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; | |
2384 | return group; | 2500 | } |
2501 | |||
2502 | group.FromPartID = sourcePart.UUID; | ||
2503 | AddNewSceneObject(group, true, curpos, rot, vel); | ||
2504 | |||
2505 | // We can only call this after adding the scene object, since the scene object references the scene | ||
2506 | // to find out if scripts should be activated at all. | ||
2507 | group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); | ||
2508 | |||
2509 | group.ScheduleGroupForFullUpdate(); | ||
2510 | } | ||
2511 | |||
2512 | return objlist; | ||
2385 | } | 2513 | } |
2386 | 2514 | ||
2387 | public virtual bool returnObjects(SceneObjectGroup[] returnobjects, | 2515 | public virtual bool returnObjects(SceneObjectGroup[] returnobjects, |
@@ -2576,12 +2704,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2576 | return; | 2704 | return; |
2577 | } | 2705 | } |
2578 | 2706 | ||
2707 | bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0; | ||
2579 | m_sceneGraph.LinkObjects(root, children); | 2708 | m_sceneGraph.LinkObjects(root, children); |
2580 | 2709 | ||
2581 | ScenePresence sp; | 2710 | ScenePresence sp; |
2582 | if (TryGetScenePresence(agentId, out sp)) | 2711 | if (TryGetScenePresence(agentId, out sp)) |
2583 | { | 2712 | { |
2584 | root.SendPropertiesToClient(sp.ControllingClient); | 2713 | root.SendPropertiesToClient(sp.ControllingClient); |
2714 | if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0) | ||
2715 | { | ||
2716 | sp.ControllingClient.SendAlertMessage("Object physics canceled"); | ||
2717 | } | ||
2585 | } | 2718 | } |
2586 | } | 2719 | } |
2587 | 2720 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ce6415a..931093a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | |||
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
252 | if (part.ParentGroup.RootPart.LocalId != part.LocalId) | 252 | if (part.ParentGroup.RootPart.LocalId != part.LocalId) |
253 | return; | 253 | return; |
254 | 254 | ||
255 | bool isAttachment = false; | ||
256 | |||
257 | // This is wrong, wrong, wrong. Selection should not be | 255 | // This is wrong, wrong, wrong. Selection should not be |
258 | // handled by group, but by prim. Legacy cruft. | 256 | // handled by group, but by prim. Legacy cruft. |
259 | // TODO: Make selection flagging per prim! | 257 | // TODO: Make selection flagging per prim! |
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
262 | || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 260 | || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) |
263 | part.ParentGroup.IsSelected = false; | 261 | part.ParentGroup.IsSelected = false; |
264 | 262 | ||
265 | if (part.ParentGroup.IsAttachment) | 263 | part.ParentGroup.ScheduleGroupForFullUpdate(); |
266 | isAttachment = true; | ||
267 | else | ||
268 | part.ParentGroup.ScheduleGroupForFullUpdate(); | ||
269 | 264 | ||
270 | // If it's not an attachment, and we are allowed to move it, | 265 | // If it's not an attachment, and we are allowed to move it, |
271 | // then we might have done so. If we moved across a parcel | 266 | // then we might have done so. If we moved across a parcel |
272 | // boundary, we will need to recount prims on the parcels. | 267 | // boundary, we will need to recount prims on the parcels. |
273 | // For attachments, that makes no sense. | 268 | // For attachments, that makes no sense. |
274 | // | 269 | // |
275 | if (!isAttachment) | 270 | if (!part.ParentGroup.IsAttachment) |
276 | { | 271 | { |
277 | if (Permissions.CanEditObject( | 272 | if (Permissions.CanEditObject( |
278 | part.UUID, remoteClient.AgentId) | 273 | part.UUID, remoteClient.AgentId) |
@@ -296,6 +291,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
296 | EventManager.TriggerParcelPrimCountTainted(); | 291 | EventManager.TriggerParcelPrimCountTainted(); |
297 | } | 292 | } |
298 | 293 | ||
294 | // restore targetOmega | ||
295 | if (part.AngularVelocity != Vector3.Zero) | ||
296 | part.ScheduleTerseUpdate(); | ||
297 | |||
299 | } | 298 | } |
300 | 299 | ||
301 | public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, | 300 | public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, |
@@ -416,6 +415,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
416 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) | 415 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) |
417 | { | 416 | { |
418 | // TODO: don't create new blocks if recycling an old packet | 417 | // TODO: don't create new blocks if recycling an old packet |
418 | bool discardableEffects = true; | ||
419 | ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; | 419 | ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; |
420 | for (int i = 0; i < args.Count; i++) | 420 | for (int i = 0; i < args.Count; i++) |
421 | { | 421 | { |
@@ -427,17 +427,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
427 | effect.Type = args[i].Type; | 427 | effect.Type = args[i].Type; |
428 | effect.TypeData = args[i].TypeData; | 428 | effect.TypeData = args[i].TypeData; |
429 | effectBlockArray[i] = effect; | 429 | effectBlockArray[i] = effect; |
430 | |||
431 | if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam) | ||
432 | discardableEffects = false; | ||
433 | |||
434 | //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type); | ||
430 | } | 435 | } |
431 | 436 | ||
432 | ForEachClient( | 437 | ForEachScenePresence(sp => |
433 | delegate(IClientAPI client) | ||
434 | { | 438 | { |
435 | if (client.AgentId != remoteClient.AgentId) | 439 | if (sp.ControllingClient.AgentId != remoteClient.AgentId) |
436 | client.SendViewerEffect(effectBlockArray); | 440 | { |
437 | } | 441 | if (!discardableEffects || |
438 | ); | 442 | (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp))) |
443 | { | ||
444 | //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID); | ||
445 | sp.ControllingClient.SendViewerEffect(effectBlockArray); | ||
446 | } | ||
447 | //else | ||
448 | // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID); | ||
449 | } | ||
450 | }); | ||
439 | } | 451 | } |
440 | 452 | ||
453 | private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other) | ||
454 | { | ||
455 | return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; | ||
456 | } | ||
457 | |||
441 | private class DescendentsRequestData | 458 | private class DescendentsRequestData |
442 | { | 459 | { |
443 | public IClientAPI RemoteClient; | 460 | public IClientAPI RemoteClient; |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b189599..eb34f55 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
151 | public SynchronizeSceneHandler SynchronizeScene; | 151 | public SynchronizeSceneHandler SynchronizeScene; |
152 | 152 | ||
153 | /// <summary> | 153 | /// <summary> |
154 | /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. | 154 | /// Used to prevent simultaneous calls to code that adds and removes agents. |
155 | /// </summary> | 155 | /// </summary> |
156 | private object m_removeClientLock = new object(); | 156 | private object m_removeClientLock = new object(); |
157 | 157 | ||
@@ -204,6 +204,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
204 | /// </summary> | 204 | /// </summary> |
205 | public int m_linksetCapacity = 0; | 205 | public int m_linksetCapacity = 0; |
206 | 206 | ||
207 | /// <summary> | ||
208 | /// Max prims an Physical object will hold | ||
209 | /// </summary> | ||
210 | /// | ||
211 | public int m_linksetPhysCapacity = 0; | ||
212 | |||
207 | public bool m_clampPrimSize; | 213 | public bool m_clampPrimSize; |
208 | public bool m_trustBinaries; | 214 | public bool m_trustBinaries; |
209 | public bool m_allowScriptCrossings; | 215 | public bool m_allowScriptCrossings; |
@@ -221,6 +227,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
221 | get { return m_defaultDrawDistance; } | 227 | get { return m_defaultDrawDistance; } |
222 | } | 228 | } |
223 | 229 | ||
230 | // protected float m_maxDrawDistance = 512.0f; | ||
231 | protected float m_maxDrawDistance = 256.0f; | ||
232 | public float MaxDrawDistance | ||
233 | { | ||
234 | get { return m_maxDrawDistance; } | ||
235 | } | ||
236 | |||
224 | private List<string> m_AllowedViewers = new List<string>(); | 237 | private List<string> m_AllowedViewers = new List<string>(); |
225 | private List<string> m_BannedViewers = new List<string>(); | 238 | private List<string> m_BannedViewers = new List<string>(); |
226 | 239 | ||
@@ -230,6 +243,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
230 | public bool m_seeIntoBannedRegion = false; | 243 | public bool m_seeIntoBannedRegion = false; |
231 | public int MaxUndoCount = 5; | 244 | public int MaxUndoCount = 5; |
232 | 245 | ||
246 | public bool SeeIntoRegion { get; set; } | ||
247 | |||
233 | // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; | 248 | // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; |
234 | public bool LoginLock = false; | 249 | public bool LoginLock = false; |
235 | 250 | ||
@@ -396,10 +411,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
396 | if (value) | 411 | if (value) |
397 | { | 412 | { |
398 | if (!m_active) | 413 | if (!m_active) |
399 | Start(); | 414 | Start(false); |
400 | } | 415 | } |
401 | else | 416 | else |
402 | { | 417 | { |
418 | // This appears assymetric with Start() above but is not - setting m_active = false stops the loops | ||
419 | // XXX: Possibly this should be in an explicit Stop() method for symmetry. | ||
403 | m_active = false; | 420 | m_active = false; |
404 | } | 421 | } |
405 | } | 422 | } |
@@ -747,6 +764,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
747 | m_config = config; | 764 | m_config = config; |
748 | MinFrameTime = 0.089f; | 765 | MinFrameTime = 0.089f; |
749 | MinMaintenanceTime = 1; | 766 | MinMaintenanceTime = 1; |
767 | SeeIntoRegion = true; | ||
750 | 768 | ||
751 | Random random = new Random(); | 769 | Random random = new Random(); |
752 | 770 | ||
@@ -851,7 +869,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
851 | 869 | ||
852 | StartDisabled = startupConfig.GetBoolean("StartDisabled", false); | 870 | StartDisabled = startupConfig.GetBoolean("StartDisabled", false); |
853 | 871 | ||
854 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); | 872 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); |
873 | m_defaultDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance); | ||
855 | UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); | 874 | UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); |
856 | if (!UseBackup) | 875 | if (!UseBackup) |
857 | m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); | 876 | m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); |
@@ -859,9 +878,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
859 | //Animation states | 878 | //Animation states |
860 | m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); | 879 | m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); |
861 | 880 | ||
881 | SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion); | ||
882 | |||
883 | MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); | ||
884 | |||
862 | PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); | 885 | PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); |
863 | CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); | 886 | CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); |
864 | |||
865 | m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); | 887 | m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); |
866 | if (RegionInfo.NonphysPrimMin > 0) | 888 | if (RegionInfo.NonphysPrimMin > 0) |
867 | { | 889 | { |
@@ -893,6 +915,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
893 | m_linksetCapacity = RegionInfo.LinksetCapacity; | 915 | m_linksetCapacity = RegionInfo.LinksetCapacity; |
894 | } | 916 | } |
895 | 917 | ||
918 | m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity); | ||
919 | |||
920 | |||
896 | SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); | 921 | SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); |
897 | TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); | 922 | TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); |
898 | 923 | ||
@@ -1052,7 +1077,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1052 | 1077 | ||
1053 | BordersLocked = true; | 1078 | BordersLocked = true; |
1054 | Border northBorder = new Border(); | 1079 | Border northBorder = new Border(); |
1055 | northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- | 1080 | northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeY); //<--- |
1056 | northBorder.CrossDirection = Cardinals.N; | 1081 | northBorder.CrossDirection = Cardinals.N; |
1057 | NorthBorders.Add(northBorder); | 1082 | NorthBorders.Add(northBorder); |
1058 | 1083 | ||
@@ -1062,7 +1087,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1062 | SouthBorders.Add(southBorder); | 1087 | SouthBorders.Add(southBorder); |
1063 | 1088 | ||
1064 | Border eastBorder = new Border(); | 1089 | Border eastBorder = new Border(); |
1065 | eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- | 1090 | eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeX); //<--- |
1066 | eastBorder.CrossDirection = Cardinals.E; | 1091 | eastBorder.CrossDirection = Cardinals.E; |
1067 | EastBorders.Add(eastBorder); | 1092 | EastBorders.Add(eastBorder); |
1068 | 1093 | ||
@@ -1075,6 +1100,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1075 | m_eventManager = new EventManager(); | 1100 | m_eventManager = new EventManager(); |
1076 | 1101 | ||
1077 | m_permissions = new ScenePermissions(this); | 1102 | m_permissions = new ScenePermissions(this); |
1103 | |||
1078 | } | 1104 | } |
1079 | 1105 | ||
1080 | #endregion | 1106 | #endregion |
@@ -1332,7 +1358,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1332 | Thread.Sleep(500); | 1358 | Thread.Sleep(500); |
1333 | 1359 | ||
1334 | // Stop all client threads. | 1360 | // Stop all client threads. |
1335 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); | 1361 | ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); |
1336 | 1362 | ||
1337 | m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); | 1363 | m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); |
1338 | EventManager.TriggerSceneShuttingDown(this); | 1364 | EventManager.TriggerSceneShuttingDown(this); |
@@ -1361,10 +1387,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1361 | } | 1387 | } |
1362 | } | 1388 | } |
1363 | 1389 | ||
1390 | public override void Start() | ||
1391 | { | ||
1392 | Start(true); | ||
1393 | } | ||
1394 | |||
1364 | /// <summary> | 1395 | /// <summary> |
1365 | /// Start the scene | 1396 | /// Start the scene |
1366 | /// </summary> | 1397 | /// </summary> |
1367 | public void Start() | 1398 | /// <param name='startScripts'> |
1399 | /// Start the scripts within the scene. | ||
1400 | /// </param> | ||
1401 | public void Start(bool startScripts) | ||
1368 | { | 1402 | { |
1369 | m_active = true; | 1403 | m_active = true; |
1370 | 1404 | ||
@@ -1401,6 +1435,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1401 | m_heartbeatThread | 1435 | m_heartbeatThread |
1402 | = Watchdog.StartThread( | 1436 | = Watchdog.StartThread( |
1403 | Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); | 1437 | Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); |
1438 | |||
1439 | StartScripts(); | ||
1404 | } | 1440 | } |
1405 | 1441 | ||
1406 | /// <summary> | 1442 | /// <summary> |
@@ -1557,6 +1593,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1557 | 1593 | ||
1558 | try | 1594 | try |
1559 | { | 1595 | { |
1596 | EventManager.TriggerRegionHeartbeatStart(this); | ||
1597 | |||
1560 | // Apply taints in terrain module to terrain in physics scene | 1598 | // Apply taints in terrain module to terrain in physics scene |
1561 | if (Frame % m_update_terrain == 0) | 1599 | if (Frame % m_update_terrain == 0) |
1562 | { | 1600 | { |
@@ -1996,6 +2034,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1996 | 2034 | ||
1997 | GridRegion region = new GridRegion(RegionInfo); | 2035 | GridRegion region = new GridRegion(RegionInfo); |
1998 | string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); | 2036 | string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); |
2037 | m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>", | ||
2038 | LogHeader, m_regionName, | ||
2039 | RegionInfo.RegionID, | ||
2040 | RegionInfo.RegionLocX, RegionInfo.RegionLocY, | ||
2041 | RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); | ||
1999 | if (error != String.Empty) | 2042 | if (error != String.Empty) |
2000 | throw new Exception(error); | 2043 | throw new Exception(error); |
2001 | } | 2044 | } |
@@ -2444,7 +2487,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2444 | foreach (UUID av in avatars) | 2487 | foreach (UUID av in avatars) |
2445 | { | 2488 | { |
2446 | ScenePresence p = GetScenePresence(av); | 2489 | ScenePresence p = GetScenePresence(av); |
2447 | if (p != null) | 2490 | if (p != null && p.ParentUUID == UUID.Zero) |
2448 | p.StandUp(); | 2491 | p.StandUp(); |
2449 | } | 2492 | } |
2450 | 2493 | ||
@@ -2514,6 +2557,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2514 | return false; | 2557 | return false; |
2515 | } | 2558 | } |
2516 | 2559 | ||
2560 | |||
2561 | public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp) | ||
2562 | { | ||
2563 | m_sceneGraph.updateScenePartGroup(part, grp); | ||
2564 | } | ||
2517 | /// <summary> | 2565 | /// <summary> |
2518 | /// Move the given scene object into a new region depending on which region its absolute position has moved | 2566 | /// Move the given scene object into a new region depending on which region its absolute position has moved |
2519 | /// into. | 2567 | /// into. |
@@ -2935,14 +2983,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2935 | 2983 | ||
2936 | #region Add/Remove Avatar Methods | 2984 | #region Add/Remove Avatar Methods |
2937 | 2985 | ||
2938 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2986 | public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) |
2939 | { | 2987 | { |
2940 | ScenePresence sp; | 2988 | ScenePresence sp; |
2941 | bool vialogin; | 2989 | bool vialogin; |
2990 | bool reallyNew = true; | ||
2942 | 2991 | ||
2943 | // Validation occurs in LLUDPServer | 2992 | // Validation occurs in LLUDPServer |
2944 | // | 2993 | // |
2945 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | 2994 | // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with |
2946 | // each other. In practice, this does not currently occur in the code. | 2995 | // each other. In practice, this does not currently occur in the code. |
2947 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2996 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2948 | 2997 | ||
@@ -2950,9 +2999,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2950 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point | 2999 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point |
2951 | // whilst connecting). | 3000 | // whilst connecting). |
2952 | // | 3001 | // |
2953 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and | 3002 | // It would be easier to lock across all NewUserConnection(), AddNewAgent() and |
2954 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | 3003 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service |
2955 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. | 3004 | // response in some module listening to AddNewAgent()) from holding up unrelated agent calls. |
2956 | // | 3005 | // |
2957 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all | 3006 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all |
2958 | // AddNewClient() operations (though not other ops). | 3007 | // AddNewClient() operations (though not other ops). |
@@ -2969,18 +3018,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
2969 | 3018 | ||
2970 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 3019 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this |
2971 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause | 3020 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause |
2972 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 3021 | // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already |
2973 | // connected. | 3022 | // connected. |
2974 | if (sp == null) | 3023 | if (sp == null) |
2975 | { | 3024 | { |
2976 | m_log.DebugFormat( | 3025 | m_log.DebugFormat( |
2977 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", | 3026 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}", |
2978 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | 3027 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos, |
3028 | ((TPFlags)aCircuit.teleportFlags).ToString()); | ||
2979 | 3029 | ||
2980 | m_clientManager.Add(client); | 3030 | m_clientManager.Add(client); |
2981 | SubscribeToClientEvents(client); | 3031 | SubscribeToClientEvents(client); |
2982 | 3032 | ||
2983 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | 3033 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); |
3034 | |||
3035 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
3036 | |||
3037 | /* done in completMovement | ||
2984 | InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46); | 3038 | InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46); |
2985 | if (cof == null) | 3039 | if (cof == null) |
2986 | sp.COF = UUID.Zero; | 3040 | sp.COF = UUID.Zero; |
@@ -2988,25 +3042,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
2988 | sp.COF = cof.ID; | 3042 | sp.COF = cof.ID; |
2989 | 3043 | ||
2990 | m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF); | 3044 | m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF); |
3045 | */ | ||
2991 | m_eventManager.TriggerOnNewPresence(sp); | 3046 | m_eventManager.TriggerOnNewPresence(sp); |
2992 | 3047 | ||
2993 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2994 | } | 3048 | } |
2995 | else | 3049 | else |
2996 | { | 3050 | { |
2997 | m_log.WarnFormat( | 3051 | m_log.WarnFormat( |
2998 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | 3052 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", |
2999 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 3053 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); |
3054 | reallyNew = false; | ||
3000 | } | 3055 | } |
3001 | 3056 | ||
3002 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | 3057 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the |
3003 | // client is for a root or child agent. | 3058 | // client is for a root or child agent. |
3059 | // XXX: This may be better set for a new client before that client is added to the client manager. | ||
3060 | // But need to know what happens in the case where a ScenePresence is already present (and if this | ||
3061 | // actually occurs). | ||
3004 | client.SceneAgent = sp; | 3062 | client.SceneAgent = sp; |
3005 | 3063 | ||
3006 | // Cache the user's name | 3064 | // This is currently also being done earlier in NewUserConnection for real users to see if this |
3065 | // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other | ||
3066 | // places. However, we still need to do it here for NPCs. | ||
3007 | CacheUserName(sp, aCircuit); | 3067 | CacheUserName(sp, aCircuit); |
3008 | 3068 | ||
3009 | EventManager.TriggerOnNewClient(client); | 3069 | if (reallyNew) |
3070 | EventManager.TriggerOnNewClient(client); | ||
3071 | |||
3010 | if (vialogin) | 3072 | if (vialogin) |
3011 | EventManager.TriggerOnClientLogin(client); | 3073 | EventManager.TriggerOnClientLogin(client); |
3012 | } | 3074 | } |
@@ -3027,7 +3089,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3027 | { | 3089 | { |
3028 | string first = aCircuit.firstname, last = aCircuit.lastname; | 3090 | string first = aCircuit.firstname, last = aCircuit.lastname; |
3029 | 3091 | ||
3030 | if (sp.PresenceType == PresenceType.Npc) | 3092 | if (sp != null && sp.PresenceType == PresenceType.Npc) |
3031 | { | 3093 | { |
3032 | UserManagementModule.AddUser(aCircuit.AgentID, first, last); | 3094 | UserManagementModule.AddUser(aCircuit.AgentID, first, last); |
3033 | } | 3095 | } |
@@ -3100,12 +3162,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
3100 | // and the scene presence and the client, if they exist | 3162 | // and the scene presence and the client, if they exist |
3101 | try | 3163 | try |
3102 | { | 3164 | { |
3103 | ScenePresence sp = GetScenePresence(agentID); | 3165 | ScenePresence sp = WaitGetScenePresence(agentID); |
3104 | 3166 | ||
3105 | if (sp != null) | 3167 | if (sp != null) |
3106 | { | 3168 | { |
3107 | PresenceService.LogoutAgent(sp.ControllingClient.SessionId); | 3169 | PresenceService.LogoutAgent(sp.ControllingClient.SessionId); |
3108 | sp.ControllingClient.Close(); | 3170 | |
3171 | CloseAgent(sp.UUID, false); | ||
3109 | } | 3172 | } |
3110 | 3173 | ||
3111 | // BANG! SLASH! | 3174 | // BANG! SLASH! |
@@ -3244,8 +3307,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3244 | { | 3307 | { |
3245 | //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; | 3308 | //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; |
3246 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; | 3309 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; |
3247 | client.OnSetStartLocationRequest += SetHomeRezPoint; | ||
3248 | client.OnRegionHandleRequest += RegionHandleRequest; | ||
3249 | } | 3310 | } |
3250 | 3311 | ||
3251 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) | 3312 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) |
@@ -3371,8 +3432,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3371 | { | 3432 | { |
3372 | //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; | 3433 | //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; |
3373 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; | 3434 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; |
3374 | client.OnSetStartLocationRequest -= SetHomeRezPoint; | ||
3375 | client.OnRegionHandleRequest -= RegionHandleRequest; | ||
3376 | } | 3435 | } |
3377 | 3436 | ||
3378 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) | 3437 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) |
@@ -3498,33 +3557,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3498 | } | 3557 | } |
3499 | 3558 | ||
3500 | /// <summary> | 3559 | /// <summary> |
3501 | /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in | ||
3502 | /// </summary> | ||
3503 | /// <param name="remoteClient"></param> | ||
3504 | /// <param name="regionHandle"></param> | ||
3505 | /// <param name="position"></param> | ||
3506 | /// <param name="lookAt"></param> | ||
3507 | /// <param name="flags"></param> | ||
3508 | public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) | ||
3509 | { | ||
3510 | //Add half the avatar's height so that the user doesn't fall through prims | ||
3511 | ScenePresence presence; | ||
3512 | if (TryGetScenePresence(remoteClient.AgentId, out presence)) | ||
3513 | { | ||
3514 | if (presence.Appearance != null) | ||
3515 | { | ||
3516 | position.Z = position.Z + (presence.Appearance.AvatarHeight / 2); | ||
3517 | } | ||
3518 | } | ||
3519 | |||
3520 | if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) | ||
3521 | // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. | ||
3522 | m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); | ||
3523 | else | ||
3524 | m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed."); | ||
3525 | } | ||
3526 | |||
3527 | /// <summary> | ||
3528 | /// Get the avatar apperance for the given client. | 3560 | /// Get the avatar apperance for the given client. |
3529 | /// </summary> | 3561 | /// </summary> |
3530 | /// <param name="client"></param> | 3562 | /// <param name="client"></param> |
@@ -3548,63 +3580,73 @@ namespace OpenSim.Region.Framework.Scenes | |||
3548 | } | 3580 | } |
3549 | } | 3581 | } |
3550 | 3582 | ||
3551 | public override void RemoveClient(UUID agentID, bool closeChildAgents) | 3583 | /// <summary> |
3584 | /// Remove the given client from the scene. | ||
3585 | /// </summary> | ||
3586 | /// <remarks> | ||
3587 | /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead | ||
3588 | /// to properly operate the state machine and avoid race conditions with other close requests (such as directly | ||
3589 | /// from viewers). | ||
3590 | /// </remarks> | ||
3591 | /// <param name='agentID'>ID of agent to close</param> | ||
3592 | /// <param name='closeChildAgents'> | ||
3593 | /// Close the neighbour child agents associated with this client. | ||
3594 | /// </param> | ||
3595 | /// | ||
3596 | |||
3597 | private object m_removeClientPrivLock = new Object(); | ||
3598 | |||
3599 | public void RemoveClient(UUID agentID, bool closeChildAgents) | ||
3552 | { | 3600 | { |
3553 | // CheckHeartbeat(); | 3601 | AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
3554 | bool isChildAgent = false; | ||
3555 | AgentCircuitData acd; | ||
3556 | 3602 | ||
3557 | lock (m_removeClientLock) | 3603 | // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which |
3604 | // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not | ||
3605 | // However, will keep for now just in case. | ||
3606 | if (acd == null) | ||
3558 | { | 3607 | { |
3559 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); | 3608 | m_log.ErrorFormat( |
3609 | "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name); | ||
3560 | 3610 | ||
3561 | if (acd == null) | 3611 | return; |
3562 | { | ||
3563 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); | ||
3564 | return; | ||
3565 | } | ||
3566 | else | ||
3567 | { | ||
3568 | // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred | ||
3569 | // simultaneously. | ||
3570 | // We also need to remove by agent ID since NPCs will have no circuit code. | ||
3571 | m_authenticateHandler.RemoveCircuit(agentID); | ||
3572 | } | ||
3573 | } | 3612 | } |
3574 | 3613 | else | |
3575 | lock (acd) | ||
3576 | { | 3614 | { |
3615 | m_authenticateHandler.RemoveCircuit(agentID); | ||
3616 | } | ||
3617 | |||
3618 | // TODO: Can we now remove this lock? | ||
3619 | lock (m_removeClientPrivLock) | ||
3620 | { | ||
3621 | bool isChildAgent = false; | ||
3622 | |||
3577 | ScenePresence avatar = GetScenePresence(agentID); | 3623 | ScenePresence avatar = GetScenePresence(agentID); |
3578 | 3624 | ||
3625 | // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which | ||
3626 | // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not | ||
3627 | // However, will keep for now just in case. | ||
3579 | if (avatar == null) | 3628 | if (avatar == null) |
3580 | { | 3629 | { |
3581 | m_log.WarnFormat( | 3630 | m_log.ErrorFormat( |
3582 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | 3631 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); |
3583 | 3632 | ||
3584 | return; | 3633 | return; |
3585 | } | 3634 | } |
3586 | 3635 | ||
3587 | try | 3636 | try |
3588 | { | 3637 | { |
3589 | isChildAgent = avatar.IsChildAgent; | 3638 | isChildAgent = avatar.IsChildAgent; |
3590 | 3639 | ||
3591 | m_log.DebugFormat( | 3640 | m_log.DebugFormat( |
3592 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | 3641 | "[SCENE]: Removing {0} agent {1} {2} from {3}", |
3593 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | 3642 | isChildAgent ? "child" : "root", avatar.Name, agentID, Name); |
3594 | 3643 | ||
3595 | // Don't do this to root agents, it's not nice for the viewer | 3644 | // Don't do this to root agents, it's not nice for the viewer |
3596 | if (closeChildAgents && isChildAgent) | 3645 | if (closeChildAgents && isChildAgent) |
3597 | { | 3646 | { |
3598 | // Tell a single agent to disconnect from the region. | 3647 | // Tell a single agent to disconnect from the region. |
3599 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | 3648 | // Let's do this via UDP |
3600 | if (eq != null) | 3649 | avatar.ControllingClient.SendShutdownConnectionNotice(); |
3601 | { | ||
3602 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3603 | } | ||
3604 | else | ||
3605 | { | ||
3606 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3607 | } | ||
3608 | } | 3650 | } |
3609 | 3651 | ||
3610 | // Only applies to root agents. | 3652 | // Only applies to root agents. |
@@ -3620,40 +3662,44 @@ namespace OpenSim.Region.Framework.Scenes | |||
3620 | if (closeChildAgents && CapsModule != null) | 3662 | if (closeChildAgents && CapsModule != null) |
3621 | CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); | 3663 | CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); |
3622 | 3664 | ||
3623 | // // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3624 | // // this method is doing is HORRIBLE!!! | ||
3625 | // Commented pending deletion since this method no longer appears to do anything at all | ||
3626 | // avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3627 | |||
3628 | if (closeChildAgents && !isChildAgent) | 3665 | if (closeChildAgents && !isChildAgent) |
3629 | { | 3666 | { |
3630 | List<ulong> regions = avatar.KnownRegionHandles; | 3667 | List<ulong> regions = avatar.KnownRegionHandles; |
3631 | regions.Remove(RegionInfo.RegionHandle); | 3668 | regions.Remove(RegionInfo.RegionHandle); |
3632 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | 3669 | |
3670 | // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours. | ||
3671 | m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions); | ||
3633 | } | 3672 | } |
3634 | 3673 | ||
3635 | m_eventManager.TriggerClientClosed(agentID, this); | 3674 | m_eventManager.TriggerClientClosed(agentID, this); |
3675 | // m_log.Debug("[Scene]TriggerClientClosed done"); | ||
3636 | m_eventManager.TriggerOnRemovePresence(agentID); | 3676 | m_eventManager.TriggerOnRemovePresence(agentID); |
3677 | // m_log.Debug("[Scene]TriggerOnRemovePresence done"); | ||
3637 | 3678 | ||
3638 | if (!isChildAgent) | 3679 | if (!isChildAgent) |
3639 | { | 3680 | { |
3640 | if (AttachmentsModule != null) | 3681 | if (AttachmentsModule != null) |
3641 | { | 3682 | { |
3683 | // m_log.Debug("[Scene]DeRezAttachments"); | ||
3642 | AttachmentsModule.DeRezAttachments(avatar); | 3684 | AttachmentsModule.DeRezAttachments(avatar); |
3685 | // m_log.Debug("[Scene]DeRezAttachments done"); | ||
3643 | } | 3686 | } |
3644 | 3687 | ||
3645 | ForEachClient( | 3688 | ForEachClient( |
3646 | delegate(IClientAPI client) | 3689 | delegate(IClientAPI client) |
3647 | { | 3690 | { |
3648 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3691 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway |
3649 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3692 | try { client.SendKillObject(new List<uint> { avatar.LocalId }); } |
3650 | catch (NullReferenceException) { } | 3693 | catch (NullReferenceException) { } |
3651 | }); | 3694 | }); |
3652 | } | 3695 | } |
3653 | 3696 | ||
3654 | // It's possible for child agents to have transactions if changes are being made cross-border. | 3697 | // It's possible for child agents to have transactions if changes are being made cross-border. |
3655 | if (AgentTransactionsModule != null) | 3698 | if (AgentTransactionsModule != null) |
3699 | { | ||
3700 | // m_log.Debug("[Scene]RemoveAgentAssetTransactions"); | ||
3656 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | 3701 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); |
3702 | } | ||
3657 | m_log.Debug("[Scene] The avatar has left the building"); | 3703 | m_log.Debug("[Scene] The avatar has left the building"); |
3658 | } | 3704 | } |
3659 | catch (Exception e) | 3705 | catch (Exception e) |
@@ -3727,7 +3773,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3727 | } | 3773 | } |
3728 | deleteIDs.Add(localID); | 3774 | deleteIDs.Add(localID); |
3729 | } | 3775 | } |
3730 | ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); | 3776 | |
3777 | ForEachClient(c => c.SendKillObject(deleteIDs)); | ||
3731 | } | 3778 | } |
3732 | 3779 | ||
3733 | #endregion | 3780 | #endregion |
@@ -3763,13 +3810,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
3763 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of | 3810 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of |
3764 | /// the LLUDP stack). | 3811 | /// the LLUDP stack). |
3765 | /// </remarks> | 3812 | /// </remarks> |
3766 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3813 | /// <param name="acd">CircuitData of the agent who is connecting</param> |
3767 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3814 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3768 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC | 3815 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC |
3769 | /// or other applications where a full grid/Hypergrid presence may not be required.</param> | 3816 | /// or other applications where a full grid/Hypergrid presence may not be required.</param> |
3770 | /// <returns>True if the region accepts this agent. False if it does not. False will | 3817 | /// <returns>True if the region accepts this agent. False if it does not. False will |
3771 | /// also return a reason.</returns> | 3818 | /// also return a reason.</returns> |
3772 | public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) | 3819 | /// |
3820 | private object m_newUserConnLock = new object(); | ||
3821 | |||
3822 | public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup) | ||
3773 | { | 3823 | { |
3774 | bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || | 3824 | bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || |
3775 | (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); | 3825 | (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); |
@@ -3789,17 +3839,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
3789 | m_log.DebugFormat( | 3839 | m_log.DebugFormat( |
3790 | "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", | 3840 | "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", |
3791 | RegionInfo.RegionName, | 3841 | RegionInfo.RegionName, |
3792 | (agent.child ? "child" : "root"), | 3842 | (acd.child ? "child" : "root"), |
3793 | agent.firstname, | 3843 | acd.firstname, |
3794 | agent.lastname, | 3844 | acd.lastname, |
3795 | agent.AgentID, | 3845 | acd.AgentID, |
3796 | agent.circuitcode, | 3846 | acd.circuitcode, |
3797 | agent.IPAddress, | 3847 | acd.IPAddress, |
3798 | agent.Viewer, | 3848 | acd.Viewer, |
3799 | ((TPFlags)teleportFlags).ToString(), | 3849 | ((TPFlags)teleportFlags).ToString(), |
3800 | agent.startpos | 3850 | acd.startpos |
3801 | ); | 3851 | ); |
3802 | 3852 | ||
3853 | // m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace); | ||
3854 | |||
3803 | if (!LoginsEnabled) | 3855 | if (!LoginsEnabled) |
3804 | { | 3856 | { |
3805 | reason = "Logins Disabled"; | 3857 | reason = "Logins Disabled"; |
@@ -3815,7 +3867,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3815 | { | 3867 | { |
3816 | foreach (string viewer in m_AllowedViewers) | 3868 | foreach (string viewer in m_AllowedViewers) |
3817 | { | 3869 | { |
3818 | if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) | 3870 | if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower()) |
3819 | { | 3871 | { |
3820 | ViewerDenied = false; | 3872 | ViewerDenied = false; |
3821 | break; | 3873 | break; |
@@ -3832,7 +3884,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3832 | { | 3884 | { |
3833 | foreach (string viewer in m_BannedViewers) | 3885 | foreach (string viewer in m_BannedViewers) |
3834 | { | 3886 | { |
3835 | if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) | 3887 | if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower()) |
3836 | { | 3888 | { |
3837 | ViewerDenied = true; | 3889 | ViewerDenied = true; |
3838 | break; | 3890 | break; |
@@ -3844,54 +3896,135 @@ namespace OpenSim.Region.Framework.Scenes | |||
3844 | { | 3896 | { |
3845 | m_log.DebugFormat( | 3897 | m_log.DebugFormat( |
3846 | "[SCENE]: Access denied for {0} {1} using {2}", | 3898 | "[SCENE]: Access denied for {0} {1} using {2}", |
3847 | agent.firstname, agent.lastname, agent.Viewer); | 3899 | acd.firstname, acd.lastname, acd.Viewer); |
3848 | reason = "Access denied, your viewer is banned by the region owner"; | 3900 | reason = "Access denied, your viewer is banned by the region owner"; |
3849 | return false; | 3901 | return false; |
3850 | } | 3902 | } |
3851 | 3903 | ||
3852 | ScenePresence sp = GetScenePresence(agent.AgentID); | 3904 | ILandObject land; |
3905 | ScenePresence sp; | ||
3853 | 3906 | ||
3854 | // If we have noo presence here or if that presence is a zombie root | 3907 | lock (m_removeClientLock) |
3855 | // presence that will be kicled, we need a new CAPS object. | ||
3856 | if (sp == null || (sp != null && !sp.IsChildAgent)) | ||
3857 | { | 3908 | { |
3858 | if (CapsModule != null) | 3909 | sp = GetScenePresence(acd.AgentID); |
3910 | |||
3911 | // We need to ensure that we are not already removing the scene presence before we ask it not to be | ||
3912 | // closed. | ||
3913 | if (sp != null && sp.IsChildAgent | ||
3914 | && (sp.LifecycleState == ScenePresenceState.Running | ||
3915 | || sp.LifecycleState == ScenePresenceState.PreRemove)) | ||
3859 | { | 3916 | { |
3860 | lock (agent) | 3917 | m_log.DebugFormat( |
3918 | "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}", | ||
3919 | sp.Name, sp.LifecycleState, Name); | ||
3920 | |||
3921 | // In the case where, for example, an A B C D region layout, an avatar may | ||
3922 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C | ||
3923 | // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. | ||
3924 | // | ||
3925 | // XXX: In the end, this should not be necessary if child agents are closed without delay on | ||
3926 | // teleport, since realistically, the close request should always be processed before any other | ||
3927 | // region tried to re-establish a child agent. This is much simpler since the logic below is | ||
3928 | // vulnerable to an issue when a viewer quits a region without sending a proper logout but then | ||
3929 | // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport | ||
3930 | // flag when no teleport had taken place (and hence no close was going to come). | ||
3931 | // if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) | ||
3932 | // { | ||
3933 | // m_log.DebugFormat( | ||
3934 | // "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", | ||
3935 | // sp.Name, Name); | ||
3936 | // | ||
3937 | // sp.DoNotCloseAfterTeleport = true; | ||
3938 | // } | ||
3939 | // else if (EntityTransferModule.IsInTransit(sp.UUID)) | ||
3940 | |||
3941 | sp.LifecycleState = ScenePresenceState.Running; | ||
3942 | |||
3943 | if (EntityTransferModule.IsInTransit(sp.UUID)) | ||
3861 | { | 3944 | { |
3862 | CapsModule.SetAgentCapsSeeds(agent); | 3945 | sp.DoNotCloseAfterTeleport = true; |
3863 | CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); | 3946 | |
3947 | m_log.DebugFormat( | ||
3948 | "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", | ||
3949 | sp.Name, Name); | ||
3864 | } | 3950 | } |
3865 | } | 3951 | } |
3866 | } | 3952 | } |
3867 | 3953 | ||
3954 | // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will | ||
3955 | // allow unpredictable things to happen. | ||
3868 | if (sp != null) | 3956 | if (sp != null) |
3869 | { | 3957 | { |
3870 | if (!sp.IsChildAgent) | 3958 | const int polls = 10; |
3959 | const int pollInterval = 1000; | ||
3960 | int pollsLeft = polls; | ||
3961 | |||
3962 | while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0) | ||
3963 | Thread.Sleep(pollInterval); | ||
3964 | |||
3965 | if (sp.LifecycleState == ScenePresenceState.Removing) | ||
3871 | { | 3966 | { |
3872 | // We have a zombie from a crashed session. | ||
3873 | // Or the same user is trying to be root twice here, won't work. | ||
3874 | // Kill it. | ||
3875 | m_log.WarnFormat( | 3967 | m_log.WarnFormat( |
3876 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | 3968 | "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", |
3877 | sp.Name, sp.UUID, RegionInfo.RegionName); | 3969 | sp.Name, Name, polls * pollInterval / 1000); |
3878 | 3970 | ||
3879 | sp.ControllingClient.Close(true, true); | 3971 | return false; |
3880 | sp = null; | 3972 | } |
3973 | else if (polls != pollsLeft) | ||
3974 | { | ||
3975 | m_log.DebugFormat( | ||
3976 | "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.", | ||
3977 | sp.Name, Name, polls * pollInterval / 1000); | ||
3881 | } | 3978 | } |
3882 | } | 3979 | } |
3883 | 3980 | ||
3884 | lock (agent) | 3981 | // TODO: can we remove this lock? |
3982 | lock (m_newUserConnLock) | ||
3885 | { | 3983 | { |
3886 | //On login test land permisions | 3984 | if (sp != null && !sp.IsChildAgent) |
3985 | { | ||
3986 | // We have a root agent. Is it in transit? | ||
3987 | if (!EntityTransferModule.IsInTransit(sp.UUID)) | ||
3988 | { | ||
3989 | // We have a zombie from a crashed session. | ||
3990 | // Or the same user is trying to be root twice here, won't work. | ||
3991 | // Kill it. | ||
3992 | m_log.WarnFormat( | ||
3993 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | ||
3994 | sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3995 | |||
3996 | if (sp.ControllingClient != null) | ||
3997 | CloseAgent(sp.UUID, true); | ||
3998 | |||
3999 | sp = null; | ||
4000 | } | ||
4001 | //else | ||
4002 | // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName); | ||
4003 | } | ||
4004 | |||
4005 | // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. | ||
4006 | // We need the circuit data here for some of the subsequent checks. (groups, for example) | ||
4007 | // If the checks fail, we remove the circuit. | ||
4008 | acd.teleportFlags = teleportFlags; | ||
4009 | |||
4010 | // Remove any preexisting circuit - we don't want duplicates | ||
4011 | // This is a stab at preventing avatar "ghosting" | ||
4012 | if (vialogin) | ||
4013 | m_authenticateHandler.RemoveCircuit(acd.AgentID); | ||
4014 | |||
4015 | m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); | ||
4016 | |||
4017 | land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); | ||
4018 | |||
4019 | // On login test land permisions | ||
3887 | if (vialogin) | 4020 | if (vialogin) |
3888 | { | 4021 | { |
3889 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); | 4022 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); |
3890 | if (cache != null) | 4023 | if (cache != null) |
3891 | cache.Remove(agent.firstname + " " + agent.lastname); | 4024 | cache.Remove(acd.firstname + " " + acd.lastname); |
3892 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | 4025 | if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) |
3893 | { | 4026 | { |
3894 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | 4027 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); |
3895 | return false; | 4028 | return false; |
3896 | } | 4029 | } |
3897 | } | 4030 | } |
@@ -3902,84 +4035,97 @@ namespace OpenSim.Region.Framework.Scenes | |||
3902 | { | 4035 | { |
3903 | try | 4036 | try |
3904 | { | 4037 | { |
3905 | if (!VerifyUserPresence(agent, out reason)) | 4038 | if (!VerifyUserPresence(acd, out reason)) |
4039 | { | ||
4040 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3906 | return false; | 4041 | return false; |
3907 | } catch (Exception e) | 4042 | } |
4043 | } | ||
4044 | catch (Exception e) | ||
3908 | { | 4045 | { |
3909 | m_log.ErrorFormat( | 4046 | m_log.ErrorFormat( |
3910 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | 4047 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); |
4048 | |||
4049 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3911 | return false; | 4050 | return false; |
3912 | } | 4051 | } |
3913 | } | 4052 | } |
3914 | 4053 | ||
3915 | try | 4054 | try |
3916 | { | 4055 | { |
3917 | // Always check estate if this is a login. Always | 4056 | if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason)) |
3918 | // check if banned regions are to be blacked out. | ||
3919 | if (vialogin || (!m_seeIntoBannedRegion)) | ||
3920 | { | 4057 | { |
3921 | if (!AuthorizeUser(agent, out reason)) | 4058 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); |
3922 | { | 4059 | return false; |
3923 | return false; | ||
3924 | } | ||
3925 | } | 4060 | } |
3926 | } | 4061 | } |
3927 | catch (Exception e) | 4062 | catch (Exception e) |
3928 | { | 4063 | { |
3929 | m_log.ErrorFormat( | 4064 | m_log.ErrorFormat( |
3930 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | 4065 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); |
4066 | |||
4067 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3931 | return false; | 4068 | return false; |
3932 | } | 4069 | } |
3933 | 4070 | ||
3934 | m_log.InfoFormat( | 4071 | m_log.InfoFormat( |
3935 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | 4072 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", |
3936 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | 4073 | Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname, |
3937 | agent.AgentID, agent.circuitcode); | 4074 | acd.AgentID, acd.circuitcode); |
3938 | 4075 | ||
4076 | if (CapsModule != null) | ||
4077 | { | ||
4078 | CapsModule.SetAgentCapsSeeds(acd); | ||
4079 | CapsModule.CreateCaps(acd.AgentID, acd.circuitcode); | ||
4080 | } | ||
3939 | } | 4081 | } |
3940 | else | 4082 | else |
3941 | { | 4083 | { |
3942 | // Let the SP know how we got here. This has a lot of interesting | 4084 | // Let the SP know how we got here. This has a lot of interesting |
3943 | // uses down the line. | 4085 | // uses down the line. |
3944 | sp.TeleportFlags = (TPFlags)teleportFlags; | 4086 | sp.TeleportFlags = (TPFlags)teleportFlags; |
3945 | 4087 | ||
3946 | if (sp.IsChildAgent) | 4088 | if (sp.IsChildAgent) |
3947 | { | 4089 | { |
3948 | m_log.DebugFormat( | 4090 | m_log.DebugFormat( |
3949 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | 4091 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", |
3950 | agent.AgentID, RegionInfo.RegionName); | 4092 | acd.AgentID, RegionInfo.RegionName); |
3951 | |||
3952 | sp.AdjustKnownSeeds(); | ||
3953 | 4093 | ||
3954 | if (CapsModule != null) | 4094 | if (CapsModule != null) |
3955 | CapsModule.SetAgentCapsSeeds(agent); | 4095 | { |
4096 | CapsModule.SetAgentCapsSeeds(acd); | ||
4097 | CapsModule.CreateCaps(acd.AgentID, acd.circuitcode); | ||
4098 | } | ||
4099 | |||
4100 | sp.AdjustKnownSeeds(); | ||
3956 | } | 4101 | } |
3957 | } | 4102 | } |
3958 | } | ||
3959 | 4103 | ||
3960 | // In all cases, add or update the circuit data with the new agent circuit data and teleport flags | 4104 | // Try caching an incoming user name much earlier on to see if this helps with an issue |
3961 | agent.teleportFlags = teleportFlags; | 4105 | // where HG users are occasionally seen by others as "Unknown User" because their UUIDName |
3962 | m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); | 4106 | // request for the HG avatar appears to trigger before the user name is cached. |
4107 | CacheUserName(null, acd); | ||
4108 | } | ||
3963 | 4109 | ||
3964 | if (CapsModule != null) | 4110 | if (CapsModule != null) |
3965 | { | 4111 | { |
3966 | CapsModule.ActivateCaps(agent.circuitcode); | 4112 | CapsModule.ActivateCaps(acd.circuitcode); |
3967 | } | 4113 | } |
3968 | 4114 | ||
3969 | if (vialogin) | 4115 | if (vialogin) |
3970 | { | 4116 | { |
3971 | // CleanDroppedAttachments(); | 4117 | // CleanDroppedAttachments(); |
3972 | 4118 | ||
3973 | if (TestBorderCross(agent.startpos, Cardinals.E)) | 4119 | if (TestBorderCross(acd.startpos, Cardinals.E)) |
3974 | { | 4120 | { |
3975 | Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); | 4121 | Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); |
3976 | agent.startpos.X = crossedBorder.BorderLine.Z - 1; | 4122 | acd.startpos.X = crossedBorder.BorderLine.Z - 1; |
3977 | } | 4123 | } |
3978 | 4124 | ||
3979 | if (TestBorderCross(agent.startpos, Cardinals.N)) | 4125 | if (TestBorderCross(acd.startpos, Cardinals.N)) |
3980 | { | 4126 | { |
3981 | Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); | 4127 | Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N); |
3982 | agent.startpos.Y = crossedBorder.BorderLine.Z - 1; | 4128 | acd.startpos.Y = crossedBorder.BorderLine.Z - 1; |
3983 | } | 4129 | } |
3984 | 4130 | ||
3985 | //Mitigate http://opensimulator.org/mantis/view.php?id=3522 | 4131 | //Mitigate http://opensimulator.org/mantis/view.php?id=3522 |
@@ -3989,68 +4135,88 @@ namespace OpenSim.Region.Framework.Scenes | |||
3989 | { | 4135 | { |
3990 | lock (EastBorders) | 4136 | lock (EastBorders) |
3991 | { | 4137 | { |
3992 | if (agent.startpos.X > EastBorders[0].BorderLine.Z) | 4138 | if (acd.startpos.X > EastBorders[0].BorderLine.Z) |
3993 | { | 4139 | { |
3994 | m_log.Warn("FIX AGENT POSITION"); | 4140 | m_log.Warn("FIX AGENT POSITION"); |
3995 | agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; | 4141 | acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; |
3996 | if (agent.startpos.Z > 720) | 4142 | if (acd.startpos.Z > 720) |
3997 | agent.startpos.Z = 720; | 4143 | acd.startpos.Z = 720; |
3998 | } | 4144 | } |
3999 | } | 4145 | } |
4000 | lock (NorthBorders) | 4146 | lock (NorthBorders) |
4001 | { | 4147 | { |
4002 | if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) | 4148 | if (acd.startpos.Y > NorthBorders[0].BorderLine.Z) |
4003 | { | 4149 | { |
4004 | m_log.Warn("FIX Agent POSITION"); | 4150 | m_log.Warn("FIX Agent POSITION"); |
4005 | agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; | 4151 | acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; |
4006 | if (agent.startpos.Z > 720) | 4152 | if (acd.startpos.Z > 720) |
4007 | agent.startpos.Z = 720; | 4153 | acd.startpos.Z = 720; |
4008 | } | 4154 | } |
4009 | } | 4155 | } |
4010 | } else | 4156 | } else |
4011 | { | 4157 | { |
4012 | if (agent.startpos.X > EastBorders[0].BorderLine.Z) | 4158 | if (acd.startpos.X > EastBorders[0].BorderLine.Z) |
4013 | { | 4159 | { |
4014 | m_log.Warn("FIX AGENT POSITION"); | 4160 | m_log.Warn("FIX AGENT POSITION"); |
4015 | agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; | 4161 | acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; |
4016 | if (agent.startpos.Z > 720) | 4162 | if (acd.startpos.Z > 720) |
4017 | agent.startpos.Z = 720; | 4163 | acd.startpos.Z = 720; |
4018 | } | 4164 | } |
4019 | if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) | 4165 | if (acd.startpos.Y > NorthBorders[0].BorderLine.Z) |
4020 | { | 4166 | { |
4021 | m_log.Warn("FIX Agent POSITION"); | 4167 | m_log.Warn("FIX Agent POSITION"); |
4022 | agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; | 4168 | acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; |
4023 | if (agent.startpos.Z > 720) | 4169 | if (acd.startpos.Z > 720) |
4024 | agent.startpos.Z = 720; | 4170 | acd.startpos.Z = 720; |
4025 | } | 4171 | } |
4026 | } | 4172 | } |
4027 | 4173 | ||
4174 | // m_log.DebugFormat( | ||
4175 | // "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", | ||
4176 | // RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); | ||
4177 | |||
4028 | // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags | 4178 | // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags |
4029 | if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && | 4179 | if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && |
4030 | RegionInfo.EstateSettings.AllowDirectTeleport == false && | 4180 | RegionInfo.EstateSettings.AllowDirectTeleport == false && |
4031 | !viahome && !godlike) | 4181 | !viahome && !godlike) |
4032 | { | 4182 | { |
4033 | SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); | 4183 | SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); |
4034 | // Can have multiple SpawnPoints | 4184 | |
4035 | List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); | 4185 | if (telehub != null) |
4036 | if (spawnpoints.Count > 1) | ||
4037 | { | 4186 | { |
4038 | // We have multiple SpawnPoints, Route the agent to a random or sequential one | 4187 | // Can have multiple SpawnPoints |
4039 | if (SpawnPointRouting == "random") | 4188 | List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); |
4040 | agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( | 4189 | if (spawnpoints.Count > 1) |
4041 | telehub.AbsolutePosition, | 4190 | { |
4042 | telehub.GroupRotation | 4191 | // We have multiple SpawnPoints, Route the agent to a random or sequential one |
4043 | ); | 4192 | if (SpawnPointRouting == "random") |
4193 | acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( | ||
4194 | telehub.AbsolutePosition, | ||
4195 | telehub.GroupRotation | ||
4196 | ); | ||
4197 | else | ||
4198 | acd.startpos = spawnpoints[SpawnPoint()].GetLocation( | ||
4199 | telehub.AbsolutePosition, | ||
4200 | telehub.GroupRotation | ||
4201 | ); | ||
4202 | } | ||
4203 | else if (spawnpoints.Count == 1) | ||
4204 | { | ||
4205 | // We have a single SpawnPoint and will route the agent to it | ||
4206 | acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); | ||
4207 | } | ||
4044 | else | 4208 | else |
4045 | agent.startpos = spawnpoints[SpawnPoint()].GetLocation( | 4209 | { |
4046 | telehub.AbsolutePosition, | 4210 | m_log.DebugFormat( |
4047 | telehub.GroupRotation | 4211 | "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", |
4048 | ); | 4212 | RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); |
4213 | } | ||
4049 | } | 4214 | } |
4050 | else | 4215 | else |
4051 | { | 4216 | { |
4052 | // We have a single SpawnPoint and will route the agent to it | 4217 | m_log.DebugFormat( |
4053 | agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); | 4218 | "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", |
4219 | RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); | ||
4054 | } | 4220 | } |
4055 | 4221 | ||
4056 | return true; | 4222 | return true; |
@@ -4063,7 +4229,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4063 | { | 4229 | { |
4064 | if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) | 4230 | if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) |
4065 | { | 4231 | { |
4066 | agent.startpos = land.LandData.UserLocation; | 4232 | acd.startpos = land.LandData.UserLocation; |
4067 | } | 4233 | } |
4068 | } | 4234 | } |
4069 | */// This is now handled properly in ScenePresence.MakeRootAgent | 4235 | */// This is now handled properly in ScenePresence.MakeRootAgent |
@@ -4158,7 +4324,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4158 | /// <param name="reason">outputs the reason to this string</param> | 4324 | /// <param name="reason">outputs the reason to this string</param> |
4159 | /// <returns>True if the region accepts this agent. False if it does not. False will | 4325 | /// <returns>True if the region accepts this agent. False if it does not. False will |
4160 | /// also return a reason.</returns> | 4326 | /// also return a reason.</returns> |
4161 | protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) | 4327 | protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) |
4162 | { | 4328 | { |
4163 | reason = String.Empty; | 4329 | reason = String.Empty; |
4164 | 4330 | ||
@@ -4177,67 +4343,75 @@ namespace OpenSim.Region.Framework.Scenes | |||
4177 | } | 4343 | } |
4178 | } | 4344 | } |
4179 | 4345 | ||
4180 | if (RegionInfo.EstateSettings != null) | 4346 | // We only test the things below when we want to cut off |
4347 | // child agents from being present in the scene for which their root | ||
4348 | // agent isn't allowed. Otherwise, we allow child agents. The test for | ||
4349 | // the root is done elsewhere (QueryAccess) | ||
4350 | if (!bypassAccessControl) | ||
4181 | { | 4351 | { |
4182 | if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) | 4352 | if (RegionInfo.EstateSettings != null) |
4183 | { | 4353 | { |
4184 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", | 4354 | int flags = GetUserFlags(agent.AgentID); |
4185 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); | 4355 | if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags)) |
4186 | reason = String.Format("Denied access to region {0}: You have been banned from that region.", | 4356 | { |
4187 | RegionInfo.RegionName); | 4357 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", |
4188 | return false; | 4358 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); |
4359 | reason = String.Format("Denied access to region {0}: You have been banned from that region.", | ||
4360 | RegionInfo.RegionName); | ||
4361 | return false; | ||
4362 | } | ||
4189 | } | 4363 | } |
4190 | } | 4364 | else |
4191 | else | ||
4192 | { | ||
4193 | m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); | ||
4194 | } | ||
4195 | |||
4196 | List<UUID> agentGroups = new List<UUID>(); | ||
4197 | |||
4198 | if (m_groupsModule != null) | ||
4199 | { | ||
4200 | GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); | ||
4201 | |||
4202 | if (GroupMembership != null) | ||
4203 | { | 4365 | { |
4204 | for (int i = 0; i < GroupMembership.Length; i++) | 4366 | m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); |
4205 | agentGroups.Add(GroupMembership[i].GroupID); | ||
4206 | } | 4367 | } |
4207 | else | 4368 | |
4369 | List<UUID> agentGroups = new List<UUID>(); | ||
4370 | |||
4371 | if (m_groupsModule != null) | ||
4208 | { | 4372 | { |
4209 | m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); | 4373 | GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); |
4374 | |||
4375 | if (GroupMembership != null) | ||
4376 | { | ||
4377 | for (int i = 0; i < GroupMembership.Length; i++) | ||
4378 | agentGroups.Add(GroupMembership[i].GroupID); | ||
4379 | } | ||
4380 | else | ||
4381 | { | ||
4382 | m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); | ||
4383 | } | ||
4210 | } | 4384 | } |
4211 | } | ||
4212 | 4385 | ||
4213 | bool groupAccess = false; | 4386 | bool groupAccess = false; |
4214 | UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; | 4387 | UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; |
4215 | 4388 | ||
4216 | if (estateGroups != null) | 4389 | if (estateGroups != null) |
4217 | { | ||
4218 | foreach (UUID group in estateGroups) | ||
4219 | { | 4390 | { |
4220 | if (agentGroups.Contains(group)) | 4391 | foreach (UUID group in estateGroups) |
4221 | { | 4392 | { |
4222 | groupAccess = true; | 4393 | if (agentGroups.Contains(group)) |
4223 | break; | 4394 | { |
4395 | groupAccess = true; | ||
4396 | break; | ||
4397 | } | ||
4224 | } | 4398 | } |
4225 | } | 4399 | } |
4226 | } | 4400 | else |
4227 | else | 4401 | { |
4228 | { | 4402 | m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); |
4229 | m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); | 4403 | } |
4230 | } | ||
4231 | 4404 | ||
4232 | if (!RegionInfo.EstateSettings.PublicAccess && | 4405 | if (!RegionInfo.EstateSettings.PublicAccess && |
4233 | !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && | 4406 | !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && |
4234 | !groupAccess) | 4407 | !groupAccess) |
4235 | { | 4408 | { |
4236 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", | 4409 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", |
4237 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); | 4410 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); |
4238 | reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", | 4411 | reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", |
4239 | RegionInfo.RegionName); | 4412 | RegionInfo.RegionName); |
4240 | return false; | 4413 | return false; |
4414 | } | ||
4241 | } | 4415 | } |
4242 | 4416 | ||
4243 | // TODO: estate/region settings are not properly hooked up | 4417 | // TODO: estate/region settings are not properly hooked up |
@@ -4362,13 +4536,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
4362 | /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. | 4536 | /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. |
4363 | /// Appearance, animations, position, etc.</param> | 4537 | /// Appearance, animations, position, etc.</param> |
4364 | /// <returns>true if we handled it.</returns> | 4538 | /// <returns>true if we handled it.</returns> |
4365 | public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) | 4539 | public virtual bool IncomingUpdateChildAgent(AgentData cAgentData) |
4366 | { | 4540 | { |
4367 | m_log.DebugFormat( | 4541 | m_log.DebugFormat( |
4368 | "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); | 4542 | "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); |
4369 | 4543 | ||
4370 | // XPTO: if this agent is not allowed here as root, always return false | 4544 | if (!LoginsEnabled) |
4371 | 4545 | { | |
4546 | // reason = "Logins Disabled"; | ||
4547 | m_log.DebugFormat( | ||
4548 | "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName); | ||
4549 | return false; | ||
4550 | } | ||
4372 | // We have to wait until the viewer contacts this region after receiving EAC. | 4551 | // We have to wait until the viewer contacts this region after receiving EAC. |
4373 | // That calls AddNewClient, which finally creates the ScenePresence | 4552 | // That calls AddNewClient, which finally creates the ScenePresence |
4374 | int flags = GetUserFlags(cAgentData.AgentID); | 4553 | int flags = GetUserFlags(cAgentData.AgentID); |
@@ -4382,7 +4561,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4382 | ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); | 4561 | ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); |
4383 | if (nearestParcel == null) | 4562 | if (nearestParcel == null) |
4384 | { | 4563 | { |
4385 | m_log.DebugFormat( | 4564 | m_log.InfoFormat( |
4386 | "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", | 4565 | "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", |
4387 | cAgentData.AgentID, RegionInfo.RegionName); | 4566 | cAgentData.AgentID, RegionInfo.RegionName); |
4388 | 4567 | ||
@@ -4390,13 +4569,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
4390 | } | 4569 | } |
4391 | 4570 | ||
4392 | // We have to wait until the viewer contacts this region | 4571 | // We have to wait until the viewer contacts this region |
4393 | // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send | 4572 | // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) |
4394 | // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. | 4573 | // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send |
4395 | ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); | 4574 | // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. |
4575 | ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); | ||
4396 | 4576 | ||
4397 | if (childAgentUpdate != null) | 4577 | if (sp != null) |
4398 | { | 4578 | { |
4399 | childAgentUpdate.ChildAgentDataUpdate(cAgentData); | 4579 | if (!sp.IsChildAgent) |
4580 | { | ||
4581 | m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}", | ||
4582 | sp.Name, sp.UUID, Name); | ||
4583 | return false; | ||
4584 | } | ||
4585 | if (cAgentData.SessionID != sp.ControllingClient.SessionId) | ||
4586 | { | ||
4587 | m_log.WarnFormat( | ||
4588 | "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", | ||
4589 | sp.UUID, cAgentData.SessionID); | ||
4590 | |||
4591 | Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", | ||
4592 | sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); | ||
4593 | } | ||
4594 | |||
4595 | sp.UpdateChildAgent(cAgentData); | ||
4596 | |||
4597 | int ntimes = 20; | ||
4598 | if (cAgentData.SenderWantsToWaitForRoot) | ||
4599 | { | ||
4600 | while (sp.IsChildAgent && ntimes-- > 0) | ||
4601 | Thread.Sleep(1000); | ||
4602 | |||
4603 | if (sp.IsChildAgent) | ||
4604 | m_log.WarnFormat( | ||
4605 | "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}", | ||
4606 | sp.Name, sp.UUID, Name); | ||
4607 | else | ||
4608 | m_log.InfoFormat( | ||
4609 | "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits", | ||
4610 | sp.Name, sp.UUID, Name, 20 - ntimes); | ||
4611 | |||
4612 | if (sp.IsChildAgent) | ||
4613 | return false; | ||
4614 | } | ||
4615 | |||
4400 | return true; | 4616 | return true; |
4401 | } | 4617 | } |
4402 | 4618 | ||
@@ -4409,12 +4625,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
4409 | /// </summary> | 4625 | /// </summary> |
4410 | /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> | 4626 | /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> |
4411 | /// <returns>true if we handled it.</returns> | 4627 | /// <returns>true if we handled it.</returns> |
4412 | public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) | 4628 | public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) |
4413 | { | 4629 | { |
4414 | //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); | 4630 | //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); |
4415 | ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); | 4631 | ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); |
4416 | if (childAgentUpdate != null) | 4632 | if (childAgentUpdate != null) |
4417 | { | 4633 | { |
4634 | // if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) | ||
4635 | // // Only warn for now | ||
4636 | // m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", | ||
4637 | // childAgentUpdate.UUID, cAgentData.SessionID); | ||
4638 | |||
4418 | // I can't imagine *yet* why we would get an update if the agent is a root agent.. | 4639 | // I can't imagine *yet* why we would get an update if the agent is a root agent.. |
4419 | // however to avoid a race condition crossing borders.. | 4640 | // however to avoid a race condition crossing borders.. |
4420 | if (childAgentUpdate.IsChildAgent) | 4641 | if (childAgentUpdate.IsChildAgent) |
@@ -4424,7 +4645,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4424 | uint tRegionX = RegionInfo.RegionLocX; | 4645 | uint tRegionX = RegionInfo.RegionLocX; |
4425 | uint tRegionY = RegionInfo.RegionLocY; | 4646 | uint tRegionY = RegionInfo.RegionLocY; |
4426 | //Send Data to ScenePresence | 4647 | //Send Data to ScenePresence |
4427 | childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); | 4648 | childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); |
4428 | // Not Implemented: | 4649 | // Not Implemented: |
4429 | //TODO: Do we need to pass the message on to one of our neighbors? | 4650 | //TODO: Do we need to pass the message on to one of our neighbors? |
4430 | } | 4651 | } |
@@ -4451,35 +4672,99 @@ namespace OpenSim.Region.Framework.Scenes | |||
4451 | m_log.WarnFormat( | 4672 | m_log.WarnFormat( |
4452 | "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", | 4673 | "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", |
4453 | agentID, RegionInfo.RegionName); | 4674 | agentID, RegionInfo.RegionName); |
4454 | // else | ||
4455 | // m_log.DebugFormat( | ||
4456 | // "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits", | ||
4457 | // sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes); | ||
4458 | 4675 | ||
4459 | return sp; | 4676 | return sp; |
4460 | } | 4677 | } |
4461 | 4678 | ||
4462 | public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) | 4679 | /// <summary> |
4680 | /// Authenticated close (via network) | ||
4681 | /// </summary> | ||
4682 | /// <param name="agentID"></param> | ||
4683 | /// <param name="force"></param> | ||
4684 | /// <param name="auth_token"></param> | ||
4685 | /// <returns></returns> | ||
4686 | public bool CloseAgent(UUID agentID, bool force, string auth_token) | ||
4463 | { | 4687 | { |
4464 | agent = null; | 4688 | //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token); |
4465 | ScenePresence sp = GetScenePresence(id); | 4689 | |
4466 | if ((sp != null) && (!sp.IsChildAgent)) | 4690 | // Check that the auth_token is valid |
4691 | AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); | ||
4692 | |||
4693 | if (acd == null) | ||
4694 | { | ||
4695 | m_log.DebugFormat( | ||
4696 | "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", | ||
4697 | agentID, Name); | ||
4698 | |||
4699 | return false; | ||
4700 | } | ||
4701 | |||
4702 | if (acd.SessionID.ToString() == auth_token) | ||
4703 | { | ||
4704 | return CloseAgent(agentID, force); | ||
4705 | } | ||
4706 | else | ||
4467 | { | 4707 | { |
4468 | sp.IsChildAgent = true; | 4708 | m_log.WarnFormat( |
4469 | return sp.CopyAgent(out agent); | 4709 | "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", |
4710 | agentID, auth_token, Name); | ||
4470 | } | 4711 | } |
4471 | 4712 | ||
4472 | return false; | 4713 | return false; |
4473 | } | 4714 | } |
4474 | 4715 | ||
4475 | public bool IncomingCloseAgent(UUID agentID) | 4716 | // public bool IncomingCloseAgent(UUID agentID) |
4476 | { | 4717 | // { |
4477 | return IncomingCloseAgent(agentID, false); | 4718 | // return IncomingCloseAgent(agentID, false); |
4478 | } | 4719 | // } |
4479 | 4720 | ||
4480 | public bool IncomingCloseChildAgent(UUID agentID) | 4721 | // public bool IncomingCloseChildAgent(UUID agentID) |
4722 | // { | ||
4723 | // return IncomingCloseAgent(agentID, true); | ||
4724 | // } | ||
4725 | |||
4726 | /// <summary> | ||
4727 | /// Tell a single client to prepare to close. | ||
4728 | /// </summary> | ||
4729 | /// <remarks> | ||
4730 | /// This should only be called if we may close the client but there will be some delay in so doing. Meant for | ||
4731 | /// internal use - other callers should almost certainly called CloseClient(). | ||
4732 | /// </remarks> | ||
4733 | /// <param name="sp"></param> | ||
4734 | /// <returns>true if pre-close state notification was successful. false if the agent | ||
4735 | /// was not in a state where it could transition to pre-close.</returns> | ||
4736 | public bool IncomingPreCloseClient(ScenePresence sp) | ||
4481 | { | 4737 | { |
4482 | return IncomingCloseAgent(agentID, true); | 4738 | lock (m_removeClientLock) |
4739 | { | ||
4740 | // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may | ||
4741 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not | ||
4742 | // want to obey this close since C may have renewed the child agent lease on B. | ||
4743 | if (sp.DoNotCloseAfterTeleport) | ||
4744 | { | ||
4745 | m_log.DebugFormat( | ||
4746 | "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection", | ||
4747 | sp.IsChildAgent ? "child" : "root", sp.Name, Name); | ||
4748 | |||
4749 | // Need to reset the flag so that a subsequent close after another teleport can succeed. | ||
4750 | sp.DoNotCloseAfterTeleport = false; | ||
4751 | |||
4752 | return false; | ||
4753 | } | ||
4754 | |||
4755 | if (sp.LifecycleState != ScenePresenceState.Running) | ||
4756 | { | ||
4757 | m_log.DebugFormat( | ||
4758 | "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}", | ||
4759 | sp.Name, Name, sp.LifecycleState); | ||
4760 | |||
4761 | return false; | ||
4762 | } | ||
4763 | |||
4764 | sp.LifecycleState = ScenePresenceState.PreRemove; | ||
4765 | |||
4766 | return true; | ||
4767 | } | ||
4483 | } | 4768 | } |
4484 | 4769 | ||
4485 | /// <summary> | 4770 | /// <summary> |
@@ -4490,18 +4775,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
4490 | /// Force the agent to close even if it might be in the middle of some other operation. You do not want to | 4775 | /// Force the agent to close even if it might be in the middle of some other operation. You do not want to |
4491 | /// force unless you are absolutely sure that the agent is dead and a normal close is not working. | 4776 | /// force unless you are absolutely sure that the agent is dead and a normal close is not working. |
4492 | /// </param> | 4777 | /// </param> |
4493 | public bool IncomingCloseAgent(UUID agentID, bool force) | 4778 | public override bool CloseAgent(UUID agentID, bool force) |
4494 | { | 4779 | { |
4495 | //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); | 4780 | ScenePresence sp; |
4496 | 4781 | ||
4497 | ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); | 4782 | lock (m_removeClientLock) |
4498 | if (presence != null) | 4783 | { |
4784 | sp = GetScenePresence(agentID); | ||
4785 | |||
4786 | if (sp == null) | ||
4787 | { | ||
4788 | // If there is no scene presence, we may be handling a dead | ||
4789 | // client. These can keep an avatar from reentering a region | ||
4790 | // and since they don't get cleaned up they will stick | ||
4791 | // around until region restart. So, if there is no SP, | ||
4792 | // remove the client as well. | ||
4793 | IClientAPI client = null; | ||
4794 | if (m_clientManager.TryGetValue(agentID, out client)) | ||
4795 | { | ||
4796 | m_clientManager.Remove(agentID); | ||
4797 | if (CapsModule != null) | ||
4798 | CapsModule.RemoveCaps(agentID, 0); | ||
4799 | m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name); | ||
4800 | return true; | ||
4801 | } | ||
4802 | m_log.DebugFormat( | ||
4803 | "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", | ||
4804 | agentID, Name); | ||
4805 | |||
4806 | return false; | ||
4807 | } | ||
4808 | |||
4809 | if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) | ||
4810 | { | ||
4811 | m_log.DebugFormat( | ||
4812 | "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}", | ||
4813 | sp.Name, Name, sp.LifecycleState); | ||
4814 | |||
4815 | return false; | ||
4816 | } | ||
4817 | |||
4818 | // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may | ||
4819 | // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not | ||
4820 | // want to obey this close since C may have renewed the child agent lease on B. | ||
4821 | if (sp.DoNotCloseAfterTeleport) | ||
4822 | { | ||
4823 | m_log.DebugFormat( | ||
4824 | "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection", | ||
4825 | sp.IsChildAgent ? "child" : "root", sp.Name, Name); | ||
4826 | |||
4827 | // Need to reset the flag so that a subsequent close after another teleport can succeed. | ||
4828 | sp.DoNotCloseAfterTeleport = false; | ||
4829 | |||
4830 | return false; | ||
4831 | } | ||
4832 | |||
4833 | sp.LifecycleState = ScenePresenceState.Removing; | ||
4834 | } | ||
4835 | |||
4836 | if (sp != null) | ||
4499 | { | 4837 | { |
4500 | presence.ControllingClient.Close(force, force); | 4838 | sp.ControllingClient.Close(force, force); |
4501 | return true; | 4839 | return true; |
4502 | } | 4840 | } |
4503 | 4841 | ||
4504 | // Agent not here | 4842 | // Agent not here |
4505 | return false; | 4843 | return false; |
4506 | } | 4844 | } |
4507 | 4845 | ||
@@ -4700,7 +5038,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
4700 | 5038 | ||
4701 | public LandData GetLandData(float x, float y) | 5039 | public LandData GetLandData(float x, float y) |
4702 | { | 5040 | { |
4703 | return LandChannel.GetLandObject(x, y).LandData; | 5041 | ILandObject parcel = LandChannel.GetLandObject(x, y); |
5042 | if (parcel == null) | ||
5043 | return null; | ||
5044 | return parcel.LandData; | ||
4704 | } | 5045 | } |
4705 | 5046 | ||
4706 | /// <summary> | 5047 | /// <summary> |
@@ -4716,7 +5057,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
4716 | public LandData GetLandData(uint x, uint y) | 5057 | public LandData GetLandData(uint x, uint y) |
4717 | { | 5058 | { |
4718 | m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); | 5059 | m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); |
4719 | return LandChannel.GetLandObject((int)x, (int)y).LandData; | 5060 | ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y); |
5061 | if (parcel == null) | ||
5062 | return null; | ||
5063 | return parcel.LandData; | ||
4720 | } | 5064 | } |
4721 | 5065 | ||
4722 | #endregion | 5066 | #endregion |
@@ -5091,21 +5435,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
5091 | 5435 | ||
5092 | #endregion | 5436 | #endregion |
5093 | 5437 | ||
5094 | public void RegionHandleRequest(IClientAPI client, UUID regionID) | ||
5095 | { | ||
5096 | ulong handle = 0; | ||
5097 | if (regionID == RegionInfo.RegionID) | ||
5098 | handle = RegionInfo.RegionHandle; | ||
5099 | else | ||
5100 | { | ||
5101 | GridRegion r = GridService.GetRegionByUUID(UUID.Zero, regionID); | ||
5102 | if (r != null) | ||
5103 | handle = r.RegionHandle; | ||
5104 | } | ||
5105 | |||
5106 | if (handle != 0) | ||
5107 | client.SendRegionHandle(regionID, handle); | ||
5108 | } | ||
5109 | 5438 | ||
5110 | // Commented pending deletion since this method no longer appears to do anything at all | 5439 | // Commented pending deletion since this method no longer appears to do anything at all |
5111 | // public bool NeedSceneCacheClear(UUID agentID) | 5440 | // public bool NeedSceneCacheClear(UUID agentID) |
@@ -5657,12 +5986,12 @@ Environment.Exit(1); | |||
5657 | List<SceneObjectGroup> objects, | 5986 | List<SceneObjectGroup> objects, |
5658 | out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) | 5987 | out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) |
5659 | { | 5988 | { |
5660 | minX = 256; | 5989 | minX = float.MaxValue; |
5661 | maxX = -256; | 5990 | maxX = float.MinValue; |
5662 | minY = 256; | 5991 | minY = float.MaxValue; |
5663 | maxY = -256; | 5992 | maxY = float.MinValue; |
5664 | minZ = 8192; | 5993 | minZ = float.MaxValue; |
5665 | maxZ = -256; | 5994 | maxZ = float.MinValue; |
5666 | 5995 | ||
5667 | List<Vector3> offsets = new List<Vector3>(); | 5996 | List<Vector3> offsets = new List<Vector3>(); |
5668 | 5997 | ||
@@ -5802,17 +6131,6 @@ Environment.Exit(1); | |||
5802 | { | 6131 | { |
5803 | reason = "You are banned from the region"; | 6132 | reason = "You are banned from the region"; |
5804 | 6133 | ||
5805 | if (EntityTransferModule.IsInTransit(agentID)) | ||
5806 | { | ||
5807 | reason = "Agent is still in transit from this region"; | ||
5808 | |||
5809 | m_log.WarnFormat( | ||
5810 | "[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit", | ||
5811 | agentID, RegionInfo.RegionName); | ||
5812 | |||
5813 | return false; | ||
5814 | } | ||
5815 | |||
5816 | if (Permissions.IsGod(agentID)) | 6134 | if (Permissions.IsGod(agentID)) |
5817 | { | 6135 | { |
5818 | reason = String.Empty; | 6136 | reason = String.Empty; |
@@ -5862,9 +6180,9 @@ Environment.Exit(1); | |||
5862 | 6180 | ||
5863 | try | 6181 | try |
5864 | { | 6182 | { |
5865 | if (!AuthorizeUser(aCircuit, out reason)) | 6183 | if (!AuthorizeUser(aCircuit, false, out reason)) |
5866 | { | 6184 | { |
5867 | // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); | 6185 | //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); |
5868 | return false; | 6186 | return false; |
5869 | } | 6187 | } |
5870 | } | 6188 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 74c9582..f5be7a7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs | |||
@@ -1,575 +1,593 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
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.Threading; | 31 | using System.Threading; |
32 | using OpenMetaverse; | 32 | using OpenMetaverse; |
33 | using log4net; | 33 | using log4net; |
34 | using Nini.Config; | 34 | using Nini.Config; |
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Framework.Console; | 36 | using OpenSim.Framework.Console; |
37 | 37 | ||
38 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
39 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | 39 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; |
40 | 40 | ||
41 | namespace OpenSim.Region.Framework.Scenes | 41 | 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 | 46 | protected static readonly string LogHeader = "[SCENE]"; | |
47 | #region Events | 47 | |
48 | 48 | #region Events | |
49 | public event restart OnRestart; | 49 | |
50 | 50 | public event restart OnRestart; | |
51 | #endregion | 51 | |
52 | 52 | #endregion | |
53 | #region Fields | 53 | |
54 | 54 | #region Fields | |
55 | public string Name { get { return RegionInfo.RegionName; } } | 55 | |
56 | 56 | public string Name { get { return RegionInfo.RegionName; } } | |
57 | public IConfigSource Config | 57 | |
58 | { | 58 | public IConfigSource Config |
59 | get { return GetConfig(); } | 59 | { |
60 | } | 60 | get { return GetConfig(); } |
61 | 61 | } | |
62 | protected virtual IConfigSource GetConfig() | 62 | |
63 | { | 63 | protected virtual IConfigSource GetConfig() |
64 | return null; | 64 | { |
65 | } | 65 | return null; |
66 | 66 | } | |
67 | /// <value> | 67 | |
68 | /// All the region modules attached to this scene. | 68 | /// <value> |
69 | /// </value> | 69 | /// All the region modules attached to this scene. |
70 | public Dictionary<string, IRegionModuleBase> RegionModules | 70 | /// </value> |
71 | { | 71 | public Dictionary<string, IRegionModuleBase> RegionModules |
72 | get { return m_regionModules; } | 72 | { |
73 | } | 73 | get { return m_regionModules; } |
74 | private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>(); | 74 | } |
75 | 75 | private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>(); | |
76 | /// <value> | 76 | |
77 | /// The module interfaces available from this scene. | 77 | /// <value> |
78 | /// </value> | 78 | /// The module interfaces available from this scene. |
79 | protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>(); | 79 | /// </value> |
80 | 80 | protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>(); | |
81 | protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>(); | 81 | |
82 | 82 | protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>(); | |
83 | /// <value> | 83 | |
84 | /// The module commanders available from this scene | 84 | /// <value> |
85 | /// </value> | 85 | /// The module commanders available from this scene |
86 | protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>(); | 86 | /// </value> |
87 | 87 | protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>(); | |
88 | /// <value> | 88 | |
89 | /// Registered classes that are capable of creating entities. | 89 | /// <value> |
90 | /// </value> | 90 | /// Registered classes that are capable of creating entities. |
91 | protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>(); | 91 | /// </value> |
92 | 92 | protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>(); | |
93 | /// <summary> | 93 | |
94 | /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is | 94 | /// <summary> |
95 | /// dispensed. | 95 | /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is |
96 | /// </summary> | 96 | /// dispensed. |
97 | protected uint m_lastAllocatedLocalId = 720000; | 97 | /// </summary> |
98 | 98 | protected uint m_lastAllocatedLocalId = 720000; | |
99 | private readonly Mutex _primAllocateMutex = new Mutex(false); | 99 | |
100 | 100 | private readonly Mutex _primAllocateMutex = new Mutex(false); | |
101 | protected readonly ClientManager m_clientManager = new ClientManager(); | 101 | |
102 | 102 | protected readonly ClientManager m_clientManager = new ClientManager(); | |
103 | public bool LoginsEnabled | 103 | |
104 | { | 104 | public bool LoginsEnabled |
105 | get | 105 | { |
106 | { | 106 | get |
107 | return m_loginsEnabled; | 107 | { |
108 | } | 108 | return m_loginsEnabled; |
109 | 109 | } | |
110 | set | 110 | |
111 | { | 111 | set |
112 | if (m_loginsEnabled != value) | 112 | { |
113 | { | 113 | if (m_loginsEnabled != value) |
114 | m_loginsEnabled = value; | 114 | { |
115 | EventManager.TriggerRegionLoginsStatusChange(this); | 115 | m_loginsEnabled = value; |
116 | } | 116 | EventManager.TriggerRegionLoginsStatusChange(this); |
117 | } | 117 | } |
118 | } | 118 | } |
119 | private bool m_loginsEnabled; | 119 | } |
120 | 120 | private bool m_loginsEnabled; | |
121 | public bool Ready | 121 | |
122 | { | 122 | public bool Ready |
123 | get | 123 | { |
124 | { | 124 | get |
125 | return m_ready; | 125 | { |
126 | } | 126 | return m_ready; |
127 | 127 | } | |
128 | set | 128 | |
129 | { | 129 | set |
130 | if (m_ready != value) | 130 | { |
131 | { | 131 | if (m_ready != value) |
132 | m_ready = value; | 132 | { |
133 | EventManager.TriggerRegionReadyStatusChange(this); | 133 | m_ready = value; |
134 | } | 134 | EventManager.TriggerRegionReadyStatusChange(this); |
135 | } | 135 | } |
136 | } | 136 | } |
137 | private bool m_ready; | 137 | } |
138 | 138 | private bool m_ready; | |
139 | public float TimeDilation | 139 | |
140 | { | 140 | public float TimeDilation |
141 | get { return 1.0f; } | 141 | { |
142 | } | 142 | get { return 1.0f; } |
143 | 143 | } | |
144 | protected ulong m_regionHandle; | 144 | |
145 | protected string m_regionName; | 145 | protected ulong m_regionHandle; |
146 | 146 | protected string m_regionName; | |
147 | public ITerrainChannel Heightmap; | 147 | |
148 | 148 | public ITerrainChannel Heightmap; | |
149 | /// <value> | 149 | |
150 | /// Allows retrieval of land information for this scene. | 150 | /// <value> |
151 | /// </value> | 151 | /// Allows retrieval of land information for this scene. |
152 | public ILandChannel LandChannel; | 152 | /// </value> |
153 | 153 | public ILandChannel LandChannel; | |
154 | /// <value> | 154 | |
155 | /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules | 155 | /// <value> |
156 | /// to subscribe to scene events. | 156 | /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules |
157 | /// </value> | 157 | /// to subscribe to scene events. |
158 | public EventManager EventManager | 158 | /// </value> |
159 | { | 159 | public EventManager EventManager |
160 | get { return m_eventManager; } | 160 | { |
161 | } | 161 | get { return m_eventManager; } |
162 | protected EventManager m_eventManager; | 162 | } |
163 | 163 | protected EventManager m_eventManager; | |
164 | protected ScenePermissions m_permissions; | 164 | |
165 | public ScenePermissions Permissions | 165 | protected ScenePermissions m_permissions; |
166 | { | 166 | public ScenePermissions Permissions |
167 | get { return m_permissions; } | 167 | { |
168 | } | 168 | get { return m_permissions; } |
169 | 169 | } | |
170 | protected string m_datastore; | 170 | |
171 | 171 | protected string m_datastore; | |
172 | /* Used by the loadbalancer plugin on GForge */ | 172 | |
173 | protected RegionStatus m_regStatus; | 173 | /* Used by the loadbalancer plugin on GForge */ |
174 | public RegionStatus RegionStatus | 174 | protected RegionStatus m_regStatus; |
175 | { | 175 | public RegionStatus RegionStatus |
176 | get { return m_regStatus; } | 176 | { |
177 | set { m_regStatus = value; } | 177 | get { return m_regStatus; } |
178 | } | 178 | set { m_regStatus = value; } |
179 | 179 | } | |
180 | #endregion | 180 | |
181 | 181 | #endregion | |
182 | public SceneBase(RegionInfo regInfo) | 182 | |
183 | { | 183 | public SceneBase(RegionInfo regInfo) |
184 | RegionInfo = regInfo; | 184 | { |
185 | } | 185 | RegionInfo = regInfo; |
186 | 186 | } | |
187 | #region Update Methods | 187 | |
188 | 188 | #region Update Methods | |
189 | /// <summary> | 189 | |
190 | /// Called to update the scene loop by a number of frames and until shutdown. | 190 | /// <summary> |
191 | /// </summary> | 191 | /// Called to update the scene loop by a number of frames and until shutdown. |
192 | /// <param name="frames"> | 192 | /// </summary> |
193 | /// Number of frames to update. Exits on shutdown even if there are frames remaining. | 193 | /// <param name="frames"> |
194 | /// If -1 then updates until shutdown. | 194 | /// Number of frames to update. Exits on shutdown even if there are frames remaining. |
195 | /// </param> | 195 | /// If -1 then updates until shutdown. |
196 | public abstract void Update(int frames); | 196 | /// </param> |
197 | 197 | public abstract void Update(int frames); | |
198 | #endregion | 198 | |
199 | 199 | #endregion | |
200 | #region Terrain Methods | 200 | |
201 | 201 | #region Terrain Methods | |
202 | /// <summary> | 202 | |
203 | /// Loads the World heightmap | 203 | /// <summary> |
204 | /// </summary> | 204 | /// Loads the World heightmap |
205 | public abstract void LoadWorldMap(); | 205 | /// </summary> |
206 | 206 | public abstract void LoadWorldMap(); | |
207 | /// <summary> | 207 | |
208 | /// Send the region heightmap to the client | 208 | /// <summary> |
209 | /// </summary> | 209 | /// Send the region heightmap to the client |
210 | /// <param name="RemoteClient">Client to send to</param> | 210 | /// </summary> |
211 | public virtual void SendLayerData(IClientAPI RemoteClient) | 211 | /// <param name="RemoteClient">Client to send to</param> |
212 | { | 212 | public virtual void SendLayerData(IClientAPI RemoteClient) |
213 | RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); | 213 | { |
214 | } | 214 | RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); |
215 | 215 | } | |
216 | #endregion | 216 | |
217 | 217 | #endregion | |
218 | #region Add/Remove Agent/Avatar | 218 | |
219 | 219 | #region Add/Remove Agent/Avatar | |
220 | public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); | 220 | |
221 | public abstract void RemoveClient(UUID agentID, bool closeChildAgents); | 221 | public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type); |
222 | 222 | ||
223 | public bool TryGetScenePresence(UUID agentID, out object scenePresence) | 223 | public abstract bool CloseAgent(UUID agentID, bool force); |
224 | { | 224 | |
225 | scenePresence = null; | 225 | public bool TryGetScenePresence(UUID agentID, out object scenePresence) |
226 | ScenePresence sp = null; | 226 | { |
227 | if (TryGetScenePresence(agentID, out sp)) | 227 | scenePresence = null; |
228 | { | 228 | ScenePresence sp = null; |
229 | scenePresence = sp; | 229 | if (TryGetScenePresence(agentID, out sp)) |
230 | return true; | 230 | { |
231 | } | 231 | scenePresence = sp; |
232 | 232 | return true; | |
233 | return false; | 233 | } |
234 | } | 234 | |
235 | 235 | return false; | |
236 | /// <summary> | 236 | } |
237 | /// Try to get a scene presence from the scene | 237 | |
238 | /// </summary> | 238 | /// <summary> |
239 | /// <param name="agentID"></param> | 239 | /// Try to get a scene presence from the scene |
240 | /// <param name="scenePresence">null if there is no scene presence with the given agent id</param> | 240 | /// </summary> |
241 | /// <returns>true if there was a scene presence with the given id, false otherwise.</returns> | 241 | /// <param name="agentID"></param> |
242 | public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); | 242 | /// <param name="scenePresence">null if there is no scene presence with the given agent id</param> |
243 | 243 | /// <returns>true if there was a scene presence with the given id, false otherwise.</returns> | |
244 | #endregion | 244 | public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); |
245 | 245 | ||
246 | /// <summary> | 246 | #endregion |
247 | /// | 247 | |
248 | /// </summary> | 248 | /// <summary> |
249 | /// <returns></returns> | 249 | /// |
250 | public virtual RegionInfo RegionInfo { get; private set; } | 250 | /// </summary> |
251 | 251 | /// <returns></returns> | |
252 | #region admin stuff | 252 | public virtual RegionInfo RegionInfo { get; private set; } |
253 | 253 | ||
254 | public abstract void OtherRegionUp(GridRegion otherRegion); | 254 | #region admin stuff |
255 | 255 | ||
256 | public virtual string GetSimulatorVersion() | 256 | public abstract void OtherRegionUp(GridRegion otherRegion); |
257 | { | 257 | |
258 | return "OpenSimulator Server"; | 258 | public virtual string GetSimulatorVersion() |
259 | } | 259 | { |
260 | 260 | return "OpenSimulator Server"; | |
261 | #endregion | 261 | } |
262 | 262 | ||
263 | #region Shutdown | 263 | #endregion |
264 | 264 | ||
265 | /// <summary> | 265 | #region Shutdown |
266 | /// Tidy before shutdown | 266 | |
267 | /// </summary> | 267 | /// <summary> |
268 | public virtual void Close() | 268 | /// Tidy before shutdown |
269 | { | 269 | /// </summary> |
270 | try | 270 | public virtual void Close() |
271 | { | 271 | { |
272 | EventManager.TriggerShutdown(); | 272 | try |
273 | } | 273 | { |
274 | catch (Exception e) | 274 | EventManager.TriggerShutdown(); |
275 | { | 275 | } |
276 | m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); | 276 | catch (Exception e) |
277 | } | 277 | { |
278 | } | 278 | m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); |
279 | 279 | } | |
280 | #endregion | 280 | } |
281 | 281 | ||
282 | /// <summary> | 282 | #endregion |
283 | /// Returns a new unallocated local ID | 283 | |
284 | /// </summary> | 284 | /// <summary> |
285 | /// <returns>A brand new local ID</returns> | 285 | /// Returns a new unallocated local ID |
286 | public uint AllocateLocalId() | 286 | /// </summary> |
287 | { | 287 | /// <returns>A brand new local ID</returns> |
288 | uint myID; | 288 | public uint AllocateLocalId() |
289 | 289 | { | |
290 | _primAllocateMutex.WaitOne(); | 290 | uint myID; |
291 | myID = ++m_lastAllocatedLocalId; | 291 | |
292 | _primAllocateMutex.ReleaseMutex(); | 292 | _primAllocateMutex.WaitOne(); |
293 | 293 | myID = ++m_lastAllocatedLocalId; | |
294 | return myID; | 294 | _primAllocateMutex.ReleaseMutex(); |
295 | } | 295 | |
296 | 296 | return myID; | |
297 | #region Module Methods | 297 | } |
298 | 298 | ||
299 | /// <summary> | 299 | public uint AllocatePresenceLocalId() |
300 | /// Add a region-module to this scene. TODO: This will replace AddModule in the future. | 300 | { |
301 | /// </summary> | 301 | uint myID; |
302 | /// <param name="name"></param> | 302 | |
303 | /// <param name="module"></param> | 303 | _primAllocateMutex.WaitOne(); |
304 | public void AddRegionModule(string name, IRegionModuleBase module) | 304 | myID = ++m_lastAllocatedLocalId; |
305 | { | 305 | ++m_lastAllocatedLocalId; |
306 | if (!RegionModules.ContainsKey(name)) | 306 | _primAllocateMutex.ReleaseMutex(); |
307 | { | 307 | |
308 | RegionModules.Add(name, module); | 308 | return myID; |
309 | } | 309 | } |
310 | } | 310 | |
311 | 311 | #region Module Methods | |
312 | public void RemoveRegionModule(string name) | 312 | |
313 | { | 313 | /// <summary> |
314 | RegionModules.Remove(name); | 314 | /// Add a region-module to this scene. TODO: This will replace AddModule in the future. |
315 | } | 315 | /// </summary> |
316 | 316 | /// <param name="name"></param> | |
317 | /// <summary> | 317 | /// <param name="module"></param> |
318 | /// Register a module commander. | 318 | public void AddRegionModule(string name, IRegionModuleBase module) |
319 | /// </summary> | 319 | { |
320 | /// <param name="commander"></param> | 320 | if (!RegionModules.ContainsKey(name)) |
321 | public void RegisterModuleCommander(ICommander commander) | 321 | { |
322 | { | 322 | RegionModules.Add(name, module); |
323 | lock (m_moduleCommanders) | 323 | } |
324 | { | 324 | } |
325 | m_moduleCommanders.Add(commander.Name, commander); | 325 | |
326 | } | 326 | public void RemoveRegionModule(string name) |
327 | } | 327 | { |
328 | 328 | RegionModules.Remove(name); | |
329 | /// <summary> | 329 | } |
330 | /// Unregister a module commander and all its commands | 330 | |
331 | /// </summary> | 331 | /// <summary> |
332 | /// <param name="name"></param> | 332 | /// Register a module commander. |
333 | public void UnregisterModuleCommander(string name) | 333 | /// </summary> |
334 | { | 334 | /// <param name="commander"></param> |
335 | lock (m_moduleCommanders) | 335 | public void RegisterModuleCommander(ICommander commander) |
336 | { | 336 | { |
337 | ICommander commander; | 337 | lock (m_moduleCommanders) |
338 | if (m_moduleCommanders.TryGetValue(name, out commander)) | 338 | { |
339 | m_moduleCommanders.Remove(name); | 339 | m_moduleCommanders.Add(commander.Name, commander); |
340 | } | 340 | } |
341 | } | 341 | } |
342 | 342 | ||
343 | /// <summary> | 343 | /// <summary> |
344 | /// Get a module commander | 344 | /// Unregister a module commander and all its commands |
345 | /// </summary> | 345 | /// </summary> |
346 | /// <param name="name"></param> | 346 | /// <param name="name"></param> |
347 | /// <returns>The module commander, null if no module commander with that name was found</returns> | 347 | public void UnregisterModuleCommander(string name) |
348 | public ICommander GetCommander(string name) | 348 | { |
349 | { | 349 | lock (m_moduleCommanders) |
350 | lock (m_moduleCommanders) | 350 | { |
351 | { | 351 | ICommander commander; |
352 | if (m_moduleCommanders.ContainsKey(name)) | 352 | if (m_moduleCommanders.TryGetValue(name, out commander)) |
353 | return m_moduleCommanders[name]; | 353 | m_moduleCommanders.Remove(name); |
354 | } | 354 | } |
355 | 355 | } | |
356 | return null; | 356 | |
357 | } | 357 | /// <summary> |
358 | 358 | /// Get a module commander | |
359 | public Dictionary<string, ICommander> GetCommanders() | 359 | /// </summary> |
360 | { | 360 | /// <param name="name"></param> |
361 | return m_moduleCommanders; | 361 | /// <returns>The module commander, null if no module commander with that name was found</returns> |
362 | } | 362 | public ICommander GetCommander(string name) |
363 | 363 | { | |
364 | /// <summary> | 364 | lock (m_moduleCommanders) |
365 | /// Register an interface to a region module. This allows module methods to be called directly as | 365 | { |
366 | /// well as via events. If there is already a module registered for this interface, it is not replaced | 366 | if (m_moduleCommanders.ContainsKey(name)) |
367 | /// (is this the best behaviour?) | 367 | return m_moduleCommanders[name]; |
368 | /// </summary> | 368 | } |
369 | /// <param name="mod"></param> | 369 | |
370 | public void RegisterModuleInterface<M>(M mod) | 370 | return null; |
371 | { | 371 | } |
372 | // m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); | 372 | |
373 | 373 | public Dictionary<string, ICommander> GetCommanders() | |
374 | List<Object> l = null; | 374 | { |
375 | if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) | 375 | return m_moduleCommanders; |
376 | { | 376 | } |
377 | l = new List<Object>(); | 377 | |
378 | ModuleInterfaces.Add(typeof(M), l); | 378 | /// <summary> |
379 | } | 379 | /// Register an interface to a region module. This allows module methods to be called directly as |
380 | 380 | /// well as via events. If there is already a module registered for this interface, it is not replaced | |
381 | if (l.Count > 0) | 381 | /// (is this the best behaviour?) |
382 | return; | 382 | /// </summary> |
383 | 383 | /// <param name="mod"></param> | |
384 | l.Add(mod); | 384 | public void RegisterModuleInterface<M>(M mod) |
385 | 385 | { | |
386 | if (mod is IEntityCreator) | 386 | // m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); |
387 | { | 387 | |
388 | IEntityCreator entityCreator = (IEntityCreator)mod; | 388 | List<Object> l = null; |
389 | foreach (PCode pcode in entityCreator.CreationCapabilities) | 389 | if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) |
390 | { | 390 | { |
391 | m_entityCreators[pcode] = entityCreator; | 391 | l = new List<Object>(); |
392 | } | 392 | ModuleInterfaces.Add(typeof(M), l); |
393 | } | 393 | } |
394 | } | 394 | |
395 | 395 | if (l.Count > 0) | |
396 | public void UnregisterModuleInterface<M>(M mod) | 396 | return; |
397 | { | 397 | |
398 | List<Object> l; | 398 | l.Add(mod); |
399 | if (ModuleInterfaces.TryGetValue(typeof(M), out l)) | 399 | |
400 | { | 400 | if (mod is IEntityCreator) |
401 | if (l.Remove(mod)) | 401 | { |
402 | { | 402 | IEntityCreator entityCreator = (IEntityCreator)mod; |
403 | if (mod is IEntityCreator) | 403 | foreach (PCode pcode in entityCreator.CreationCapabilities) |
404 | { | 404 | { |
405 | IEntityCreator entityCreator = (IEntityCreator)mod; | 405 | m_entityCreators[pcode] = entityCreator; |
406 | foreach (PCode pcode in entityCreator.CreationCapabilities) | 406 | } |
407 | { | 407 | } |
408 | m_entityCreators[pcode] = null; | 408 | } |
409 | } | 409 | |
410 | } | 410 | public void UnregisterModuleInterface<M>(M mod) |
411 | } | 411 | { |
412 | } | 412 | List<Object> l; |
413 | } | 413 | if (ModuleInterfaces.TryGetValue(typeof(M), out l)) |
414 | 414 | { | |
415 | public void StackModuleInterface<M>(M mod) | 415 | if (l.Remove(mod)) |
416 | { | 416 | { |
417 | List<Object> l; | 417 | if (mod is IEntityCreator) |
418 | if (ModuleInterfaces.ContainsKey(typeof(M))) | 418 | { |
419 | l = ModuleInterfaces[typeof(M)]; | 419 | IEntityCreator entityCreator = (IEntityCreator)mod; |
420 | else | 420 | foreach (PCode pcode in entityCreator.CreationCapabilities) |
421 | l = new List<Object>(); | 421 | { |
422 | 422 | m_entityCreators[pcode] = null; | |
423 | if (l.Contains(mod)) | 423 | } |
424 | return; | 424 | } |
425 | 425 | } | |
426 | l.Add(mod); | 426 | } |
427 | 427 | } | |
428 | if (mod is IEntityCreator) | 428 | |
429 | { | 429 | public void StackModuleInterface<M>(M mod) |
430 | IEntityCreator entityCreator = (IEntityCreator)mod; | 430 | { |
431 | foreach (PCode pcode in entityCreator.CreationCapabilities) | 431 | List<Object> l; |
432 | { | 432 | if (ModuleInterfaces.ContainsKey(typeof(M))) |
433 | m_entityCreators[pcode] = entityCreator; | 433 | l = ModuleInterfaces[typeof(M)]; |
434 | } | 434 | else |
435 | } | 435 | l = new List<Object>(); |
436 | 436 | ||
437 | ModuleInterfaces[typeof(M)] = l; | 437 | if (l.Contains(mod)) |
438 | } | 438 | return; |
439 | 439 | ||
440 | /// <summary> | 440 | l.Add(mod); |
441 | /// For the given interface, retrieve the region module which implements it. | 441 | |
442 | /// </summary> | 442 | if (mod is IEntityCreator) |
443 | /// <returns>null if there is no registered module implementing that interface</returns> | 443 | { |
444 | public T RequestModuleInterface<T>() | 444 | IEntityCreator entityCreator = (IEntityCreator)mod; |
445 | { | 445 | foreach (PCode pcode in entityCreator.CreationCapabilities) |
446 | if (ModuleInterfaces.ContainsKey(typeof(T)) && | 446 | { |
447 | (ModuleInterfaces[typeof(T)].Count > 0)) | 447 | m_entityCreators[pcode] = entityCreator; |
448 | return (T)ModuleInterfaces[typeof(T)][0]; | 448 | } |
449 | else | 449 | } |
450 | return default(T); | 450 | |
451 | } | 451 | ModuleInterfaces[typeof(M)] = l; |
452 | 452 | } | |
453 | /// <summary> | 453 | |
454 | /// For the given interface, retrieve an array of region modules that implement it. | 454 | /// <summary> |
455 | /// </summary> | 455 | /// For the given interface, retrieve the region module which implements it. |
456 | /// <returns>an empty array if there are no registered modules implementing that interface</returns> | 456 | /// </summary> |
457 | public T[] RequestModuleInterfaces<T>() | 457 | /// <returns>null if there is no registered module implementing that interface</returns> |
458 | { | 458 | public T RequestModuleInterface<T>() |
459 | if (ModuleInterfaces.ContainsKey(typeof(T))) | 459 | { |
460 | { | 460 | if (ModuleInterfaces.ContainsKey(typeof(T)) && |
461 | List<T> ret = new List<T>(); | 461 | (ModuleInterfaces[typeof(T)].Count > 0)) |
462 | 462 | return (T)ModuleInterfaces[typeof(T)][0]; | |
463 | foreach (Object o in ModuleInterfaces[typeof(T)]) | 463 | else |
464 | ret.Add((T)o); | 464 | return default(T); |
465 | return ret.ToArray(); | 465 | } |
466 | } | 466 | |
467 | else | 467 | /// <summary> |
468 | { | 468 | /// For the given interface, retrieve an array of region modules that implement it. |
469 | return new T[] {}; | 469 | /// </summary> |
470 | } | 470 | /// <returns>an empty array if there are no registered modules implementing that interface</returns> |
471 | } | 471 | public T[] RequestModuleInterfaces<T>() |
472 | 472 | { | |
473 | #endregion | 473 | if (ModuleInterfaces.ContainsKey(typeof(T))) |
474 | 474 | { | |
475 | /// <summary> | 475 | List<T> ret = new List<T>(); |
476 | /// Call this from a region module to add a command to the OpenSim console. | 476 | |
477 | /// </summary> | 477 | foreach (Object o in ModuleInterfaces[typeof(T)]) |
478 | /// <param name="mod"></param> | 478 | ret.Add((T)o); |
479 | /// <param name="command"></param> | 479 | return ret.ToArray(); |
480 | /// <param name="shorthelp"></param> | 480 | } |
481 | /// <param name="longhelp"></param> | 481 | else |
482 | /// <param name="callback"></param> | 482 | { |
483 | public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) | 483 | return new T[] {}; |
484 | { | 484 | } |
485 | AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); | 485 | } |
486 | } | 486 | |
487 | 487 | #endregion | |
488 | /// <summary> | 488 | |
489 | /// Call this from a region module to add a command to the OpenSim console. | 489 | /// <summary> |
490 | /// </summary> | 490 | /// Call this from a region module to add a command to the OpenSim console. |
491 | /// <param name="mod"> | 491 | /// </summary> |
492 | /// The use of IRegionModuleBase is a cheap trick to get a different method signature, | 492 | /// <param name="mod"></param> |
493 | /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. | 493 | /// <param name="command"></param> |
494 | /// </param> | 494 | /// <param name="shorthelp"></param> |
495 | /// <param name="category"> | 495 | /// <param name="longhelp"></param> |
496 | /// Category of the command. This is the section under which it will appear when the user asks for help | 496 | /// <param name="callback"></param> |
497 | /// </param> | 497 | public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) |
498 | /// <param name="command"></param> | 498 | { |
499 | /// <param name="shorthelp"></param> | 499 | AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); |
500 | /// <param name="longhelp"></param> | 500 | } |
501 | /// <param name="callback"></param> | 501 | |
502 | public void AddCommand( | 502 | /// <summary> |
503 | string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) | 503 | /// Call this from a region module to add a command to the OpenSim console. |
504 | { | 504 | /// </summary> |
505 | AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); | 505 | /// <param name="mod"> |
506 | } | 506 | /// The use of IRegionModuleBase is a cheap trick to get a different method signature, |
507 | 507 | /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. | |
508 | /// <summary> | 508 | /// </param> |
509 | /// Call this from a region module to add a command to the OpenSim console. | 509 | /// <param name="category"> |
510 | /// </summary> | 510 | /// Category of the command. This is the section under which it will appear when the user asks for help |
511 | /// <param name="mod"></param> | 511 | /// </param> |
512 | /// <param name="command"></param> | 512 | /// <param name="command"></param> |
513 | /// <param name="shorthelp"></param> | 513 | /// <param name="shorthelp"></param> |
514 | /// <param name="longhelp"></param> | 514 | /// <param name="longhelp"></param> |
515 | /// <param name="descriptivehelp"></param> | 515 | /// <param name="callback"></param> |
516 | /// <param name="callback"></param> | 516 | public void AddCommand( |
517 | public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) | 517 | string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) |
518 | { | 518 | { |
519 | string moduleName = ""; | 519 | AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); |
520 | 520 | } | |
521 | if (module != null) | 521 | |
522 | moduleName = module.Name; | 522 | /// <summary> |
523 | 523 | /// Call this from a region module to add a command to the OpenSim console. | |
524 | AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); | 524 | /// </summary> |
525 | } | 525 | /// <param name="mod"></param> |
526 | 526 | /// <param name="command"></param> | |
527 | /// <summary> | 527 | /// <param name="shorthelp"></param> |
528 | /// Call this from a region module to add a command to the OpenSim console. | 528 | /// <param name="longhelp"></param> |
529 | /// </summary> | 529 | /// <param name="descriptivehelp"></param> |
530 | /// <param name="category"> | 530 | /// <param name="callback"></param> |
531 | /// Category of the command. This is the section under which it will appear when the user asks for help | 531 | public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) |
532 | /// </param> | 532 | { |
533 | /// <param name="mod"></param> | 533 | string moduleName = ""; |
534 | /// <param name="command"></param> | 534 | |
535 | /// <param name="shorthelp"></param> | 535 | if (module != null) |
536 | /// <param name="longhelp"></param> | 536 | moduleName = module.Name; |
537 | /// <param name="descriptivehelp"></param> | 537 | |
538 | /// <param name="callback"></param> | 538 | AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); |
539 | public void AddCommand( | 539 | } |
540 | string category, IRegionModuleBase module, string command, | 540 | |
541 | string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) | 541 | /// <summary> |
542 | { | 542 | /// Call this from a region module to add a command to the OpenSim console. |
543 | if (MainConsole.Instance == null) | 543 | /// </summary> |
544 | return; | 544 | /// <param name="category"> |
545 | 545 | /// Category of the command. This is the section under which it will appear when the user asks for help | |
546 | bool shared = false; | 546 | /// </param> |
547 | 547 | /// <param name="mod"></param> | |
548 | if (module != null) | 548 | /// <param name="command"></param> |
549 | shared = module is ISharedRegionModule; | 549 | /// <param name="shorthelp"></param> |
550 | 550 | /// <param name="longhelp"></param> | |
551 | MainConsole.Instance.Commands.AddCommand( | 551 | /// <param name="descriptivehelp"></param> |
552 | category, shared, command, shorthelp, longhelp, descriptivehelp, callback); | 552 | /// <param name="callback"></param> |
553 | } | 553 | public void AddCommand( |
554 | 554 | string category, IRegionModuleBase module, string command, | |
555 | public virtual ISceneObject DeserializeObject(string representation) | 555 | string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) |
556 | { | 556 | { |
557 | return null; | 557 | if (MainConsole.Instance == null) |
558 | } | 558 | return; |
559 | 559 | ||
560 | public virtual bool AllowScriptCrossings | 560 | bool shared = false; |
561 | { | 561 | |
562 | get { return false; } | 562 | if (module != null) |
563 | } | 563 | shared = module is ISharedRegionModule; |
564 | 564 | ||
565 | public void Restart() | 565 | MainConsole.Instance.Commands.AddCommand( |
566 | { | 566 | category, shared, command, shorthelp, longhelp, descriptivehelp, callback); |
567 | // This has to be here to fire the event | 567 | } |
568 | restart handlerPhysicsCrash = OnRestart; | 568 | |
569 | if (handlerPhysicsCrash != null) | 569 | public virtual ISceneObject DeserializeObject(string representation) |
570 | handlerPhysicsCrash(RegionInfo); | 570 | { |
571 | } | 571 | return null; |
572 | 572 | } | |
573 | public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); | 573 | |
574 | } | 574 | public virtual bool AllowScriptCrossings |
575 | } | 575 | { |
576 | get { return false; } | ||
577 | } | ||
578 | |||
579 | public virtual void Start() | ||
580 | { | ||
581 | } | ||
582 | |||
583 | public void Restart() | ||
584 | { | ||
585 | // This has to be here to fire the event | ||
586 | restart handlerPhysicsCrash = OnRestart; | ||
587 | if (handlerPhysicsCrash != null) | ||
588 | handlerPhysicsCrash(RegionInfo); | ||
589 | } | ||
590 | |||
591 | public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); | ||
592 | } | ||
593 | } | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 775a4c2..52f46f2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | |||
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
200 | /// This Closes child agents on neighboring regions | 200 | /// This Closes child agents on neighboring regions |
201 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 201 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
202 | /// </summary> | 202 | /// </summary> |
203 | protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) | 203 | protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token) |
204 | { | 204 | { |
205 | // let's do our best, but there's not much we can do if the neighbour doesn't accept. | 205 | // let's do our best, but there's not much we can do if the neighbour doesn't accept. |
206 | 206 | ||
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
209 | Utils.LongToUInts(regionHandle, out x, out y); | 209 | Utils.LongToUInts(regionHandle, out x, out y); |
210 | 210 | ||
211 | GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); | 211 | GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); |
212 | m_scene.SimulationService.CloseChildAgent(destination, agentID); | ||
213 | } | ||
214 | 212 | ||
215 | private void SendCloseChildAgentCompleted(IAsyncResult iar) | 213 | m_log.DebugFormat( |
216 | { | 214 | "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName); |
217 | SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; | 215 | |
218 | icon.EndInvoke(iar); | 216 | m_scene.SimulationService.CloseAgent(destination, agentID, auth_token); |
219 | } | 217 | } |
220 | 218 | ||
221 | public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) | 219 | /// <summary> |
220 | /// Closes a child agents in a collection of regions. Does so asynchronously | ||
221 | /// so that the caller doesn't wait. | ||
222 | /// </summary> | ||
223 | /// <param name="agentID"></param> | ||
224 | /// <param name="regionslst"></param> | ||
225 | public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst) | ||
222 | { | 226 | { |
223 | foreach (ulong handle in regionslst) | 227 | foreach (ulong handle in regionslst) |
224 | { | 228 | { |
225 | SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; | 229 | ulong handleCopy = handle; |
226 | d.BeginInvoke(agentID, handle, | 230 | Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); }); |
227 | SendCloseChildAgentCompleted, | ||
228 | d); | ||
229 | } | 231 | } |
230 | } | 232 | } |
231 | 233 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e599e90..92ce411 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -271,38 +271,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
271 | { | 271 | { |
272 | if (!m_parentScene.CombineRegions) | 272 | if (!m_parentScene.CombineRegions) |
273 | { | 273 | { |
274 | // temporary checks to remove after varsize suport | ||
275 | float regionSizeX = m_parentScene.RegionInfo.RegionSizeX; | ||
276 | if (regionSizeX == 0) | ||
277 | regionSizeX = Constants.RegionSize; | ||
278 | float regionSizeY = m_parentScene.RegionInfo.RegionSizeY; | ||
279 | if (regionSizeY == 0) | ||
280 | regionSizeY = Constants.RegionSize; | ||
281 | |||
274 | // KF: Check for out-of-region, move inside and make static. | 282 | // KF: Check for out-of-region, move inside and make static. |
275 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | 283 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, |
276 | sceneObject.RootPart.GroupPosition.Y, | 284 | sceneObject.RootPart.GroupPosition.Y, |
277 | sceneObject.RootPart.GroupPosition.Z); | 285 | sceneObject.RootPart.GroupPosition.Z); |
278 | if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || | 286 | if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || |
279 | npos.X > Constants.RegionSize || | 287 | npos.X > regionSizeX || |
280 | npos.Y > Constants.RegionSize)) | 288 | npos.Y > regionSizeY)) |
281 | { | 289 | { |
282 | if (npos.X < 0.0) npos.X = 1.0f; | 290 | if (npos.X < 0.0) npos.X = 1.0f; |
283 | if (npos.Y < 0.0) npos.Y = 1.0f; | 291 | if (npos.Y < 0.0) npos.Y = 1.0f; |
284 | if (npos.Z < 0.0) npos.Z = 0.0f; | 292 | if (npos.Z < 0.0) npos.Z = 0.0f; |
285 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | 293 | if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f; |
286 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | 294 | if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f; |
287 | 295 | ||
296 | SceneObjectPart rootpart = sceneObject.RootPart; | ||
297 | rootpart.GroupPosition = npos; | ||
298 | |||
288 | foreach (SceneObjectPart part in sceneObject.Parts) | 299 | foreach (SceneObjectPart part in sceneObject.Parts) |
289 | { | 300 | { |
301 | if (part == rootpart) | ||
302 | continue; | ||
290 | part.GroupPosition = npos; | 303 | part.GroupPosition = npos; |
291 | } | 304 | } |
292 | sceneObject.RootPart.Velocity = Vector3.Zero; | 305 | rootpart.Velocity = Vector3.Zero; |
293 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | 306 | rootpart.AngularVelocity = Vector3.Zero; |
294 | sceneObject.RootPart.Acceleration = Vector3.Zero; | 307 | rootpart.Acceleration = Vector3.Zero; |
295 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
296 | } | 308 | } |
297 | } | 309 | } |
298 | 310 | ||
311 | bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | ||
312 | |||
299 | if (attachToBackup && (!alreadyPersisted)) | 313 | if (attachToBackup && (!alreadyPersisted)) |
300 | { | 314 | { |
301 | sceneObject.ForceInventoryPersistence(); | 315 | sceneObject.ForceInventoryPersistence(); |
302 | sceneObject.HasGroupChanged = true; | 316 | sceneObject.HasGroupChanged = true; |
303 | } | 317 | } |
304 | 318 | ||
305 | return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | 319 | return ret; |
306 | } | 320 | } |
307 | 321 | ||
308 | /// <summary> | 322 | /// <summary> |
@@ -319,12 +333,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
319 | /// </returns> | 333 | /// </returns> |
320 | protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 334 | protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
321 | { | 335 | { |
322 | // Ensure that we persist this new scene object if it's not an | 336 | |
337 | bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | ||
338 | |||
339 | // Ensure that we persist this new scene object if it's not an | ||
323 | // attachment | 340 | // attachment |
341 | |||
324 | if (attachToBackup) | 342 | if (attachToBackup) |
325 | sceneObject.HasGroupChanged = true; | 343 | sceneObject.HasGroupChanged = true; |
326 | 344 | ||
327 | return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | 345 | return ret; |
328 | } | 346 | } |
329 | 347 | ||
330 | /// <summary> | 348 | /// <summary> |
@@ -421,9 +439,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
421 | { | 439 | { |
422 | Vector3 scale = part.Shape.Scale; | 440 | Vector3 scale = part.Shape.Scale; |
423 | 441 | ||
424 | scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); | 442 | scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
425 | scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); | 443 | scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
426 | scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); | 444 | scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
427 | 445 | ||
428 | part.Shape.Scale = scale; | 446 | part.Shape.Scale = scale; |
429 | } | 447 | } |
@@ -432,36 +450,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
432 | 450 | ||
433 | sceneObject.AttachToScene(m_parentScene); | 451 | sceneObject.AttachToScene(m_parentScene); |
434 | 452 | ||
435 | if (sendClientUpdates) | ||
436 | sceneObject.ScheduleGroupForFullUpdate(); | ||
437 | |||
438 | Entities.Add(sceneObject); | 453 | Entities.Add(sceneObject); |
439 | 454 | ||
440 | if (attachToBackup) | ||
441 | sceneObject.AttachToBackup(); | ||
442 | |||
443 | lock (SceneObjectGroupsByFullID) | 455 | lock (SceneObjectGroupsByFullID) |
444 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; | 456 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; |
445 | 457 | ||
446 | lock (SceneObjectGroupsByFullPartID) | 458 | foreach (SceneObjectPart part in parts) |
447 | { | 459 | { |
448 | foreach (SceneObjectPart part in parts) | 460 | lock (SceneObjectGroupsByFullPartID) |
449 | SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; | 461 | SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; |
450 | } | ||
451 | 462 | ||
452 | lock (SceneObjectGroupsByLocalPartID) | 463 | lock (SceneObjectGroupsByLocalPartID) |
453 | { | ||
454 | // m_log.DebugFormat( | ||
455 | // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", | ||
456 | // sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); | ||
457 | |||
458 | foreach (SceneObjectPart part in parts) | ||
459 | SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; | 464 | SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; |
460 | } | 465 | } |
461 | 466 | ||
467 | if (sendClientUpdates) | ||
468 | sceneObject.ScheduleGroupForFullUpdate(); | ||
469 | |||
470 | if (attachToBackup) | ||
471 | sceneObject.AttachToBackup(); | ||
472 | |||
462 | return true; | 473 | return true; |
463 | } | 474 | } |
464 | 475 | ||
476 | public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp) | ||
477 | { | ||
478 | // no tests, caller has responsability... | ||
479 | lock (SceneObjectGroupsByFullPartID) | ||
480 | SceneObjectGroupsByFullPartID[part.UUID] = grp; | ||
481 | |||
482 | lock (SceneObjectGroupsByLocalPartID) | ||
483 | SceneObjectGroupsByLocalPartID[part.LocalId] = grp; | ||
484 | } | ||
485 | |||
465 | /// <summary> | 486 | /// <summary> |
466 | /// Delete an object from the scene | 487 | /// Delete an object from the scene |
467 | /// </summary> | 488 | /// </summary> |
@@ -488,25 +509,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
488 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) | 509 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) |
489 | RemovePhysicalPrim(grp.PrimCount); | 510 | RemovePhysicalPrim(grp.PrimCount); |
490 | } | 511 | } |
491 | 512 | ||
513 | bool ret = Entities.Remove(uuid); | ||
514 | |||
492 | lock (SceneObjectGroupsByFullID) | 515 | lock (SceneObjectGroupsByFullID) |
493 | SceneObjectGroupsByFullID.Remove(grp.UUID); | 516 | SceneObjectGroupsByFullID.Remove(grp.UUID); |
494 | 517 | ||
495 | lock (SceneObjectGroupsByFullPartID) | 518 | SceneObjectPart[] parts = grp.Parts; |
519 | for (int i = 0; i < parts.Length; i++) | ||
496 | { | 520 | { |
497 | SceneObjectPart[] parts = grp.Parts; | 521 | lock (SceneObjectGroupsByFullPartID) |
498 | for (int i = 0; i < parts.Length; i++) | ||
499 | SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); | 522 | SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); |
500 | } | ||
501 | 523 | ||
502 | lock (SceneObjectGroupsByLocalPartID) | 524 | lock (SceneObjectGroupsByLocalPartID) |
503 | { | ||
504 | SceneObjectPart[] parts = grp.Parts; | ||
505 | for (int i = 0; i < parts.Length; i++) | ||
506 | SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); | 525 | SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); |
507 | } | 526 | } |
508 | 527 | ||
509 | return Entities.Remove(uuid); | 528 | return ret; |
510 | } | 529 | } |
511 | 530 | ||
512 | /// <summary> | 531 | /// <summary> |
@@ -631,40 +650,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
631 | protected internal ScenePresence CreateAndAddChildScenePresence( | 650 | protected internal ScenePresence CreateAndAddChildScenePresence( |
632 | IClientAPI client, AvatarAppearance appearance, PresenceType type) | 651 | IClientAPI client, AvatarAppearance appearance, PresenceType type) |
633 | { | 652 | { |
634 | ScenePresence newAvatar = null; | ||
635 | |||
636 | // ScenePresence always defaults to child agent | 653 | // ScenePresence always defaults to child agent |
637 | newAvatar = new ScenePresence(client, m_parentScene, appearance, type); | 654 | ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type); |
638 | |||
639 | AddScenePresence(newAvatar); | ||
640 | |||
641 | return newAvatar; | ||
642 | } | ||
643 | |||
644 | /// <summary> | ||
645 | /// Add a presence to the scene | ||
646 | /// </summary> | ||
647 | /// <param name="presence"></param> | ||
648 | protected internal void AddScenePresence(ScenePresence presence) | ||
649 | { | ||
650 | // Always a child when added to the scene | ||
651 | bool child = presence.IsChildAgent; | ||
652 | |||
653 | if (child) | ||
654 | { | ||
655 | m_numChildAgents++; | ||
656 | } | ||
657 | else | ||
658 | { | ||
659 | m_numRootAgents++; | ||
660 | presence.AddToPhysicalScene(false); | ||
661 | } | ||
662 | 655 | ||
663 | Entities[presence.UUID] = presence; | 656 | Entities[presence.UUID] = presence; |
664 | 657 | ||
665 | m_scenePresencesLock.EnterWriteLock(); | 658 | m_scenePresencesLock.EnterWriteLock(); |
666 | try | 659 | try |
667 | { | 660 | { |
661 | m_numChildAgents++; | ||
662 | |||
668 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 663 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
669 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 664 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
670 | 665 | ||
@@ -675,7 +670,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
675 | } | 670 | } |
676 | else | 671 | else |
677 | { | 672 | { |
678 | // Remember the old presene reference from the dictionary | 673 | // Remember the old presence reference from the dictionary |
679 | ScenePresence oldref = newmap[presence.UUID]; | 674 | ScenePresence oldref = newmap[presence.UUID]; |
680 | // Replace the presence reference in the dictionary with the new value | 675 | // Replace the presence reference in the dictionary with the new value |
681 | newmap[presence.UUID] = presence; | 676 | newmap[presence.UUID] = presence; |
@@ -691,6 +686,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
691 | { | 686 | { |
692 | m_scenePresencesLock.ExitWriteLock(); | 687 | m_scenePresencesLock.ExitWriteLock(); |
693 | } | 688 | } |
689 | |||
690 | return presence; | ||
694 | } | 691 | } |
695 | 692 | ||
696 | /// <summary> | 693 | /// <summary> |
@@ -949,7 +946,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
949 | m_log.WarnFormat( | 946 | m_log.WarnFormat( |
950 | "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", | 947 | "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", |
951 | sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); | 948 | sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); |
952 | 949 | m_log.WarnFormat("stack: {0}", Environment.StackTrace); | |
953 | SceneObjectGroupsByLocalPartID.Remove(localID); | 950 | SceneObjectGroupsByLocalPartID.Remove(localID); |
954 | } | 951 | } |
955 | } | 952 | } |
@@ -1569,6 +1566,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1569 | // VolumeDetect can't be set via UI and will always be off when a change is made there | 1566 | // VolumeDetect can't be set via UI and will always be off when a change is made there |
1570 | // now only change volume dtc if phantom off | 1567 | // now only change volume dtc if phantom off |
1571 | 1568 | ||
1569 | bool wantedPhys = UsePhysics; | ||
1572 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data | 1570 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data |
1573 | { | 1571 | { |
1574 | bool vdtc; | 1572 | bool vdtc; |
@@ -1585,10 +1583,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1585 | if (part != null) | 1583 | if (part != null) |
1586 | { | 1584 | { |
1587 | part.UpdateExtraPhysics(PhysData); | 1585 | part.UpdateExtraPhysics(PhysData); |
1588 | if (part.UpdatePhysRequired) | 1586 | if (part.UpdatePhysRequired && remoteClient != null) |
1589 | remoteClient.SendPartPhysicsProprieties(part); | 1587 | remoteClient.SendPartPhysicsProprieties(part); |
1590 | } | 1588 | } |
1591 | } | 1589 | } |
1590 | |||
1591 | if (wantedPhys != group.UsesPhysics && remoteClient != null) | ||
1592 | { | ||
1593 | remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " + | ||
1594 | m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None"); | ||
1595 | group.RootPart.ScheduleFullUpdate(); | ||
1596 | } | ||
1592 | } | 1597 | } |
1593 | } | 1598 | } |
1594 | } | 1599 | } |
@@ -1818,7 +1823,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1818 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1823 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1819 | 1824 | ||
1820 | // We do this in reverse to get the link order of the prims correct | 1825 | // We do this in reverse to get the link order of the prims correct |
1821 | for (int i = 0 ; i < children.Count ; i++) | 1826 | for (int i = 0; i < children.Count; i++) |
1822 | { | 1827 | { |
1823 | SceneObjectGroup child = children[i].ParentGroup; | 1828 | SceneObjectGroup child = children[i].ParentGroup; |
1824 | 1829 | ||
@@ -1829,7 +1834,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1829 | // Make sure no child prim is set for sale | 1834 | // Make sure no child prim is set for sale |
1830 | // So that, on delink, no prims are unwittingly | 1835 | // So that, on delink, no prims are unwittingly |
1831 | // left for sale and sold off | 1836 | // left for sale and sold off |
1832 | 1837 | ||
1833 | if (child != null) | 1838 | if (child != null) |
1834 | { | 1839 | { |
1835 | child.RootPart.ObjectSaleType = 0; | 1840 | child.RootPart.ObjectSaleType = 0; |
@@ -1864,12 +1869,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1864 | } | 1869 | } |
1865 | finally | 1870 | finally |
1866 | { | 1871 | { |
1872 | /* | ||
1867 | lock (SceneObjectGroupsByLocalPartID) | 1873 | lock (SceneObjectGroupsByLocalPartID) |
1868 | { | 1874 | { |
1869 | foreach (SceneObjectPart part in parentGroup.Parts) | 1875 | foreach (SceneObjectPart part in parentGroup.Parts) |
1870 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | 1876 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; |
1871 | } | 1877 | } |
1872 | 1878 | */ | |
1873 | parentGroup.AdjustChildPrimPermissions(); | 1879 | parentGroup.AdjustChildPrimPermissions(); |
1874 | parentGroup.HasGroupChanged = true; | 1880 | parentGroup.HasGroupChanged = true; |
1875 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | 1881 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); |
@@ -1952,20 +1958,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1952 | // slated for unlink, we need to do this | 1958 | // slated for unlink, we need to do this |
1953 | // Unlink the remaining set | 1959 | // Unlink the remaining set |
1954 | // | 1960 | // |
1955 | bool sendEventsToRemainder = true; | 1961 | bool sendEventsToRemainder = false; |
1956 | if (numChildren > 1) | 1962 | if (numChildren == 2) // only one child prim no re-link needed |
1957 | sendEventsToRemainder = false; | 1963 | sendEventsToRemainder = true; |
1958 | 1964 | ||
1959 | foreach (SceneObjectPart p in newSet) | 1965 | foreach (SceneObjectPart p in newSet) |
1960 | { | 1966 | { |
1961 | if (p != group.RootPart) | 1967 | if (p != group.RootPart) |
1962 | { | 1968 | { |
1963 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1969 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1964 | if (numChildren > 2) | 1970 | if (sendEventsToRemainder) // finish single child prim now |
1965 | { | 1971 | { |
1966 | } | ||
1967 | else | ||
1968 | { | ||
1969 | p.ParentGroup.HasGroupChanged = true; | 1972 | p.ParentGroup.HasGroupChanged = true; |
1970 | p.ParentGroup.ScheduleGroupForFullUpdate(); | 1973 | p.ParentGroup.ScheduleGroupForFullUpdate(); |
1971 | } | 1974 | } |
@@ -1998,8 +2001,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1998 | newChild.ClearUpdateSchedule(); | 2001 | newChild.ClearUpdateSchedule(); |
1999 | 2002 | ||
2000 | LinkObjects(newRoot, newSet); | 2003 | LinkObjects(newRoot, newSet); |
2001 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 2004 | // if (!affectedGroups.Contains(newRoot.ParentGroup)) |
2002 | affectedGroups.Add(newRoot.ParentGroup); | 2005 | // affectedGroups.Add(newRoot.ParentGroup); |
2003 | } | 2006 | } |
2004 | } | 2007 | } |
2005 | 2008 | ||
@@ -2126,21 +2129,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2126 | lock (SceneObjectGroupsByFullID) | 2129 | lock (SceneObjectGroupsByFullID) |
2127 | SceneObjectGroupsByFullID[copy.UUID] = copy; | 2130 | SceneObjectGroupsByFullID[copy.UUID] = copy; |
2128 | 2131 | ||
2129 | SceneObjectPart[] children = copy.Parts; | 2132 | SceneObjectPart[] parts = copy.Parts; |
2130 | 2133 | foreach (SceneObjectPart part in parts) | |
2131 | lock (SceneObjectGroupsByFullPartID) | ||
2132 | { | 2134 | { |
2133 | SceneObjectGroupsByFullPartID[copy.UUID] = copy; | 2135 | lock (SceneObjectGroupsByFullPartID) |
2134 | foreach (SceneObjectPart part in children) | ||
2135 | SceneObjectGroupsByFullPartID[part.UUID] = copy; | 2136 | SceneObjectGroupsByFullPartID[part.UUID] = copy; |
2136 | } | 2137 | lock (SceneObjectGroupsByLocalPartID) |
2137 | |||
2138 | lock (SceneObjectGroupsByLocalPartID) | ||
2139 | { | ||
2140 | SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; | ||
2141 | foreach (SceneObjectPart part in children) | ||
2142 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; | 2138 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; |
2143 | } | 2139 | } |
2140 | |||
2144 | // PROBABLE END OF FIXME | 2141 | // PROBABLE END OF FIXME |
2145 | 2142 | ||
2146 | // Since we copy from a source group that is in selected | 2143 | // Since we copy from a source group that is in selected |
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index c70342f..c5c083a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs | |||
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
420 | return false; | 420 | return false; |
421 | } | 421 | } |
422 | 422 | ||
423 | /// <summary> | ||
424 | /// Set the debug packet level on each current scene. This level governs which packets are printed out to the | ||
425 | /// console. | ||
426 | /// </summary> | ||
427 | /// <param name="newDebug"></param> | ||
428 | /// <param name="name">Name of avatar to debug</param> | ||
429 | public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name) | ||
430 | { | ||
431 | ForEachSelectedScene(scene => | ||
432 | scene.ForEachScenePresence(sp => | ||
433 | { | ||
434 | if (name == null || sp.Name == name) | ||
435 | { | ||
436 | m_log.DebugFormat( | ||
437 | "Packet debug for {0} ({1}) set to {2}", | ||
438 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug); | ||
439 | |||
440 | sp.ControllingClient.DebugPacketLevel = newDebug; | ||
441 | } | ||
442 | }) | ||
443 | ); | ||
444 | } | ||
445 | |||
446 | public List<ScenePresence> GetCurrentSceneAvatars() | 423 | public List<ScenePresence> GetCurrentSceneAvatars() |
447 | { | 424 | { |
448 | List<ScenePresence> avatars = new List<ScenePresence>(); | 425 | List<ScenePresence> avatars = new List<ScenePresence>(); |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index f8624e7..8c50a81 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | |||
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
67 | { | 67 | { |
68 | int scriptsStarted = 0; | 68 | int scriptsStarted = 0; |
69 | 69 | ||
70 | if (m_scene == null) | ||
71 | { | ||
72 | m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances"); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
70 | // Don't start scripts if they're turned off in the region! | 76 | // Don't start scripts if they're turned off in the region! |
71 | if (!m_scene.RegionInfo.RegionSettings.DisableScripts) | 77 | if (!m_scene.RegionInfo.RegionSettings.DisableScripts) |
72 | { | 78 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 86f60bb..9a2707b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -111,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
111 | STATUS_ROTATE_Z = 0x008, | 111 | STATUS_ROTATE_Z = 0x008, |
112 | } | 112 | } |
113 | 113 | ||
114 | // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm | ||
115 | public static readonly uint SLAM = 16; | ||
116 | |||
114 | // private PrimCountTaintedDelegate handlerPrimCountTainted = null; | 117 | // private PrimCountTaintedDelegate handlerPrimCountTainted = null; |
115 | 118 | ||
116 | /// <summary> | 119 | /// <summary> |
@@ -506,15 +509,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
506 | { | 509 | { |
507 | return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); | 510 | return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); |
508 | } | 511 | } |
509 | 512 | ||
510 | |||
511 | |||
512 | private struct avtocrossInfo | 513 | private struct avtocrossInfo |
513 | { | 514 | { |
514 | public ScenePresence av; | 515 | public ScenePresence av; |
515 | public uint ParentID; | 516 | public uint ParentID; |
516 | } | 517 | } |
517 | 518 | ||
519 | |||
520 | public bool inTransit = false; | ||
521 | public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos); | ||
522 | |||
518 | /// <summary> | 523 | /// <summary> |
519 | /// The absolute position of this scene object in the scene | 524 | /// The absolute position of this scene object in the scene |
520 | /// </summary> | 525 | /// </summary> |
@@ -524,214 +529,257 @@ namespace OpenSim.Region.Framework.Scenes | |||
524 | set | 529 | set |
525 | { | 530 | { |
526 | Vector3 val = value; | 531 | Vector3 val = value; |
527 | 532 | if (Scene != null && !IsAttachmentCheckFull() | |
528 | if (Scene != null) | 533 | && !Scene.LoadingPrims && |
534 | (Scene.TestBorderCross(val, Cardinals.E) || | ||
535 | Scene.TestBorderCross(val, Cardinals.W) || | ||
536 | Scene.TestBorderCross(val, Cardinals.N) || | ||
537 | Scene.TestBorderCross(val, Cardinals.S)) | ||
538 | ) | ||
529 | { | 539 | { |
530 | if ( | 540 | if (!inTransit) |
531 | // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) | ||
532 | // || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) | ||
533 | // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) | ||
534 | // || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) | ||
535 | // Experimental change for better border crossings. | ||
536 | // The commented out original lines above would, it seems, trigger | ||
537 | // a border crossing a little early or late depending on which | ||
538 | // direction the object was moving. | ||
539 | (Scene.TestBorderCross(val, Cardinals.E) | ||
540 | || Scene.TestBorderCross(val, Cardinals.W) | ||
541 | || Scene.TestBorderCross(val, Cardinals.N) | ||
542 | || Scene.TestBorderCross(val, Cardinals.S)) | ||
543 | && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) | ||
544 | { | 541 | { |
545 | IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 542 | inTransit = true; |
546 | uint x = 0; | 543 | SOGCrossDelegate d = CrossAsync; |
547 | uint y = 0; | 544 | d.BeginInvoke(this, val, CrossAsyncCompleted, d); |
548 | string version = String.Empty; | ||
549 | Vector3 newpos = Vector3.Zero; | ||
550 | OpenSim.Services.Interfaces.GridRegion destination = null; | ||
551 | |||
552 | if (m_rootPart.KeyframeMotion != null) | ||
553 | m_rootPart.KeyframeMotion.StartCrossingCheck(); | ||
554 | |||
555 | bool canCross = true; | ||
556 | foreach (ScenePresence av in m_linkedAvatars) | ||
557 | { | ||
558 | // We need to cross these agents. First, let's find | ||
559 | // out if any of them can't cross for some reason. | ||
560 | // We have to deny the crossing entirely if any | ||
561 | // of them are banned. Alternatively, we could | ||
562 | // unsit banned agents.... | ||
563 | |||
564 | |||
565 | // We set the avatar position as being the object | ||
566 | // position to get the region to send to | ||
567 | if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) | ||
568 | { | ||
569 | canCross = false; | ||
570 | break; | ||
571 | } | ||
572 | |||
573 | m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); | ||
574 | } | ||
575 | |||
576 | if (canCross) | ||
577 | { | ||
578 | // We unparent the SP quietly so that it won't | ||
579 | // be made to stand up | ||
580 | |||
581 | List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); | ||
582 | |||
583 | foreach (ScenePresence av in m_linkedAvatars) | ||
584 | { | ||
585 | avtocrossInfo avinfo = new avtocrossInfo(); | ||
586 | SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); | ||
587 | if (parentPart != null) | ||
588 | av.ParentUUID = parentPart.UUID; | ||
589 | |||
590 | avinfo.av = av; | ||
591 | avinfo.ParentID = av.ParentID; | ||
592 | avsToCross.Add(avinfo); | ||
593 | |||
594 | av.PrevSitOffset = av.OffsetPosition; | ||
595 | av.ParentID = 0; | ||
596 | } | ||
597 | |||
598 | // m_linkedAvatars.Clear(); | ||
599 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | ||
600 | |||
601 | // Normalize | ||
602 | if (val.X >= Constants.RegionSize) | ||
603 | val.X -= Constants.RegionSize; | ||
604 | if (val.Y >= Constants.RegionSize) | ||
605 | val.Y -= Constants.RegionSize; | ||
606 | if (val.X < 0) | ||
607 | val.X += Constants.RegionSize; | ||
608 | if (val.Y < 0) | ||
609 | val.Y += Constants.RegionSize; | ||
610 | |||
611 | // If it's deleted, crossing was successful | ||
612 | if (IsDeleted) | ||
613 | { | ||
614 | // foreach (ScenePresence av in m_linkedAvatars) | ||
615 | foreach (avtocrossInfo avinfo in avsToCross) | ||
616 | { | ||
617 | ScenePresence av = avinfo.av; | ||
618 | if (!av.IsInTransit) // just in case... | ||
619 | { | ||
620 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); | ||
621 | |||
622 | av.IsInTransit = true; | ||
623 | |||
624 | CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | ||
625 | d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | ||
626 | } | ||
627 | else | ||
628 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); | ||
629 | } | ||
630 | avsToCross.Clear(); | ||
631 | return; | ||
632 | } | ||
633 | else // cross failed, put avas back ?? | ||
634 | { | ||
635 | foreach (avtocrossInfo avinfo in avsToCross) | ||
636 | { | ||
637 | ScenePresence av = avinfo.av; | ||
638 | av.ParentUUID = UUID.Zero; | ||
639 | av.ParentID = avinfo.ParentID; | ||
640 | // m_linkedAvatars.Add(av); | ||
641 | } | ||
642 | } | ||
643 | avsToCross.Clear(); | ||
644 | |||
645 | } | ||
646 | else | ||
647 | { | ||
648 | if (m_rootPart.KeyframeMotion != null) | ||
649 | m_rootPart.KeyframeMotion.CrossingFailure(); | ||
650 | |||
651 | if (RootPart.PhysActor != null) | ||
652 | { | ||
653 | RootPart.PhysActor.CrossingFailure(); | ||
654 | } | ||
655 | } | ||
656 | Vector3 oldp = AbsolutePosition; | ||
657 | val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); | ||
658 | val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); | ||
659 | val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f); | ||
660 | } | 545 | } |
546 | return; | ||
661 | } | 547 | } |
662 | 548 | ||
663 | /* don't see the need but worse don't see where is restored to false if things stay in | ||
664 | foreach (SceneObjectPart part in m_parts.GetArray()) | ||
665 | { | ||
666 | part.IgnoreUndoUpdate = true; | ||
667 | } | ||
668 | */ | ||
669 | if (RootPart.GetStatusSandbox()) | 549 | if (RootPart.GetStatusSandbox()) |
670 | { | 550 | { |
671 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 551 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
672 | { | 552 | { |
673 | RootPart.ScriptSetPhysicsStatus(false); | 553 | RootPart.ScriptSetPhysicsStatus(false); |
674 | 554 | ||
675 | if (Scene != null) | 555 | if (Scene != null) |
676 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | 556 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), |
677 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); | 557 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); |
678 | 558 | ||
679 | return; | 559 | return; |
680 | } | 560 | } |
681 | } | 561 | } |
682 | 562 | ||
683 | // Restuff the new GroupPosition into each SOP of the linkset. | ||
684 | // This has the affect of resetting and tainting the physics actors. | ||
685 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
686 | bool triggerScriptEvent = m_rootPart.GroupPosition != val; | 563 | bool triggerScriptEvent = m_rootPart.GroupPosition != val; |
687 | if (m_dupeInProgress) | 564 | if (m_dupeInProgress || IsDeleted) |
688 | triggerScriptEvent = false; | 565 | triggerScriptEvent = false; |
566 | |||
567 | m_rootPart.GroupPosition = val; | ||
568 | |||
569 | // Restuff the new GroupPosition into each child SOP of the linkset. | ||
570 | // this is needed because physics may not have linksets but just loose SOPs in world | ||
571 | |||
572 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
573 | |||
689 | foreach (SceneObjectPart part in parts) | 574 | foreach (SceneObjectPart part in parts) |
690 | { | 575 | { |
691 | part.GroupPosition = val; | 576 | if (part != m_rootPart) |
692 | if (triggerScriptEvent) | 577 | part.GroupPosition = val; |
578 | } | ||
579 | |||
580 | foreach (ScenePresence av in m_linkedAvatars) | ||
581 | { | ||
582 | av.sitSOGmoved(); | ||
583 | } | ||
584 | |||
585 | |||
586 | // now that position is changed tell it to scripts | ||
587 | if (triggerScriptEvent) | ||
588 | { | ||
589 | foreach (SceneObjectPart part in parts) | ||
590 | { | ||
693 | part.TriggerScriptChangedEvent(Changed.POSITION); | 591 | part.TriggerScriptChangedEvent(Changed.POSITION); |
592 | } | ||
694 | } | 593 | } |
695 | 594 | ||
696 | /* | 595 | if (Scene != null) |
697 | This seems not needed and should not be needed: | 596 | Scene.EventManager.TriggerParcelPrimCountTainted(); |
698 | sp absolute position depends on sit part absolute position fixed above. | 597 | |
699 | sp ParentPosition is not used anywhere. | 598 | } |
700 | Since presence is sitting, viewer considers it 'linked' to root prim, so it will move/rotate it | 599 | } |
701 | Sending a extra packet with avatar position is not only bandwidth waste, but may cause jitter in viewers due to UPD nature. | 600 | |
702 | 601 | public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val) | |
703 | if (!m_dupeInProgress) | 602 | { |
603 | Scene sogScene = sog.m_scene; | ||
604 | IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>(); | ||
605 | |||
606 | Vector3 newpos = Vector3.Zero; | ||
607 | OpenSim.Services.Interfaces.GridRegion destination = null; | ||
608 | |||
609 | if (sog.RootPart.DIE_AT_EDGE) | ||
610 | { | ||
611 | try | ||
612 | { | ||
613 | sogScene.DeleteSceneObject(sog, false); | ||
614 | } | ||
615 | catch (Exception) | ||
616 | { | ||
617 | m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); | ||
618 | } | ||
619 | return sog; | ||
620 | } | ||
621 | |||
622 | if (sog.RootPart.RETURN_AT_EDGE) | ||
623 | { | ||
624 | // We remove the object here | ||
625 | try | ||
626 | { | ||
627 | List<uint> localIDs = new List<uint>(); | ||
628 | localIDs.Add(sog.RootPart.LocalId); | ||
629 | sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition, | ||
630 | "Returned at region cross"); | ||
631 | sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero); | ||
632 | } | ||
633 | catch (Exception) | ||
704 | { | 634 | { |
705 | foreach (ScenePresence av in m_linkedAvatars) | 635 | m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); |
636 | } | ||
637 | return sog; | ||
638 | } | ||
639 | |||
640 | if (sog.m_rootPart.KeyframeMotion != null) | ||
641 | sog.m_rootPart.KeyframeMotion.StartCrossingCheck(); | ||
642 | |||
643 | if (entityTransfer == null) | ||
644 | return sog; | ||
645 | |||
646 | destination = entityTransfer.GetObjectDestination(sog, val, out newpos); | ||
647 | if (destination == null) | ||
648 | return sog; | ||
649 | |||
650 | if (sog.m_linkedAvatars.Count == 0) | ||
651 | { | ||
652 | entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true); | ||
653 | return sog; | ||
654 | } | ||
655 | |||
656 | string reason = String.Empty; | ||
657 | string version = String.Empty; | ||
658 | |||
659 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
660 | { | ||
661 | // We need to cross these agents. First, let's find | ||
662 | // out if any of them can't cross for some reason. | ||
663 | // We have to deny the crossing entirely if any | ||
664 | // of them are banned. Alternatively, we could | ||
665 | // unsit banned agents.... | ||
666 | |||
667 | // We set the avatar position as being the object | ||
668 | // position to get the region to send to | ||
669 | if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason)) | ||
670 | { | ||
671 | return sog; | ||
672 | } | ||
673 | m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); | ||
674 | } | ||
675 | |||
676 | // We unparent the SP quietly so that it won't | ||
677 | // be made to stand up | ||
678 | |||
679 | List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); | ||
680 | |||
681 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
682 | { | ||
683 | avtocrossInfo avinfo = new avtocrossInfo(); | ||
684 | SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID); | ||
685 | if (parentPart != null) | ||
686 | av.ParentUUID = parentPart.UUID; | ||
687 | |||
688 | avinfo.av = av; | ||
689 | avinfo.ParentID = av.ParentID; | ||
690 | avsToCross.Add(avinfo); | ||
691 | |||
692 | av.PrevSitOffset = av.OffsetPosition; | ||
693 | av.ParentID = 0; | ||
694 | } | ||
695 | |||
696 | if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true)) | ||
697 | { | ||
698 | foreach (avtocrossInfo avinfo in avsToCross) | ||
699 | { | ||
700 | ScenePresence av = avinfo.av; | ||
701 | if (!av.IsInTransit) // just in case... | ||
706 | { | 702 | { |
707 | SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID); | 703 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); |
708 | if (p != null && m_parts.TryGetValue(p.UUID, out p)) | 704 | |
705 | av.IsInTransit = true; | ||
706 | |||
707 | // CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | ||
708 | // d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | ||
709 | entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version); | ||
710 | if(av.IsChildAgent) | ||
709 | { | 711 | { |
710 | Vector3 offset = p.GetWorldPosition() - av.ParentPosition; | 712 | if (av.ParentUUID != UUID.Zero) |
711 | av.AbsolutePosition += offset; | 713 | { |
712 | // av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition | 714 | av.ClearControls(); |
713 | av.SendAvatarDataToAllAgents(); | 715 | av.ParentPart = null; |
716 | } | ||
714 | } | 717 | } |
718 | av.ParentUUID = UUID.Zero; | ||
719 | // In any case | ||
720 | av.IsInTransit = false; | ||
721 | |||
722 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); | ||
715 | } | 723 | } |
724 | else | ||
725 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val); | ||
726 | } | ||
727 | avsToCross.Clear(); | ||
728 | return sog; | ||
729 | } | ||
730 | else // cross failed, put avas back ?? | ||
731 | { | ||
732 | foreach (avtocrossInfo avinfo in avsToCross) | ||
733 | { | ||
734 | ScenePresence av = avinfo.av; | ||
735 | av.ParentUUID = UUID.Zero; | ||
736 | av.ParentID = avinfo.ParentID; | ||
716 | } | 737 | } |
717 | */ | ||
718 | //if (m_rootPart.PhysActor != null) | ||
719 | //{ | ||
720 | //m_rootPart.PhysActor.Position = | ||
721 | //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, | ||
722 | //m_rootPart.GroupPosition.Z); | ||
723 | //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | ||
724 | //} | ||
725 | |||
726 | if (Scene != null) | ||
727 | Scene.EventManager.TriggerParcelPrimCountTainted(); | ||
728 | } | 738 | } |
739 | avsToCross.Clear(); | ||
740 | |||
741 | return sog; | ||
729 | } | 742 | } |
730 | 743 | ||
731 | public override Vector3 Velocity | 744 | public void CrossAsyncCompleted(IAsyncResult iar) |
732 | { | 745 | { |
733 | get { return RootPart.Velocity; } | 746 | SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState; |
734 | set { RootPart.Velocity = value; } | 747 | SceneObjectGroup sog = icon.EndInvoke(iar); |
748 | |||
749 | if (!sog.IsDeleted) | ||
750 | { | ||
751 | SceneObjectPart rootp = sog.m_rootPart; | ||
752 | Vector3 oldp = rootp.GroupPosition; | ||
753 | oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); | ||
754 | oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); | ||
755 | rootp.GroupPosition = oldp; | ||
756 | |||
757 | SceneObjectPart[] parts = sog.m_parts.GetArray(); | ||
758 | |||
759 | foreach (SceneObjectPart part in parts) | ||
760 | { | ||
761 | if (part != rootp) | ||
762 | part.GroupPosition = oldp; | ||
763 | } | ||
764 | |||
765 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
766 | { | ||
767 | av.sitSOGmoved(); | ||
768 | } | ||
769 | |||
770 | sog.Velocity = Vector3.Zero; | ||
771 | |||
772 | if (sog.m_rootPart.KeyframeMotion != null) | ||
773 | sog.m_rootPart.KeyframeMotion.CrossingFailure(); | ||
774 | |||
775 | if (sog.RootPart.PhysActor != null) | ||
776 | { | ||
777 | sog.RootPart.PhysActor.CrossingFailure(); | ||
778 | } | ||
779 | |||
780 | sog.inTransit = false; | ||
781 | sog.ScheduleGroupForFullUpdate(); | ||
782 | } | ||
735 | } | 783 | } |
736 | 784 | ||
737 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) | 785 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) |
@@ -744,6 +792,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
744 | { | 792 | { |
745 | if (agent.ParentUUID != UUID.Zero) | 793 | if (agent.ParentUUID != UUID.Zero) |
746 | { | 794 | { |
795 | agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID); | ||
747 | agent.ParentPart = null; | 796 | agent.ParentPart = null; |
748 | // agent.ParentPosition = Vector3.Zero; | 797 | // agent.ParentPosition = Vector3.Zero; |
749 | // agent.ParentUUID = UUID.Zero; | 798 | // agent.ParentUUID = UUID.Zero; |
@@ -751,7 +800,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
751 | } | 800 | } |
752 | 801 | ||
753 | agent.ParentUUID = UUID.Zero; | 802 | agent.ParentUUID = UUID.Zero; |
754 | |||
755 | // agent.Reset(); | 803 | // agent.Reset(); |
756 | // else // Not successful | 804 | // else // Not successful |
757 | // agent.RestoreInCurrentScene(); | 805 | // agent.RestoreInCurrentScene(); |
@@ -762,6 +810,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
762 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); | 810 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); |
763 | } | 811 | } |
764 | 812 | ||
813 | public override Vector3 Velocity | ||
814 | { | ||
815 | get { return RootPart.Velocity; } | ||
816 | set { RootPart.Velocity = value; } | ||
817 | } | ||
818 | |||
765 | public override uint LocalId | 819 | public override uint LocalId |
766 | { | 820 | { |
767 | get { return m_rootPart.LocalId; } | 821 | get { return m_rootPart.LocalId; } |
@@ -885,20 +939,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
885 | return; | 939 | return; |
886 | } | 940 | } |
887 | IsSelected = partSelect; | 941 | IsSelected = partSelect; |
888 | if (!IsAttachment) | 942 | // if (!IsAttachment) |
889 | { | 943 | // { |
890 | ScheduleGroupForFullUpdate(); | 944 | // ScheduleGroupForFullUpdate(); |
891 | } | 945 | // } |
892 | } | 946 | } |
893 | } | 947 | } |
894 | 948 | // PlaySoundMasterPrim no longer in use to remove | |
895 | private SceneObjectPart m_PlaySoundMasterPrim = null; | 949 | private SceneObjectPart m_PlaySoundMasterPrim = null; |
896 | public SceneObjectPart PlaySoundMasterPrim | 950 | public SceneObjectPart PlaySoundMasterPrim |
897 | { | 951 | { |
898 | get { return m_PlaySoundMasterPrim; } | 952 | get { return m_PlaySoundMasterPrim; } |
899 | set { m_PlaySoundMasterPrim = value; } | 953 | set { m_PlaySoundMasterPrim = value; } |
900 | } | 954 | } |
901 | 955 | // PlaySoundSlavePrims no longer in use to remove | |
902 | private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); | 956 | private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); |
903 | public List<SceneObjectPart> PlaySoundSlavePrims | 957 | public List<SceneObjectPart> PlaySoundSlavePrims |
904 | { | 958 | { |
@@ -906,6 +960,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
906 | set { m_PlaySoundSlavePrims = value; } | 960 | set { m_PlaySoundSlavePrims = value; } |
907 | } | 961 | } |
908 | 962 | ||
963 | // LoopSoundMasterPrim no longer in use to remove | ||
909 | private SceneObjectPart m_LoopSoundMasterPrim = null; | 964 | private SceneObjectPart m_LoopSoundMasterPrim = null; |
910 | public SceneObjectPart LoopSoundMasterPrim | 965 | public SceneObjectPart LoopSoundMasterPrim |
911 | { | 966 | { |
@@ -913,6 +968,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
913 | set { m_LoopSoundMasterPrim = value; } | 968 | set { m_LoopSoundMasterPrim = value; } |
914 | } | 969 | } |
915 | 970 | ||
971 | // m_LoopSoundSlavePrims no longer in use to remove | ||
916 | private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); | 972 | private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); |
917 | public List<SceneObjectPart> LoopSoundSlavePrims | 973 | public List<SceneObjectPart> LoopSoundSlavePrims |
918 | { | 974 | { |
@@ -1667,7 +1723,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1667 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); | 1723 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); |
1668 | if (avatar == null) | 1724 | if (avatar == null) |
1669 | return; | 1725 | return; |
1670 | 1726 | m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State; | |
1727 | m_rootPart.AttachedPos = m_rootPart.OffsetPosition; | ||
1671 | avatar.RemoveAttachment(this); | 1728 | avatar.RemoveAttachment(this); |
1672 | 1729 | ||
1673 | Vector3 detachedpos = new Vector3(127f,127f,127f); | 1730 | Vector3 detachedpos = new Vector3(127f,127f,127f); |
@@ -1687,7 +1744,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1687 | m_rootPart.SetParentLocalId(0); | 1744 | m_rootPart.SetParentLocalId(0); |
1688 | AttachmentPoint = (byte)0; | 1745 | AttachmentPoint = (byte)0; |
1689 | // must check if buildind should be true or false here | 1746 | // must check if buildind should be true or false here |
1690 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false); | 1747 | // m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false); |
1748 | ApplyPhysics(); | ||
1749 | |||
1691 | HasGroupChanged = true; | 1750 | HasGroupChanged = true; |
1692 | RootPart.Rezzed = DateTime.Now; | 1751 | RootPart.Rezzed = DateTime.Now; |
1693 | RootPart.RemFlag(PrimFlags.TemporaryOnRez); | 1752 | RootPart.RemFlag(PrimFlags.TemporaryOnRez); |
@@ -1820,11 +1879,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
1820 | // Setting this SOG's absolute position also loops through and sets the positions | 1879 | // Setting this SOG's absolute position also loops through and sets the positions |
1821 | // of the SOP's in this SOG's linkset. This has the side affect of making sure | 1880 | // of the SOP's in this SOG's linkset. This has the side affect of making sure |
1822 | // the physics world matches the simulated world. | 1881 | // the physics world matches the simulated world. |
1823 | AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? | 1882 | // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? |
1824 | 1883 | ||
1825 | // teravus: AbsolutePosition is NOT a normal property! | 1884 | // teravus: AbsolutePosition is NOT a normal property! |
1826 | // the code in the getter of AbsolutePosition is significantly different then the code in the setter! | 1885 | // the code in the getter of AbsolutePosition is significantly different then the code in the setter! |
1827 | // jhurliman: Then why is it a property instead of two methods? | 1886 | // jhurliman: Then why is it a property instead of two methods? |
1887 | |||
1888 | // do only what is supposed to do | ||
1889 | Vector3 groupPosition = m_rootPart.GroupPosition; | ||
1890 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
1891 | |||
1892 | foreach (SceneObjectPart part in parts) | ||
1893 | { | ||
1894 | if (part != m_rootPart) | ||
1895 | part.GroupPosition = groupPosition; | ||
1896 | } | ||
1828 | } | 1897 | } |
1829 | 1898 | ||
1830 | public UUID GetPartsFullID(uint localID) | 1899 | public UUID GetPartsFullID(uint localID) |
@@ -1868,11 +1937,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1868 | /// <summary> | 1937 | /// <summary> |
1869 | /// Delete this group from its scene. | 1938 | /// Delete this group from its scene. |
1870 | /// </summary> | 1939 | /// </summary> |
1871 | /// | 1940 | /// <remarks> |
1872 | /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood | 1941 | /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood |
1873 | /// up and all avatars receive notification of its removal. Removal of the scene object from database backup | 1942 | /// up and all avatars receive notification of its removal. Removal of the scene object from database backup |
1874 | /// must be handled by the caller. | 1943 | /// must be handled by the caller. |
1875 | /// | 1944 | /// </remarks> |
1876 | /// <param name="silent">If true then deletion is not broadcast to clients</param> | 1945 | /// <param name="silent">If true then deletion is not broadcast to clients</param> |
1877 | public void DeleteGroupFromScene(bool silent) | 1946 | public void DeleteGroupFromScene(bool silent) |
1878 | { | 1947 | { |
@@ -1901,7 +1970,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1901 | if (!IsAttachment | 1970 | if (!IsAttachment |
1902 | || AttachedAvatar == avatar.ControllingClient.AgentId | 1971 | || AttachedAvatar == avatar.ControllingClient.AgentId |
1903 | || !HasPrivateAttachmentPoint) | 1972 | || !HasPrivateAttachmentPoint) |
1904 | avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); | 1973 | avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); |
1905 | } | 1974 | } |
1906 | } | 1975 | } |
1907 | }); | 1976 | }); |
@@ -2037,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2037 | return; | 2106 | return; |
2038 | } | 2107 | } |
2039 | 2108 | ||
2040 | if (IsDeleted || UUID == UUID.Zero) | 2109 | if (IsDeleted || inTransit || UUID == UUID.Zero) |
2041 | { | 2110 | { |
2042 | // m_log.DebugFormat( | 2111 | // m_log.DebugFormat( |
2043 | // "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); | 2112 | // "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); |
@@ -2109,6 +2178,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2109 | 2178 | ||
2110 | if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) | 2179 | if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) |
2111 | { | 2180 | { |
2181 | RootPart.Shape.LastAttachPoint = RootPart.Shape.State; | ||
2112 | RootPart.Shape.State = 0; | 2182 | RootPart.Shape.State = 0; |
2113 | ScheduleGroupForFullUpdate(); | 2183 | ScheduleGroupForFullUpdate(); |
2114 | } | 2184 | } |
@@ -2122,23 +2192,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
2122 | HasGroupChangedDueToDelink = false; | 2192 | HasGroupChangedDueToDelink = false; |
2123 | 2193 | ||
2124 | m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); | 2194 | m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); |
2125 | /* | 2195 | |
2126 | backup_group.ForEachPart(delegate(SceneObjectPart part) | ||
2127 | { | ||
2128 | if (part.KeyframeMotion != null) | ||
2129 | { | ||
2130 | part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); | ||
2131 | // part.KeyframeMotion.UpdateSceneObject(this); | ||
2132 | } | ||
2133 | }); | ||
2134 | */ | ||
2135 | datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); | 2196 | datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); |
2136 | 2197 | ||
2137 | backup_group.ForEachPart(delegate(SceneObjectPart part) | 2198 | backup_group.ForEachPart(delegate(SceneObjectPart part) |
2138 | { | 2199 | { |
2139 | part.Inventory.ProcessInventoryBackup(datastore); | 2200 | part.Inventory.ProcessInventoryBackup(datastore); |
2201 | |||
2202 | // take the change to delete things | ||
2203 | if(part.KeyframeMotion != null) | ||
2204 | { | ||
2205 | part.KeyframeMotion.Delete(); | ||
2206 | part.KeyframeMotion = null; | ||
2207 | } | ||
2140 | }); | 2208 | }); |
2141 | 2209 | ||
2210 | |||
2142 | backup_group = null; | 2211 | backup_group = null; |
2143 | } | 2212 | } |
2144 | // else | 2213 | // else |
@@ -2193,29 +2262,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2193 | dupe.m_isBackedUp = false; | 2262 | dupe.m_isBackedUp = false; |
2194 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | 2263 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); |
2195 | 2264 | ||
2265 | dupe.inTransit = inTransit; // this shouldn't be needed TEST | ||
2266 | |||
2196 | // new group as no sitting avatars | 2267 | // new group as no sitting avatars |
2197 | dupe.m_linkedAvatars = new List<ScenePresence>(); | 2268 | dupe.m_linkedAvatars = new List<ScenePresence>(); |
2198 | 2269 | dupe.m_sittingAvatars = new List<UUID>(); | |
2199 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of | ||
2200 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | ||
2201 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! | ||
2202 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state | ||
2203 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, | ||
2204 | // then restore it's attachment state | ||
2205 | |||
2206 | // This is only necessary when userExposed is false! | ||
2207 | |||
2208 | bool previousAttachmentStatus = dupe.IsAttachment; | ||
2209 | |||
2210 | if (!userExposed) | ||
2211 | dupe.IsAttachment = true; | ||
2212 | |||
2213 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); | ||
2214 | |||
2215 | if (!userExposed) | ||
2216 | { | ||
2217 | dupe.IsAttachment = previousAttachmentStatus; | ||
2218 | } | ||
2219 | 2270 | ||
2220 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 2271 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
2221 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 2272 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
@@ -2239,7 +2290,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2239 | { | 2290 | { |
2240 | newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); | 2291 | newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); |
2241 | newPart.LinkNum = part.LinkNum; | 2292 | newPart.LinkNum = part.LinkNum; |
2242 | if (userExposed) | 2293 | // if (userExposed) |
2243 | newPart.ParentID = dupe.m_rootPart.LocalId; | 2294 | newPart.ParentID = dupe.m_rootPart.LocalId; |
2244 | } | 2295 | } |
2245 | else | 2296 | else |
@@ -2300,10 +2351,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2300 | /// <param name="cGroupID"></param> | 2351 | /// <param name="cGroupID"></param> |
2301 | public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2352 | public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
2302 | { | 2353 | { |
2303 | // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); | 2354 | SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed); |
2304 | // give newpart a new local ID lettng old part keep same | 2355 | // SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed); |
2305 | SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed); | 2356 | // newpart.LocalId = m_scene.AllocateLocalId(); |
2306 | newpart.LocalId = m_scene.AllocateLocalId(); | ||
2307 | 2357 | ||
2308 | SetRootPart(newpart); | 2358 | SetRootPart(newpart); |
2309 | if (userExposed) | 2359 | if (userExposed) |
@@ -2522,11 +2572,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2522 | /// <param name="cGroupID"></param> | 2572 | /// <param name="cGroupID"></param> |
2523 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2573 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
2524 | { | 2574 | { |
2525 | // give new ID to the new part, letting old keep original | 2575 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
2526 | // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2576 | // SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed); |
2527 | SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed); | 2577 | // newPart.LocalId = m_scene.AllocateLocalId(); |
2528 | newPart.LocalId = m_scene.AllocateLocalId(); | ||
2529 | newPart.SetParent(this); | ||
2530 | 2578 | ||
2531 | AddPart(newPart); | 2579 | AddPart(newPart); |
2532 | 2580 | ||
@@ -2585,7 +2633,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2585 | // an object has been deleted from a scene before update was processed. | 2633 | // an object has been deleted from a scene before update was processed. |
2586 | // A more fundamental overhaul of the update mechanism is required to eliminate all | 2634 | // A more fundamental overhaul of the update mechanism is required to eliminate all |
2587 | // the race conditions. | 2635 | // the race conditions. |
2588 | if (IsDeleted) | 2636 | if (IsDeleted || inTransit) |
2589 | return; | 2637 | return; |
2590 | 2638 | ||
2591 | // Even temporary objects take part in physics (e.g. temp-on-rez bullets) | 2639 | // Even temporary objects take part in physics (e.g. temp-on-rez bullets) |
@@ -2600,6 +2648,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2600 | m_rootPart.UpdateFlag = UpdateRequired.TERSE; | 2648 | m_rootPart.UpdateFlag = UpdateRequired.TERSE; |
2601 | } | 2649 | } |
2602 | 2650 | ||
2651 | if (IsAttachment) | ||
2652 | { | ||
2653 | ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); | ||
2654 | if (sp != null) | ||
2655 | { | ||
2656 | sp.SendAttachmentScheduleUpdate(this); | ||
2657 | return; | ||
2658 | } | ||
2659 | } | ||
2660 | |||
2603 | SceneObjectPart[] parts = m_parts.GetArray(); | 2661 | SceneObjectPart[] parts = m_parts.GetArray(); |
2604 | for (int i = 0; i < parts.Length; i++) | 2662 | for (int i = 0; i < parts.Length; i++) |
2605 | { | 2663 | { |
@@ -2661,15 +2719,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
2661 | return; | 2719 | return; |
2662 | 2720 | ||
2663 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 2721 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
2664 | 2722 | ||
2665 | RootPart.SendFullUpdateToAllClients(); | 2723 | if (IsAttachment) |
2724 | { | ||
2725 | ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); | ||
2726 | if (sp != null) | ||
2727 | { | ||
2728 | sp.SendAttachmentUpdate(this,UpdateRequired.FULL); | ||
2729 | return; | ||
2730 | } | ||
2731 | } | ||
2732 | |||
2733 | RootPart.SendFullUpdateToAllClientsInternal(); | ||
2666 | 2734 | ||
2667 | SceneObjectPart[] parts = m_parts.GetArray(); | 2735 | SceneObjectPart[] parts = m_parts.GetArray(); |
2668 | for (int i = 0; i < parts.Length; i++) | 2736 | for (int i = 0; i < parts.Length; i++) |
2669 | { | 2737 | { |
2670 | SceneObjectPart part = parts[i]; | 2738 | SceneObjectPart part = parts[i]; |
2671 | if (part != RootPart) | 2739 | if (part != RootPart) |
2672 | part.SendFullUpdateToAllClients(); | 2740 | part.SendFullUpdateToAllClientsInternal(); |
2673 | } | 2741 | } |
2674 | } | 2742 | } |
2675 | 2743 | ||
@@ -2681,7 +2749,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2681 | /// </summary> | 2749 | /// </summary> |
2682 | public void SendGroupRootTerseUpdate() | 2750 | public void SendGroupRootTerseUpdate() |
2683 | { | 2751 | { |
2684 | if (IsDeleted) | 2752 | if (IsDeleted || inTransit) |
2685 | return; | 2753 | return; |
2686 | 2754 | ||
2687 | RootPart.SendTerseUpdateToAllClients(); | 2755 | RootPart.SendTerseUpdateToAllClients(); |
@@ -2700,12 +2768,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
2700 | /// </summary> | 2768 | /// </summary> |
2701 | public void SendGroupTerseUpdate() | 2769 | public void SendGroupTerseUpdate() |
2702 | { | 2770 | { |
2703 | if (IsDeleted) | 2771 | if (IsDeleted || inTransit) |
2704 | return; | 2772 | return; |
2705 | 2773 | ||
2774 | if (IsAttachment) | ||
2775 | { | ||
2776 | ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); | ||
2777 | if (sp != null) | ||
2778 | { | ||
2779 | sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); | ||
2780 | return; | ||
2781 | } | ||
2782 | } | ||
2783 | |||
2706 | SceneObjectPart[] parts = m_parts.GetArray(); | 2784 | SceneObjectPart[] parts = m_parts.GetArray(); |
2707 | for (int i = 0; i < parts.Length; i++) | 2785 | for (int i = 0; i < parts.Length; i++) |
2708 | parts[i].SendTerseUpdateToAllClients(); | 2786 | parts[i].SendTerseUpdateToAllClientsInternal(); |
2709 | } | 2787 | } |
2710 | 2788 | ||
2711 | /// <summary> | 2789 | /// <summary> |
@@ -2813,6 +2891,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
2813 | return; | 2891 | return; |
2814 | } | 2892 | } |
2815 | 2893 | ||
2894 | // physical prims count limit | ||
2895 | // not very eficient :( | ||
2896 | |||
2897 | if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) > | ||
2898 | m_scene.m_linksetPhysCapacity) | ||
2899 | { | ||
2900 | int cntr = 0; | ||
2901 | foreach (SceneObjectPart part in Parts) | ||
2902 | { | ||
2903 | if (part.PhysicsShapeType != (byte)PhysicsShapeType.None) | ||
2904 | cntr++; | ||
2905 | } | ||
2906 | foreach (SceneObjectPart part in objectGroup.Parts) | ||
2907 | { | ||
2908 | if (part.PhysicsShapeType != (byte)PhysicsShapeType.None) | ||
2909 | cntr++; | ||
2910 | } | ||
2911 | |||
2912 | if (cntr > m_scene.m_linksetPhysCapacity) | ||
2913 | { | ||
2914 | // cancel physics | ||
2915 | RootPart.Flags &= ~PrimFlags.Physics; | ||
2916 | ApplyPhysics(); | ||
2917 | } | ||
2918 | } | ||
2919 | |||
2920 | |||
2816 | // 'linkPart' == the root of the group being linked into this group | 2921 | // 'linkPart' == the root of the group being linked into this group |
2817 | SceneObjectPart linkPart = objectGroup.m_rootPart; | 2922 | SceneObjectPart linkPart = objectGroup.m_rootPart; |
2818 | 2923 | ||
@@ -2837,22 +2942,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2837 | // First move the new group's root SOP's position to be relative to ours | 2942 | // First move the new group's root SOP's position to be relative to ours |
2838 | // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, | 2943 | // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, |
2839 | // this code can be reordered to have a more logical flow.) | 2944 | // this code can be reordered to have a more logical flow.) |
2840 | linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; | 2945 | linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition); |
2841 | // Assign the new parent to the root of the old group | 2946 | // Assign the new parent to the root of the old group |
2842 | linkPart.ParentID = m_rootPart.LocalId; | 2947 | linkPart.ParentID = m_rootPart.LocalId; |
2843 | // Now that it's a child, it's group position is our root position | 2948 | // Now that it's a child, it's group position is our root position |
2844 | linkPart.GroupPosition = AbsolutePosition; | 2949 | linkPart.setGroupPosition(AbsolutePosition); |
2845 | 2950 | ||
2846 | Vector3 axPos = linkPart.OffsetPosition; | ||
2847 | // Rotate the linking root SOP's position to be relative to the new root prim | 2951 | // Rotate the linking root SOP's position to be relative to the new root prim |
2848 | Quaternion parentRot = m_rootPart.RotationOffset; | 2952 | Quaternion parentRot = m_rootPart.RotationOffset; |
2849 | axPos *= Quaternion.Conjugate(parentRot); | ||
2850 | linkPart.OffsetPosition = axPos; | ||
2851 | 2953 | ||
2852 | // Make the linking root SOP's rotation relative to the new root prim | 2954 | // Make the linking root SOP's rotation relative to the new root prim |
2853 | Quaternion oldRot = linkPart.RotationOffset; | 2955 | Quaternion oldRot = linkPart.RotationOffset; |
2854 | Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot; | 2956 | Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot; |
2855 | linkPart.RotationOffset = newRot; | 2957 | linkPart.setRotationOffset(newRot); |
2958 | |||
2959 | Vector3 axPos = linkPart.OffsetPosition; | ||
2960 | axPos *= Quaternion.Conjugate(parentRot); | ||
2961 | linkPart.OffsetPosition = axPos; | ||
2962 | |||
2856 | 2963 | ||
2857 | // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. | 2964 | // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. |
2858 | // Now that we know this SOG has at least two SOPs in it, the new root | 2965 | // Now that we know this SOG has at least two SOPs in it, the new root |
@@ -2882,6 +2989,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2882 | m_parts.Add(linkPart.UUID, linkPart); | 2989 | m_parts.Add(linkPart.UUID, linkPart); |
2883 | 2990 | ||
2884 | linkPart.SetParent(this); | 2991 | linkPart.SetParent(this); |
2992 | m_scene.updateScenePartGroup(linkPart, this); | ||
2993 | |||
2885 | linkPart.CreateSelected = true; | 2994 | linkPart.CreateSelected = true; |
2886 | 2995 | ||
2887 | // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now | 2996 | // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now |
@@ -3074,18 +3183,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
3074 | linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; | 3183 | linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; |
3075 | linkPart.OffsetPosition = new Vector3(0, 0, 0); | 3184 | linkPart.OffsetPosition = new Vector3(0, 0, 0); |
3076 | */ | 3185 | */ |
3077 | linkPart.GroupPosition = worldPos; | 3186 | linkPart.setGroupPosition(worldPos); |
3078 | linkPart.OffsetPosition = Vector3.Zero; | 3187 | linkPart.setOffsetPosition(Vector3.Zero); |
3079 | linkPart.RotationOffset = worldRot; | 3188 | linkPart.setRotationOffset(worldRot); |
3080 | 3189 | ||
3081 | // Create a new SOG to go around this unlinked and unattached SOP | 3190 | // Create a new SOG to go around this unlinked and unattached SOP |
3082 | SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); | 3191 | SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); |
3083 | 3192 | ||
3084 | m_scene.AddNewSceneObject(objectGroup, true); | 3193 | m_scene.AddNewSceneObject(objectGroup, true); |
3085 | 3194 | ||
3086 | if (sendEvents) | ||
3087 | linkPart.TriggerScriptChangedEvent(Changed.LINK); | ||
3088 | |||
3089 | linkPart.Rezzed = RootPart.Rezzed; | 3195 | linkPart.Rezzed = RootPart.Rezzed; |
3090 | 3196 | ||
3091 | // When we delete a group, we currently have to force persist to the database if the object id has changed | 3197 | // When we delete a group, we currently have to force persist to the database if the object id has changed |
@@ -3100,6 +3206,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3100 | 3206 | ||
3101 | objectGroup.HasGroupChangedDueToDelink = true; | 3207 | objectGroup.HasGroupChangedDueToDelink = true; |
3102 | 3208 | ||
3209 | if (sendEvents) | ||
3210 | linkPart.TriggerScriptChangedEvent(Changed.LINK); | ||
3211 | |||
3103 | return objectGroup; | 3212 | return objectGroup; |
3104 | } | 3213 | } |
3105 | 3214 | ||
@@ -3127,15 +3236,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3127 | Quaternion parentRot = oldGroupRotation; | 3236 | Quaternion parentRot = oldGroupRotation; |
3128 | Quaternion oldRot = part.RotationOffset; | 3237 | Quaternion oldRot = part.RotationOffset; |
3129 | 3238 | ||
3130 | // Move our position to not be relative to the old parent | 3239 | // Move our position in world |
3131 | Vector3 axPos = part.OffsetPosition; | 3240 | Vector3 axPos = part.OffsetPosition; |
3132 | axPos *= parentRot; | 3241 | axPos *= parentRot; |
3133 | part.OffsetPosition = axPos; | 3242 | Vector3 newPos = oldGroupPosition + axPos; |
3134 | Vector3 newPos = oldGroupPosition + part.OffsetPosition; | 3243 | part.setGroupPosition(newPos); |
3135 | part.GroupPosition = newPos; | 3244 | part.setOffsetPosition(Vector3.Zero); |
3136 | part.OffsetPosition = Vector3.Zero; | ||
3137 | 3245 | ||
3138 | // Compution our rotation to be not relative to the old parent | 3246 | // Compution our rotation in world |
3139 | Quaternion worldRot = parentRot * oldRot; | 3247 | Quaternion worldRot = parentRot * oldRot; |
3140 | part.RotationOffset = worldRot; | 3248 | part.RotationOffset = worldRot; |
3141 | 3249 | ||
@@ -3146,25 +3254,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
3146 | 3254 | ||
3147 | part.LinkNum = linkNum; | 3255 | part.LinkNum = linkNum; |
3148 | 3256 | ||
3257 | m_scene.updateScenePartGroup(part, this); | ||
3258 | |||
3149 | // Compute the new position of this SOP relative to the group position | 3259 | // Compute the new position of this SOP relative to the group position |
3150 | part.OffsetPosition = newPos - AbsolutePosition; | 3260 | part.setOffsetPosition(newPos - AbsolutePosition); |
3151 | 3261 | ||
3152 | // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. | 3262 | // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. |
3153 | // It would have the affect of setting the physics engine position multiple | 3263 | // It would have the affect of setting the physics engine position multiple |
3154 | // times. In theory, that is not necessary but I don't have a good linkset | 3264 | // times. In theory, that is not necessary but I don't have a good linkset |
3155 | // test to know that cleaning up this code wouldn't break things.) | 3265 | // test to know that cleaning up this code wouldn't break things.) |
3156 | 3266 | ||
3157 | // Rotate the relative position by the rotation of the group | ||
3158 | Quaternion rootRotation = m_rootPart.RotationOffset; | ||
3159 | Vector3 pos = part.OffsetPosition; | ||
3160 | pos *= Quaternion.Conjugate(rootRotation); | ||
3161 | part.OffsetPosition = pos; | ||
3162 | |||
3163 | // Compute the SOP's rotation relative to the rotation of the group. | 3267 | // Compute the SOP's rotation relative to the rotation of the group. |
3164 | parentRot = m_rootPart.RotationOffset; | 3268 | parentRot = m_rootPart.RotationOffset; |
3269 | |||
3165 | oldRot = part.RotationOffset; | 3270 | oldRot = part.RotationOffset; |
3166 | Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot; | 3271 | Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot; |
3167 | part.RotationOffset = newRot; | 3272 | part.setRotationOffset(newRot); |
3273 | |||
3274 | Vector3 pos = part.OffsetPosition; | ||
3275 | pos *= Quaternion.Conjugate(parentRot); | ||
3276 | |||
3277 | part.OffsetPosition = pos; // update position and orientation on physics also | ||
3168 | 3278 | ||
3169 | // Since this SOP's state has changed, push those changes into the physics engine | 3279 | // Since this SOP's state has changed, push those changes into the physics engine |
3170 | // and the simulator. | 3280 | // and the simulator. |
@@ -3411,8 +3521,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3411 | { | 3521 | { |
3412 | SceneObjectPart[] parts = m_parts.GetArray(); | 3522 | SceneObjectPart[] parts = m_parts.GetArray(); |
3413 | 3523 | ||
3414 | if (Scene != null) | 3524 | if (Scene != null && UsePhysics) |
3415 | { | 3525 | { |
3526 | int maxprims = m_scene.m_linksetPhysCapacity; | ||
3527 | bool checkShape = (maxprims > 0 && | ||
3528 | parts.Length > maxprims); | ||
3529 | |||
3416 | for (int i = 0; i < parts.Length; i++) | 3530 | for (int i = 0; i < parts.Length; i++) |
3417 | { | 3531 | { |
3418 | SceneObjectPart part = parts[i]; | 3532 | SceneObjectPart part = parts[i]; |
@@ -3423,6 +3537,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
3423 | UsePhysics = false; // Reset physics | 3537 | UsePhysics = false; // Reset physics |
3424 | break; | 3538 | break; |
3425 | } | 3539 | } |
3540 | |||
3541 | if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None) | ||
3542 | { | ||
3543 | if (--maxprims < 0) | ||
3544 | { | ||
3545 | UsePhysics = false; | ||
3546 | break; | ||
3547 | } | ||
3548 | } | ||
3426 | } | 3549 | } |
3427 | } | 3550 | } |
3428 | 3551 | ||
@@ -3813,20 +3936,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3813 | /// <summary> | 3936 | /// <summary> |
3814 | /// Update just the root prim position in a linkset | 3937 | /// Update just the root prim position in a linkset |
3815 | /// </summary> | 3938 | /// </summary> |
3816 | /// <param name="pos"></param> | 3939 | /// <param name="newPos"></param> |
3817 | public void UpdateRootPosition(Vector3 pos) | 3940 | public void UpdateRootPosition(Vector3 newPos) |
3818 | { | 3941 | { |
3819 | // needs to be called with phys building true | 3942 | // needs to be called with phys building true |
3820 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3943 | Vector3 oldPos; |
3821 | Vector3 oldPos = | 3944 | |
3822 | new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, | 3945 | if (IsAttachment) |
3823 | AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, | 3946 | oldPos = m_rootPart.AttachedPos + m_rootPart.OffsetPosition; // OffsetPosition should always be 0 in an attachments's root prim |
3824 | AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); | 3947 | else |
3948 | oldPos = AbsolutePosition + m_rootPart.OffsetPosition; | ||
3949 | |||
3825 | Vector3 diff = oldPos - newPos; | 3950 | Vector3 diff = oldPos - newPos; |
3826 | Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z); | ||
3827 | Quaternion partRotation = m_rootPart.RotationOffset; | 3951 | Quaternion partRotation = m_rootPart.RotationOffset; |
3828 | axDiff *= Quaternion.Inverse(partRotation); | 3952 | diff *= Quaternion.Inverse(partRotation); |
3829 | diff = axDiff; | ||
3830 | 3953 | ||
3831 | SceneObjectPart[] parts = m_parts.GetArray(); | 3954 | SceneObjectPart[] parts = m_parts.GetArray(); |
3832 | for (int i = 0; i < parts.Length; i++) | 3955 | for (int i = 0; i < parts.Length; i++) |
@@ -3837,6 +3960,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3837 | } | 3960 | } |
3838 | 3961 | ||
3839 | AbsolutePosition = newPos; | 3962 | AbsolutePosition = newPos; |
3963 | |||
3964 | if (IsAttachment) | ||
3965 | m_rootPart.AttachedPos = newPos; | ||
3840 | 3966 | ||
3841 | HasGroupChanged = true; | 3967 | HasGroupChanged = true; |
3842 | if (m_rootPart.Undoing) | 3968 | if (m_rootPart.Undoing) |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 566605a..91293c4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
231 | 231 | ||
232 | public double SoundRadius; | 232 | public double SoundRadius; |
233 | 233 | ||
234 | /// <summary> | ||
235 | /// Should sounds played from this prim be queued? | ||
236 | /// </summary> | ||
237 | /// <remarks> | ||
238 | /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting. | ||
239 | /// </remarks> | ||
240 | public bool SoundQueueing { get; set; } | ||
234 | 241 | ||
235 | public uint TimeStampFull; | 242 | public uint TimeStampFull; |
236 | 243 | ||
@@ -244,9 +251,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
244 | public byte AttachPoint = 0; | 251 | public byte AttachPoint = 0; |
245 | 252 | ||
246 | [XmlIgnore] | 253 | [XmlIgnore] |
247 | public Vector3 AttachOffset = Vector3.Zero; | ||
248 | |||
249 | [XmlIgnore] | ||
250 | public Quaternion AttachRotation = Quaternion.Identity; | 254 | public Quaternion AttachRotation = Quaternion.Identity; |
251 | 255 | ||
252 | [XmlIgnore] | 256 | [XmlIgnore] |
@@ -383,8 +387,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
383 | 387 | ||
384 | private SOPVehicle m_vehicleParams = null; | 388 | private SOPVehicle m_vehicleParams = null; |
385 | 389 | ||
386 | private KeyframeMotion m_keyframeMotion = null; | ||
387 | |||
388 | public KeyframeMotion KeyframeMotion | 390 | public KeyframeMotion KeyframeMotion |
389 | { | 391 | { |
390 | get; set; | 392 | get; set; |
@@ -506,7 +508,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
506 | { | 508 | { |
507 | get | 509 | get |
508 | { | 510 | { |
509 | if (CreatorData != null && CreatorData != string.Empty) | 511 | if (!string.IsNullOrEmpty(CreatorData)) |
510 | return CreatorID.ToString() + ';' + CreatorData; | 512 | return CreatorID.ToString() + ';' + CreatorData; |
511 | else | 513 | else |
512 | return CreatorID.ToString(); | 514 | return CreatorID.ToString(); |
@@ -536,7 +538,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
536 | CreatorID = uuid; | 538 | CreatorID = uuid; |
537 | } | 539 | } |
538 | if (parts.Length >= 2) | 540 | if (parts.Length >= 2) |
541 | { | ||
539 | CreatorData = parts[1]; | 542 | CreatorData = parts[1]; |
543 | if (!CreatorData.EndsWith("/")) | ||
544 | CreatorData += "/"; | ||
545 | } | ||
540 | if (parts.Length >= 3) | 546 | if (parts.Length >= 3) |
541 | name = parts[2]; | 547 | name = parts[2]; |
542 | 548 | ||
@@ -660,6 +666,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
660 | m_isSelected = value; | 666 | m_isSelected = value; |
661 | if (ParentGroup != null) | 667 | if (ParentGroup != null) |
662 | ParentGroup.PartSelectChanged(value); | 668 | ParentGroup.PartSelectChanged(value); |
669 | |||
663 | } | 670 | } |
664 | } | 671 | } |
665 | 672 | ||
@@ -765,9 +772,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
765 | set { m_damage = value; } | 772 | set { m_damage = value; } |
766 | } | 773 | } |
767 | 774 | ||
775 | |||
776 | |||
777 | |||
778 | public void setGroupPosition(Vector3 pos) | ||
779 | { | ||
780 | m_groupPosition = pos; | ||
781 | } | ||
782 | |||
768 | /// <summary> | 783 | /// <summary> |
769 | /// The position of the entire group that this prim belongs to. | 784 | /// The position of the entire group that this prim belongs to. |
770 | /// </summary> | 785 | /// </summary> |
786 | /// | ||
787 | |||
788 | |||
771 | public Vector3 GroupPosition | 789 | public Vector3 GroupPosition |
772 | { | 790 | { |
773 | get | 791 | get |
@@ -805,7 +823,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
805 | // Root prim actually goes at Position | 823 | // Root prim actually goes at Position |
806 | if (ParentID == 0) | 824 | if (ParentID == 0) |
807 | { | 825 | { |
808 | actor.Position = value; | 826 | actor.Position = value; |
809 | } | 827 | } |
810 | else | 828 | else |
811 | { | 829 | { |
@@ -815,7 +833,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
815 | } | 833 | } |
816 | 834 | ||
817 | // Tell the physics engines that this prim changed. | 835 | // Tell the physics engines that this prim changed. |
818 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | 836 | if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null) |
837 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | ||
819 | } | 838 | } |
820 | catch (Exception e) | 839 | catch (Exception e) |
821 | { | 840 | { |
@@ -825,6 +844,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
825 | } | 844 | } |
826 | } | 845 | } |
827 | 846 | ||
847 | public void setOffsetPosition(Vector3 pos) | ||
848 | { | ||
849 | m_offsetPosition = pos; | ||
850 | } | ||
851 | |||
828 | public Vector3 OffsetPosition | 852 | public Vector3 OffsetPosition |
829 | { | 853 | { |
830 | get { return m_offsetPosition; } | 854 | get { return m_offsetPosition; } |
@@ -855,7 +879,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
855 | { | 879 | { |
856 | Vector3 offset = (m_offsetPosition - oldpos); | 880 | Vector3 offset = (m_offsetPosition - oldpos); |
857 | av.AbsolutePosition += offset; | 881 | av.AbsolutePosition += offset; |
858 | av.SendAvatarDataToAllAgents(); | 882 | // av.SendAvatarDataToAllAgents(); |
883 | av.SendTerseUpdateToAllClients(); | ||
859 | } | 884 | } |
860 | } | 885 | } |
861 | } | 886 | } |
@@ -882,6 +907,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
882 | } | 907 | } |
883 | } | 908 | } |
884 | 909 | ||
910 | public void setRotationOffset(Quaternion q) | ||
911 | { | ||
912 | m_rotationOffset = q; | ||
913 | } | ||
914 | |||
885 | public Quaternion RotationOffset | 915 | public Quaternion RotationOffset |
886 | { | 916 | { |
887 | get | 917 | get |
@@ -933,7 +963,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
933 | //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); | 963 | //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); |
934 | } | 964 | } |
935 | 965 | ||
936 | if (ParentGroup != null) | 966 | if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null) |
937 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | 967 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); |
938 | //} | 968 | //} |
939 | } | 969 | } |
@@ -1218,23 +1248,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1218 | // the mappings more consistant. | 1248 | // the mappings more consistant. |
1219 | public Vector3 SitTargetPositionLL | 1249 | public Vector3 SitTargetPositionLL |
1220 | { | 1250 | { |
1221 | get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } | 1251 | get { return m_sitTargetPosition; } |
1222 | set { m_sitTargetPosition = value; } | 1252 | set { m_sitTargetPosition = value; } |
1223 | } | 1253 | } |
1224 | 1254 | ||
1225 | public Quaternion SitTargetOrientationLL | 1255 | public Quaternion SitTargetOrientationLL |
1226 | { | 1256 | { |
1227 | get | 1257 | get { return m_sitTargetOrientation; } |
1228 | { | 1258 | set { m_sitTargetOrientation = value; } |
1229 | return new Quaternion( | ||
1230 | m_sitTargetOrientation.X, | ||
1231 | m_sitTargetOrientation.Y, | ||
1232 | m_sitTargetOrientation.Z, | ||
1233 | m_sitTargetOrientation.W | ||
1234 | ); | ||
1235 | } | ||
1236 | |||
1237 | set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); } | ||
1238 | } | 1259 | } |
1239 | 1260 | ||
1240 | public bool Stopped | 1261 | public bool Stopped |
@@ -2111,7 +2132,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2111 | /// <param name="linkNum"></param> | 2132 | /// <param name="linkNum"></param> |
2112 | /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> | 2133 | /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> |
2113 | /// <returns></returns> | 2134 | /// <returns></returns> |
2114 | public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) | 2135 | public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) |
2115 | { | 2136 | { |
2116 | SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); | 2137 | SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); |
2117 | dupe.m_shape = m_shape.Copy(); | 2138 | dupe.m_shape = m_shape.Copy(); |
@@ -2157,7 +2178,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2157 | } | 2178 | } |
2158 | 2179 | ||
2159 | // Move afterwards ResetIDs as it clears the localID | 2180 | // Move afterwards ResetIDs as it clears the localID |
2160 | dupe.LocalId = localID; | 2181 | dupe.LocalId = plocalID; |
2161 | 2182 | ||
2162 | // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. | 2183 | // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. |
2163 | dupe.LastOwnerID = OwnerID; | 2184 | dupe.LastOwnerID = OwnerID; |
@@ -2187,7 +2208,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2187 | } | 2208 | } |
2188 | 2209 | ||
2189 | if (dupe.PhysActor != null) | 2210 | if (dupe.PhysActor != null) |
2190 | dupe.PhysActor.LocalID = localID; | 2211 | dupe.PhysActor.LocalID = plocalID; |
2191 | 2212 | ||
2192 | ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); | 2213 | ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); |
2193 | 2214 | ||
@@ -2687,6 +2708,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2687 | detobj.velVector = obj.Velocity; | 2708 | detobj.velVector = obj.Velocity; |
2688 | detobj.colliderType = 0; | 2709 | detobj.colliderType = 0; |
2689 | detobj.groupUUID = obj.GroupID; | 2710 | detobj.groupUUID = obj.GroupID; |
2711 | detobj.linkNumber = LinkNum; // pass my link number | ||
2690 | 2712 | ||
2691 | return detobj; | 2713 | return detobj; |
2692 | } | 2714 | } |
@@ -2702,6 +2724,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2702 | detobj.velVector = av.Velocity; | 2724 | detobj.velVector = av.Velocity; |
2703 | detobj.colliderType = 0; | 2725 | detobj.colliderType = 0; |
2704 | detobj.groupUUID = av.ControllingClient.ActiveGroupId; | 2726 | detobj.groupUUID = av.ControllingClient.ActiveGroupId; |
2727 | detobj.linkNumber = LinkNum; // pass my link number | ||
2705 | 2728 | ||
2706 | return detobj; | 2729 | return detobj; |
2707 | } | 2730 | } |
@@ -2717,6 +2740,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2717 | detobj.velVector = Vector3.Zero; | 2740 | detobj.velVector = Vector3.Zero; |
2718 | detobj.colliderType = 0; | 2741 | detobj.colliderType = 0; |
2719 | detobj.groupUUID = UUID.Zero; | 2742 | detobj.groupUUID = UUID.Zero; |
2743 | detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm | ||
2720 | 2744 | ||
2721 | return detobj; | 2745 | return detobj; |
2722 | } | 2746 | } |
@@ -2965,7 +2989,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
2965 | } | 2989 | } |
2966 | //ParentGroup.RootPart.m_groupPosition = newpos; | 2990 | //ParentGroup.RootPart.m_groupPosition = newpos; |
2967 | } | 2991 | } |
2968 | 2992 | /* ubit: there are no flexible links | |
2993 | if (pa != null && ParentID != 0 && ParentGroup != null) | ||
2994 | { | ||
2995 | // Special case where a child object is requesting property updates. | ||
2996 | // This happens when linksets are modified to use flexible links rather than | ||
2997 | // the default links. | ||
2998 | // The simulator code presumes that child parts are only modified by scripts | ||
2999 | // so the logic for changing position/rotation/etc does not take into | ||
3000 | // account the physical object actually moving. | ||
3001 | // This code updates the offset position and rotation of the child and then | ||
3002 | // lets the update code push the update to the viewer. | ||
3003 | // Since physics engines do not normally generate this event for linkset children, | ||
3004 | // this code will not be active unless you have a specially configured | ||
3005 | // physics engine. | ||
3006 | Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset)); | ||
3007 | m_offsetPosition = pa.Position - m_groupPosition; | ||
3008 | RotationOffset = pa.Orientation * invRootRotation; | ||
3009 | // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", | ||
3010 | // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); | ||
3011 | } | ||
3012 | */ | ||
2969 | ScheduleTerseUpdate(); | 3013 | ScheduleTerseUpdate(); |
2970 | } | 3014 | } |
2971 | 3015 | ||
@@ -3144,7 +3188,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3144 | return; | 3188 | return; |
3145 | 3189 | ||
3146 | // This was pulled from SceneViewer. Attachments always receive full updates. | 3190 | // This was pulled from SceneViewer. Attachments always receive full updates. |
3147 | // I could not verify if this is a requirement but this maintains existing behavior | 3191 | // This is needed because otherwise if only the root prim changes position, then |
3192 | // it looks as if the entire object has moved (including the other prims). | ||
3148 | if (ParentGroup.IsAttachment) | 3193 | if (ParentGroup.IsAttachment) |
3149 | { | 3194 | { |
3150 | ScheduleFullUpdate(); | 3195 | ScheduleFullUpdate(); |
@@ -3217,7 +3262,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
3217 | 3262 | ||
3218 | // m_log.DebugFormat( | 3263 | // m_log.DebugFormat( |
3219 | // "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); | 3264 | // "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); |
3220 | 3265 | ||
3266 | |||
3267 | if (ParentGroup.IsAttachment) | ||
3268 | { | ||
3269 | ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); | ||
3270 | if (sp != null) | ||
3271 | { | ||
3272 | sp.SendAttachmentUpdate(this, UpdateRequired.FULL); | ||
3273 | } | ||
3274 | } | ||
3275 | |||
3276 | /* this does nothing | ||
3277 | SendFullUpdateToClient(remoteClient, Position) ignores position parameter | ||
3221 | if (IsRoot) | 3278 | if (IsRoot) |
3222 | { | 3279 | { |
3223 | if (ParentGroup.IsAttachment) | 3280 | if (ParentGroup.IsAttachment) |
@@ -3229,6 +3286,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3229 | SendFullUpdateToClient(remoteClient, AbsolutePosition); | 3286 | SendFullUpdateToClient(remoteClient, AbsolutePosition); |
3230 | } | 3287 | } |
3231 | } | 3288 | } |
3289 | */ | ||
3232 | else | 3290 | else |
3233 | { | 3291 | { |
3234 | SendFullUpdateToClient(remoteClient); | 3292 | SendFullUpdateToClient(remoteClient); |
@@ -3238,7 +3296,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3238 | /// <summary> | 3296 | /// <summary> |
3239 | /// Send a full update for this part to all clients. | 3297 | /// Send a full update for this part to all clients. |
3240 | /// </summary> | 3298 | /// </summary> |
3241 | public void SendFullUpdateToAllClients() | 3299 | public void SendFullUpdateToAllClientsInternal() |
3242 | { | 3300 | { |
3243 | if (ParentGroup == null) | 3301 | if (ParentGroup == null) |
3244 | return; | 3302 | return; |
@@ -3257,6 +3315,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
3257 | }); | 3315 | }); |
3258 | } | 3316 | } |
3259 | 3317 | ||
3318 | public void SendFullUpdateToAllClients() | ||
3319 | { | ||
3320 | if (ParentGroup == null) | ||
3321 | return; | ||
3322 | |||
3323 | // Update the "last" values | ||
3324 | m_lastPosition = OffsetPosition; | ||
3325 | m_lastRotation = RotationOffset; | ||
3326 | m_lastVelocity = Velocity; | ||
3327 | m_lastAcceleration = Acceleration; | ||
3328 | m_lastAngularVelocity = AngularVelocity; | ||
3329 | m_lastUpdateSentTime = Environment.TickCount; | ||
3330 | |||
3331 | if (ParentGroup.IsAttachment) | ||
3332 | { | ||
3333 | ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); | ||
3334 | if (sp != null) | ||
3335 | { | ||
3336 | sp.SendAttachmentUpdate(this, UpdateRequired.FULL); | ||
3337 | } | ||
3338 | } | ||
3339 | else | ||
3340 | { | ||
3341 | ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) | ||
3342 | { | ||
3343 | SendFullUpdate(avatar.ControllingClient); | ||
3344 | }); | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3260 | /// <summary> | 3348 | /// <summary> |
3261 | /// Sends a full update to the client | 3349 | /// Sends a full update to the client |
3262 | /// </summary> | 3350 | /// </summary> |
@@ -3277,9 +3365,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3277 | return; | 3365 | return; |
3278 | 3366 | ||
3279 | // Suppress full updates during attachment editing | 3367 | // Suppress full updates during attachment editing |
3280 | // | 3368 | // sl Does send them |
3281 | if (ParentGroup.IsSelected && ParentGroup.IsAttachment) | 3369 | // if (ParentGroup.IsSelected && ParentGroup.IsAttachment) |
3282 | return; | 3370 | // return; |
3283 | 3371 | ||
3284 | if (ParentGroup.IsDeleted) | 3372 | if (ParentGroup.IsDeleted) |
3285 | return; | 3373 | return; |
@@ -3326,24 +3414,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
3326 | !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || | 3414 | !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || |
3327 | Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE) | 3415 | Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE) |
3328 | { | 3416 | { |
3329 | SendTerseUpdateToAllClients(); | 3417 | SendTerseUpdateToAllClientsInternal(); |
3330 | |||
3331 | } | 3418 | } |
3332 | break; | 3419 | break; |
3333 | } | 3420 | } |
3334 | case UpdateRequired.FULL: | 3421 | case UpdateRequired.FULL: |
3335 | { | 3422 | { |
3336 | ClearUpdateSchedule(); | 3423 | ClearUpdateSchedule(); |
3337 | SendFullUpdateToAllClients(); | 3424 | SendFullUpdateToAllClientsInternal(); |
3338 | break; | 3425 | break; |
3339 | } | 3426 | } |
3340 | } | 3427 | } |
3341 | } | 3428 | } |
3342 | 3429 | ||
3430 | |||
3343 | /// <summary> | 3431 | /// <summary> |
3344 | /// Send a terse update to all clients | 3432 | /// Send a terse update to all clients |
3345 | /// </summary> | 3433 | /// </summary> |
3346 | public void SendTerseUpdateToAllClients() | 3434 | public void SendTerseUpdateToAllClientsInternal() |
3347 | { | 3435 | { |
3348 | if (ParentGroup == null || ParentGroup.Scene == null) | 3436 | if (ParentGroup == null || ParentGroup.Scene == null) |
3349 | return; | 3437 | return; |
@@ -3362,6 +3450,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
3362 | }); | 3450 | }); |
3363 | } | 3451 | } |
3364 | 3452 | ||
3453 | public void SendTerseUpdateToAllClients() | ||
3454 | { | ||
3455 | if (ParentGroup == null || ParentGroup.Scene == null) | ||
3456 | return; | ||
3457 | |||
3458 | // Update the "last" values | ||
3459 | m_lastPosition = OffsetPosition; | ||
3460 | m_lastRotation = RotationOffset; | ||
3461 | m_lastVelocity = Velocity; | ||
3462 | m_lastAcceleration = Acceleration; | ||
3463 | m_lastAngularVelocity = AngularVelocity; | ||
3464 | m_lastUpdateSentTime = Environment.TickCount; | ||
3465 | |||
3466 | if (ParentGroup.IsAttachment) | ||
3467 | { | ||
3468 | ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); | ||
3469 | if (sp != null) | ||
3470 | { | ||
3471 | sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); | ||
3472 | } | ||
3473 | } | ||
3474 | else | ||
3475 | { | ||
3476 | ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) | ||
3477 | { | ||
3478 | SendTerseUpdateToClient(client); | ||
3479 | }); | ||
3480 | } | ||
3481 | } | ||
3482 | |||
3365 | public void SetAxisRotation(int axis, int rotate) | 3483 | public void SetAxisRotation(int axis, int rotate) |
3366 | { | 3484 | { |
3367 | ParentGroup.SetAxisRotation(axis, rotate); | 3485 | ParentGroup.SetAxisRotation(axis, rotate); |
@@ -3714,8 +3832,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3714 | // Name, groupID, OwnerID); | 3832 | // Name, groupID, OwnerID); |
3715 | 3833 | ||
3716 | GroupID = groupID; | 3834 | GroupID = groupID; |
3717 | if (client != null) | 3835 | // if (client != null) |
3718 | SendPropertiesToClient(client); | 3836 | // SendPropertiesToClient(client); |
3719 | UpdateFlag = UpdateRequired.FULL; | 3837 | UpdateFlag = UpdateRequired.FULL; |
3720 | } | 3838 | } |
3721 | 3839 | ||
@@ -4357,30 +4475,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
4357 | } | 4475 | } |
4358 | } | 4476 | } |
4359 | 4477 | ||
4360 | public void UpdateGroupPosition(Vector3 pos) | 4478 | public void UpdateGroupPosition(Vector3 newPos) |
4361 | { | 4479 | { |
4362 | if ((pos.X != GroupPosition.X) || | 4480 | Vector3 oldPos = GroupPosition; |
4363 | (pos.Y != GroupPosition.Y) || | 4481 | |
4364 | (pos.Z != GroupPosition.Z)) | 4482 | if ((newPos.X != oldPos.X) || |
4483 | (newPos.Y != oldPos.Y) || | ||
4484 | (newPos.Z != oldPos.Z)) | ||
4365 | { | 4485 | { |
4366 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | ||
4367 | GroupPosition = newPos; | 4486 | GroupPosition = newPos; |
4368 | ScheduleTerseUpdate(); | 4487 | ScheduleTerseUpdate(); |
4369 | } | 4488 | } |
4370 | } | 4489 | } |
4371 | 4490 | ||
4372 | /// <summary> | 4491 | /// <summary> |
4373 | /// | 4492 | /// Update this part's offset position. |
4374 | /// </summary> | 4493 | /// </summary> |
4375 | /// <param name="pos"></param> | 4494 | /// <param name="pos"></param> |
4376 | public void UpdateOffSet(Vector3 pos) | 4495 | public void UpdateOffSet(Vector3 newPos) |
4377 | { | 4496 | { |
4378 | if ((pos.X != OffsetPosition.X) || | 4497 | Vector3 oldPos = OffsetPosition; |
4379 | (pos.Y != OffsetPosition.Y) || | ||
4380 | (pos.Z != OffsetPosition.Z)) | ||
4381 | { | ||
4382 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | ||
4383 | 4498 | ||
4499 | if ((newPos.X != oldPos.X) || | ||
4500 | (newPos.Y != oldPos.Y) || | ||
4501 | (newPos.Z != oldPos.Z)) | ||
4502 | { | ||
4384 | if (ParentGroup.RootPart.GetStatusSandbox()) | 4503 | if (ParentGroup.RootPart.GetStatusSandbox()) |
4385 | { | 4504 | { |
4386 | if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) | 4505 | if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) |
@@ -4527,7 +4646,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4527 | // For now, we use the NINJA naming scheme for identifying joints. | 4646 | // For now, we use the NINJA naming scheme for identifying joints. |
4528 | // In the future, we can support other joint specification schemes such as a | 4647 | // In the future, we can support other joint specification schemes such as a |
4529 | // custom checkbox in the viewer GUI. | 4648 | // custom checkbox in the viewer GUI. |
4530 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | 4649 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) |
4531 | { | 4650 | { |
4532 | return IsHingeJoint() || IsBallJoint(); | 4651 | return IsHingeJoint() || IsBallJoint(); |
4533 | } | 4652 | } |
@@ -4649,6 +4768,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
4649 | } | 4768 | } |
4650 | } | 4769 | } |
4651 | */ | 4770 | */ |
4771 | if (pa != null) | ||
4772 | { | ||
4773 | pa.SetMaterial(Material); | ||
4774 | DoPhysicsPropertyUpdate(UsePhysics, true); | ||
4775 | } | ||
4652 | } | 4776 | } |
4653 | else // it already has a physical representation | 4777 | else // it already has a physical representation |
4654 | { | 4778 | { |
@@ -5021,6 +5145,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
5021 | oldTex.DefaultTexture = fallbackOldFace; | 5145 | oldTex.DefaultTexture = fallbackOldFace; |
5022 | } | 5146 | } |
5023 | 5147 | ||
5148 | // Materials capable viewers can send a ObjectImage packet | ||
5149 | // when nothing in TE has changed. MaterialID should be updated | ||
5150 | // by the RenderMaterials CAP handler, so updating it here may cause a | ||
5151 | // race condtion. Therefore, if no non-materials TE fields have changed, | ||
5152 | // we should ignore any changes and not update Shape.TextureEntry | ||
5153 | |||
5154 | bool otherFieldsChanged = false; | ||
5155 | |||
5024 | for (int i = 0 ; i < GetNumberOfSides(); i++) | 5156 | for (int i = 0 ; i < GetNumberOfSides(); i++) |
5025 | { | 5157 | { |
5026 | 5158 | ||
@@ -5047,18 +5179,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
5047 | // Max change, skip the rest of testing | 5179 | // Max change, skip the rest of testing |
5048 | if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) | 5180 | if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) |
5049 | break; | 5181 | break; |
5182 | |||
5183 | if (!otherFieldsChanged) | ||
5184 | { | ||
5185 | if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true; | ||
5186 | if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true; | ||
5187 | if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true; | ||
5188 | if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true; | ||
5189 | if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true; | ||
5190 | if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true; | ||
5191 | if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true; | ||
5192 | if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true; | ||
5193 | if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true; | ||
5194 | if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true; | ||
5195 | if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true; | ||
5196 | } | ||
5050 | } | 5197 | } |
5051 | 5198 | ||
5052 | m_shape.TextureEntry = newTex.GetBytes(); | 5199 | if (changeFlags != 0 || otherFieldsChanged) |
5053 | if (changeFlags != 0) | 5200 | { |
5054 | TriggerScriptChangedEvent(changeFlags); | 5201 | m_shape.TextureEntry = newTex.GetBytes(); |
5055 | UpdateFlag = UpdateRequired.FULL; | 5202 | if (changeFlags != 0) |
5056 | ParentGroup.HasGroupChanged = true; | 5203 | TriggerScriptChangedEvent(changeFlags); |
5204 | UpdateFlag = UpdateRequired.FULL; | ||
5205 | ParentGroup.HasGroupChanged = true; | ||
5057 | 5206 | ||
5058 | //This is madness.. | 5207 | //This is madness.. |
5059 | //ParentGroup.ScheduleGroupForFullUpdate(); | 5208 | //ParentGroup.ScheduleGroupForFullUpdate(); |
5060 | //This is sparta | 5209 | //This is sparta |
5061 | ScheduleFullUpdate(); | 5210 | ScheduleFullUpdate(); |
5211 | } | ||
5062 | } | 5212 | } |
5063 | 5213 | ||
5064 | 5214 | ||
@@ -5246,6 +5396,64 @@ namespace OpenSim.Region.Framework.Scenes | |||
5246 | { | 5396 | { |
5247 | ParentGroup.AddScriptLPS(count); | 5397 | ParentGroup.AddScriptLPS(count); |
5248 | } | 5398 | } |
5399 | |||
5400 | /// <summary> | ||
5401 | /// Sets a prim's owner and permissions when it's rezzed. | ||
5402 | /// </summary> | ||
5403 | /// <param name="item">The inventory item from which the item was rezzed</param> | ||
5404 | /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param> | ||
5405 | /// <param name="scene">The scene the prim is being rezzed into</param> | ||
5406 | public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene) | ||
5407 | { | ||
5408 | if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)) | ||
5409 | { | ||
5410 | if (scene.Permissions.PropagatePermissions()) | ||
5411 | { | ||
5412 | if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) | ||
5413 | { | ||
5414 | // Apply the item's permissions to the object | ||
5415 | //LogPermissions("Before applying item permissions"); | ||
5416 | if (userInventory) | ||
5417 | { | ||
5418 | EveryoneMask = item.EveryOnePermissions; | ||
5419 | NextOwnerMask = item.NextPermissions; | ||
5420 | } | ||
5421 | else | ||
5422 | { | ||
5423 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | ||
5424 | EveryoneMask = item.EveryOnePermissions; | ||
5425 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) | ||
5426 | NextOwnerMask = item.NextPermissions; | ||
5427 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | ||
5428 | GroupMask = item.GroupPermissions; | ||
5429 | } | ||
5430 | //LogPermissions("After applying item permissions"); | ||
5431 | } | ||
5432 | } | ||
5433 | |||
5434 | GroupMask = 0; // DO NOT propagate here | ||
5435 | } | ||
5436 | |||
5437 | if (OwnerID != item.Owner) | ||
5438 | { | ||
5439 | //LogPermissions("Before ApplyNextOwnerPermissions"); | ||
5440 | ApplyNextOwnerPermissions(); | ||
5441 | //LogPermissions("After ApplyNextOwnerPermissions"); | ||
5442 | |||
5443 | LastOwnerID = OwnerID; | ||
5444 | OwnerID = item.Owner; | ||
5445 | Inventory.ChangeInventoryOwner(item.Owner); | ||
5446 | } | ||
5447 | } | ||
5448 | |||
5449 | /// <summary> | ||
5450 | /// Logs the prim's permissions. Useful when debugging permission problems. | ||
5451 | /// </summary> | ||
5452 | /// <param name="message"></param> | ||
5453 | private void LogPermissions(String message) | ||
5454 | { | ||
5455 | PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask); | ||
5456 | } | ||
5249 | 5457 | ||
5250 | public void ApplyNextOwnerPermissions() | 5458 | public void ApplyNextOwnerPermissions() |
5251 | { | 5459 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d04d87b..2fa9139 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | |||
@@ -46,10 +46,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
46 | { | 46 | { |
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | private string m_inventoryFileName = String.Empty; | ||
50 | private byte[] m_inventoryFileData = new byte[0]; | 49 | private byte[] m_inventoryFileData = new byte[0]; |
51 | private uint m_inventoryFileNameSerial = 0; | 50 | private uint m_inventoryFileNameSerial = 0; |
52 | private bool m_inventoryPrivileged = false; | 51 | private bool m_inventoryPrivileged = false; |
52 | private object m_inventoryFileLock = new object(); | ||
53 | 53 | ||
54 | private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>(); | 54 | private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>(); |
55 | 55 | ||
@@ -505,35 +505,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
505 | private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) | 505 | private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) |
506 | { | 506 | { |
507 | m_items.LockItemsForRead(true); | 507 | m_items.LockItemsForRead(true); |
508 | |||
508 | if (m_items.ContainsKey(itemId)) | 509 | if (m_items.ContainsKey(itemId)) |
509 | { | 510 | { |
510 | if (m_items.ContainsKey(itemId)) | 511 | TaskInventoryItem it = m_items[itemId]; |
511 | { | 512 | m_items.LockItemsForRead(false); |
512 | m_items.LockItemsForRead(false); | 513 | |
513 | CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); | 514 | CreateScriptInstance(it, startParam, postOnRez, engine, stateSource); |
514 | } | ||
515 | else | ||
516 | { | ||
517 | m_items.LockItemsForRead(false); | ||
518 | string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID, | ||
519 | m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); | ||
520 | StoreScriptError(itemId, msg); | ||
521 | m_log.ErrorFormat( | ||
522 | "[PRIM INVENTORY]: " + | ||
523 | "Couldn't start script with ID {0} since it {1}", itemId, msg); | ||
524 | } | ||
525 | } | 515 | } |
526 | else | 516 | else |
527 | { | 517 | { |
528 | m_items.LockItemsForRead(false); | 518 | m_items.LockItemsForRead(false); |
529 | string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID); | 519 | string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID, |
520 | m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); | ||
530 | StoreScriptError(itemId, msg); | 521 | StoreScriptError(itemId, msg); |
531 | m_log.ErrorFormat( | 522 | m_log.ErrorFormat( |
532 | "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", | 523 | "[PRIM INVENTORY]: " + |
533 | itemId, m_part.Name, m_part.UUID, | 524 | "Couldn't start script with ID {0} since it {1}", itemId, msg); |
534 | m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); | ||
535 | } | 525 | } |
536 | |||
537 | } | 526 | } |
538 | 527 | ||
539 | /// <summary> | 528 | /// <summary> |
@@ -696,7 +685,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
696 | /// </param> | 685 | /// </param> |
697 | public void StopScriptInstance(TaskInventoryItem item) | 686 | public void StopScriptInstance(TaskInventoryItem item) |
698 | { | 687 | { |
699 | m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); | 688 | if (m_part.ParentGroup.Scene != null) |
689 | m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); | ||
700 | 690 | ||
701 | // At the moment, even stopped scripts are counted as active, which is probably wrong. | 691 | // At the moment, even stopped scripts are counted as active, which is probably wrong. |
702 | // m_part.ParentGroup.AddActiveScriptCount(-1); | 692 | // m_part.ParentGroup.AddActiveScriptCount(-1); |
@@ -880,8 +870,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
880 | 870 | ||
881 | return items; | 871 | return items; |
882 | } | 872 | } |
883 | 873 | ||
884 | public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) | 874 | public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist) |
885 | { | 875 | { |
886 | AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); | 876 | AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); |
887 | 877 | ||
@@ -890,70 +880,102 @@ namespace OpenSim.Region.Framework.Scenes | |||
890 | m_log.WarnFormat( | 880 | m_log.WarnFormat( |
891 | "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", | 881 | "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", |
892 | item.AssetID, item.Name, m_part.Name); | 882 | item.AssetID, item.Name, m_part.Name); |
893 | return null; | 883 | objlist = null; |
884 | veclist = null; | ||
885 | return false; | ||
894 | } | 886 | } |
895 | 887 | ||
896 | string xmlData = Utils.BytesToString(rezAsset.Data); | 888 | Vector3 bbox; |
897 | SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | 889 | float offsetHeight; |
898 | 890 | ||
899 | group.RootPart.AttachPoint = group.RootPart.Shape.State; | 891 | bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight); |
900 | group.RootPart.AttachOffset = group.AbsolutePosition; | ||
901 | group.RootPart.AttachRotation = group.GroupRotation; | ||
902 | 892 | ||
903 | group.ResetIDs(); | 893 | for (int i = 0; i < objlist.Count; i++) |
904 | 894 | { | |
905 | SceneObjectPart rootPart = group.GetPart(group.UUID); | 895 | SceneObjectGroup group = objlist[i]; |
906 | 896 | /* | |
907 | // Since renaming the item in the inventory does not affect the name stored | 897 | group.RootPart.AttachPoint = group.RootPart.Shape.State; |
908 | // in the serialization, transfer the correct name from the inventory to the | 898 | group.RootPart.AttachedPos = group.AbsolutePosition; |
909 | // object itself before we rez. | 899 | group.RootPart.AttachRotation = group.GroupRotation; |
910 | rootPart.Name = item.Name; | 900 | */ |
911 | rootPart.Description = item.Description; | 901 | group.ResetIDs(); |
902 | |||
903 | SceneObjectPart rootPart = group.GetPart(group.UUID); | ||
904 | |||
905 | // Since renaming the item in the inventory does not affect the name stored | ||
906 | // in the serialization, transfer the correct name from the inventory to the | ||
907 | // object itself before we rez. | ||
908 | // Only do these for the first object if we are rezzing a coalescence. | ||
909 | // nahh dont mess with coalescence objects, | ||
910 | // the name in inventory can be change for inventory purpuses only | ||
911 | if (objlist.Count == 1) | ||
912 | { | ||
913 | rootPart.Name = item.Name; | ||
914 | rootPart.Description = item.Description; | ||
915 | } | ||
916 | /* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed | ||
917 | group.SetGroup(m_part.GroupID, null); | ||
912 | 918 | ||
913 | SceneObjectPart[] partList = group.Parts; | 919 | foreach (SceneObjectPart part in group.Parts) |
920 | { | ||
921 | // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :) | ||
922 | InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID); | ||
923 | dest.BasePermissions = item.BasePermissions; | ||
924 | dest.CurrentPermissions = item.CurrentPermissions; | ||
925 | dest.EveryOnePermissions = item.EveryonePermissions; | ||
926 | dest.GroupPermissions = item.GroupPermissions; | ||
927 | dest.NextPermissions = item.NextPermissions; | ||
928 | dest.Flags = item.Flags; | ||
929 | |||
930 | part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); | ||
931 | } | ||
932 | */ | ||
933 | // old code start | ||
934 | SceneObjectPart[] partList = group.Parts; | ||
914 | 935 | ||
915 | group.SetGroup(m_part.GroupID, null); | 936 | group.SetGroup(m_part.GroupID, null); |
916 | 937 | ||
917 | // TODO: Remove magic number badness | 938 | // TODO: Remove magic number badness |
918 | if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number | 939 | if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number |
919 | { | ||
920 | if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) | ||
921 | { | 940 | { |
922 | foreach (SceneObjectPart part in partList) | 941 | if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) |
923 | { | 942 | { |
924 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | 943 | foreach (SceneObjectPart part in partList) |
925 | part.EveryoneMask = item.EveryonePermissions; | 944 | { |
926 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) | 945 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) |
927 | part.NextOwnerMask = item.NextPermissions; | 946 | part.EveryoneMask = item.EveryonePermissions; |
928 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | 947 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) |
929 | part.GroupMask = item.GroupPermissions; | 948 | part.NextOwnerMask = item.NextPermissions; |
949 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | ||
950 | part.GroupMask = item.GroupPermissions; | ||
951 | } | ||
952 | |||
953 | group.ApplyNextOwnerPermissions(); | ||
930 | } | 954 | } |
931 | |||
932 | group.ApplyNextOwnerPermissions(); | ||
933 | } | 955 | } |
934 | } | ||
935 | 956 | ||
936 | foreach (SceneObjectPart part in partList) | 957 | foreach (SceneObjectPart part in partList) |
937 | { | ||
938 | // TODO: Remove magic number badness | ||
939 | if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number | ||
940 | { | 958 | { |
941 | part.LastOwnerID = part.OwnerID; | 959 | // TODO: Remove magic number badness |
942 | part.OwnerID = item.OwnerID; | 960 | if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number |
943 | part.Inventory.ChangeInventoryOwner(item.OwnerID); | 961 | { |
962 | part.LastOwnerID = part.OwnerID; | ||
963 | part.OwnerID = item.OwnerID; | ||
964 | part.Inventory.ChangeInventoryOwner(item.OwnerID); | ||
965 | } | ||
966 | |||
967 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | ||
968 | part.EveryoneMask = item.EveryonePermissions; | ||
969 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) | ||
970 | part.NextOwnerMask = item.NextPermissions; | ||
971 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | ||
972 | part.GroupMask = item.GroupPermissions; | ||
944 | } | 973 | } |
945 | 974 | // old code end | |
946 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) | 975 | rootPart.TrimPermissions(); |
947 | part.EveryoneMask = item.EveryonePermissions; | ||
948 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) | ||
949 | part.NextOwnerMask = item.NextPermissions; | ||
950 | if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) | ||
951 | part.GroupMask = item.GroupPermissions; | ||
952 | } | 976 | } |
953 | 977 | ||
954 | rootPart.TrimPermissions(); | 978 | return true; |
955 | |||
956 | return group; | ||
957 | } | 979 | } |
958 | 980 | ||
959 | /// <summary> | 981 | /// <summary> |
@@ -1077,23 +1099,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1077 | return -1; | 1099 | return -1; |
1078 | } | 1100 | } |
1079 | 1101 | ||
1080 | private bool CreateInventoryFileName() | ||
1081 | { | ||
1082 | // m_log.DebugFormat( | ||
1083 | // "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", | ||
1084 | // m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial); | ||
1085 | |||
1086 | if (m_inventoryFileName == String.Empty || | ||
1087 | m_inventoryFileNameSerial < m_inventorySerial) | ||
1088 | { | ||
1089 | m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; | ||
1090 | m_inventoryFileNameSerial = m_inventorySerial; | ||
1091 | |||
1092 | return true; | ||
1093 | } | ||
1094 | |||
1095 | return false; | ||
1096 | } | ||
1097 | 1102 | ||
1098 | /// <summary> | 1103 | /// <summary> |
1099 | /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client | 1104 | /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client |
@@ -1101,110 +1106,124 @@ namespace OpenSim.Region.Framework.Scenes | |||
1101 | /// <param name="xferManager"></param> | 1106 | /// <param name="xferManager"></param> |
1102 | public void RequestInventoryFile(IClientAPI client, IXfer xferManager) | 1107 | public void RequestInventoryFile(IClientAPI client, IXfer xferManager) |
1103 | { | 1108 | { |
1104 | bool changed = CreateInventoryFileName(); | ||
1105 | 1109 | ||
1106 | bool includeAssets = false; | 1110 | lock (m_inventoryFileLock) |
1107 | if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId)) | 1111 | { |
1108 | includeAssets = true; | 1112 | string filename = "inventory_" + UUID.Random().ToString() + ".tmp"; |
1109 | 1113 | ||
1110 | if (m_inventoryPrivileged != includeAssets) | 1114 | bool changed = false; |
1111 | changed = true; | 1115 | if (m_inventoryFileNameSerial < m_inventorySerial) |
1116 | { | ||
1117 | m_inventoryFileNameSerial = m_inventorySerial; | ||
1118 | changed = true; | ||
1119 | } | ||
1112 | 1120 | ||
1113 | InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); | 1121 | if (m_inventoryFileData.Length < 2) |
1122 | changed = true; | ||
1114 | 1123 | ||
1115 | Items.LockItemsForRead(true); | 1124 | bool includeAssets = false; |
1125 | if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId)) | ||
1126 | includeAssets = true; | ||
1116 | 1127 | ||
1117 | if (m_inventorySerial == 0) // No inventory | 1128 | if (m_inventoryPrivileged != includeAssets) |
1118 | { | 1129 | changed = true; |
1119 | client.SendTaskInventory(m_part.UUID, 0, new byte[0]); | ||
1120 | Items.LockItemsForRead(false); | ||
1121 | return; | ||
1122 | } | ||
1123 | 1130 | ||
1124 | if (m_items.Count == 0) // No inventory | ||
1125 | { | ||
1126 | client.SendTaskInventory(m_part.UUID, 0, new byte[0]); | ||
1127 | Items.LockItemsForRead(false); | ||
1128 | return; | ||
1129 | } | ||
1130 | |||
1131 | if (!changed) | ||
1132 | { | ||
1133 | if (m_inventoryFileData.Length > 2) | ||
1134 | { | ||
1135 | xferManager.AddNewFile(m_inventoryFileName, | ||
1136 | m_inventoryFileData); | ||
1137 | client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, | ||
1138 | Util.StringToBytes256(m_inventoryFileName)); | ||
1139 | 1131 | ||
1132 | Items.LockItemsForRead(true); | ||
1133 | |||
1134 | if (m_inventorySerial == 0) // No inventory | ||
1135 | { | ||
1140 | Items.LockItemsForRead(false); | 1136 | Items.LockItemsForRead(false); |
1137 | client.SendTaskInventory(m_part.UUID, 0, new byte[0]); | ||
1138 | |||
1141 | return; | 1139 | return; |
1142 | } | 1140 | } |
1143 | } | ||
1144 | |||
1145 | m_inventoryPrivileged = includeAssets; | ||
1146 | |||
1147 | foreach (TaskInventoryItem item in m_items.Values) | ||
1148 | { | ||
1149 | UUID ownerID = item.OwnerID; | ||
1150 | uint everyoneMask = 0; | ||
1151 | uint baseMask = item.BasePermissions; | ||
1152 | uint ownerMask = item.CurrentPermissions; | ||
1153 | uint groupMask = item.GroupPermissions; | ||
1154 | 1141 | ||
1155 | invString.AddItemStart(); | 1142 | if (m_items.Count == 0) // No inventory |
1156 | invString.AddNameValueLine("item_id", item.ItemID.ToString()); | 1143 | { |
1157 | invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); | 1144 | Items.LockItemsForRead(false); |
1158 | 1145 | client.SendTaskInventory(m_part.UUID, 0, new byte[0]); | |
1159 | invString.AddPermissionsStart(); | 1146 | return; |
1160 | 1147 | } | |
1161 | invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); | ||
1162 | invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); | ||
1163 | invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); | ||
1164 | invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); | ||
1165 | invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); | ||
1166 | 1148 | ||
1167 | invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); | 1149 | if (!changed) |
1168 | invString.AddNameValueLine("owner_id", ownerID.ToString()); | 1150 | { |
1151 | Items.LockItemsForRead(false); | ||
1169 | 1152 | ||
1170 | invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); | 1153 | xferManager.AddNewFile(filename, |
1154 | m_inventoryFileData); | ||
1155 | client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial, | ||
1156 | Util.StringToBytes256(filename)); | ||
1171 | 1157 | ||
1172 | invString.AddNameValueLine("group_id", item.GroupID.ToString()); | 1158 | return; |
1173 | invString.AddSectionEnd(); | 1159 | } |
1174 | 1160 | ||
1175 | if (includeAssets) | 1161 | m_inventoryPrivileged = includeAssets; |
1176 | invString.AddNameValueLine("asset_id", item.AssetID.ToString()); | ||
1177 | else | ||
1178 | invString.AddNameValueLine("asset_id", UUID.Zero.ToString()); | ||
1179 | invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); | ||
1180 | invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); | ||
1181 | invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); | ||
1182 | 1162 | ||
1183 | invString.AddSaleStart(); | 1163 | InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); |
1184 | invString.AddNameValueLine("sale_type", "not"); | ||
1185 | invString.AddNameValueLine("sale_price", "0"); | ||
1186 | invString.AddSectionEnd(); | ||
1187 | 1164 | ||
1188 | invString.AddNameValueLine("name", item.Name + "|"); | 1165 | foreach (TaskInventoryItem item in m_items.Values) |
1189 | invString.AddNameValueLine("desc", item.Description + "|"); | 1166 | { |
1167 | UUID ownerID = item.OwnerID; | ||
1168 | uint everyoneMask = 0; | ||
1169 | uint baseMask = item.BasePermissions; | ||
1170 | uint ownerMask = item.CurrentPermissions; | ||
1171 | uint groupMask = item.GroupPermissions; | ||
1172 | |||
1173 | invString.AddItemStart(); | ||
1174 | invString.AddNameValueLine("item_id", item.ItemID.ToString()); | ||
1175 | invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); | ||
1176 | |||
1177 | invString.AddPermissionsStart(); | ||
1178 | |||
1179 | invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); | ||
1180 | invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); | ||
1181 | invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); | ||
1182 | invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); | ||
1183 | invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); | ||
1184 | |||
1185 | invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); | ||
1186 | invString.AddNameValueLine("owner_id", ownerID.ToString()); | ||
1187 | |||
1188 | invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); | ||
1189 | |||
1190 | invString.AddNameValueLine("group_id", item.GroupID.ToString()); | ||
1191 | invString.AddSectionEnd(); | ||
1192 | |||
1193 | if (includeAssets) | ||
1194 | invString.AddNameValueLine("asset_id", item.AssetID.ToString()); | ||
1195 | else | ||
1196 | invString.AddNameValueLine("asset_id", UUID.Zero.ToString()); | ||
1197 | invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); | ||
1198 | invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); | ||
1199 | invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); | ||
1200 | |||
1201 | invString.AddSaleStart(); | ||
1202 | invString.AddNameValueLine("sale_type", "not"); | ||
1203 | invString.AddNameValueLine("sale_price", "0"); | ||
1204 | invString.AddSectionEnd(); | ||
1205 | |||
1206 | invString.AddNameValueLine("name", item.Name + "|"); | ||
1207 | invString.AddNameValueLine("desc", item.Description + "|"); | ||
1208 | |||
1209 | invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); | ||
1210 | invString.AddSectionEnd(); | ||
1211 | } | ||
1190 | 1212 | ||
1191 | invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); | 1213 | Items.LockItemsForRead(false); |
1192 | invString.AddSectionEnd(); | ||
1193 | } | ||
1194 | 1214 | ||
1195 | Items.LockItemsForRead(false); | 1215 | m_inventoryFileData = Utils.StringToBytes(invString.BuildString); |
1196 | 1216 | ||
1197 | m_inventoryFileData = Utils.StringToBytes(invString.BuildString); | 1217 | if (m_inventoryFileData.Length > 2) |
1218 | { | ||
1219 | xferManager.AddNewFile(filename, m_inventoryFileData); | ||
1220 | client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial, | ||
1221 | Util.StringToBytes256(filename)); | ||
1222 | return; | ||
1223 | } | ||
1198 | 1224 | ||
1199 | if (m_inventoryFileData.Length > 2) | 1225 | client.SendTaskInventory(m_part.UUID, 0, new byte[0]); |
1200 | { | ||
1201 | xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); | ||
1202 | client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, | ||
1203 | Util.StringToBytes256(m_inventoryFileName)); | ||
1204 | return; | ||
1205 | } | 1226 | } |
1206 | |||
1207 | client.SendTaskInventory(m_part.UUID, 0, new byte[0]); | ||
1208 | } | 1227 | } |
1209 | 1228 | ||
1210 | /// <summary> | 1229 | /// <summary> |
@@ -1221,10 +1240,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1221 | // if (HasInventoryChanged) | 1240 | // if (HasInventoryChanged) |
1222 | // { | 1241 | // { |
1223 | Items.LockItemsForRead(true); | 1242 | Items.LockItemsForRead(true); |
1224 | datastore.StorePrimInventory(m_part.UUID, Items.Values); | 1243 | try |
1225 | Items.LockItemsForRead(false); | 1244 | { |
1245 | datastore.StorePrimInventory(m_part.UUID, Items.Values); | ||
1246 | } | ||
1247 | catch {} | ||
1226 | 1248 | ||
1227 | HasInventoryChanged = false; | 1249 | HasInventoryChanged = false; |
1250 | |||
1251 | Items.LockItemsForRead(false); | ||
1252 | |||
1253 | |||
1228 | // } | 1254 | // } |
1229 | } | 1255 | } |
1230 | 1256 | ||
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ba25d9b..5a3e554 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -29,7 +29,9 @@ using System; | |||
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,22 +75,60 @@ namespace OpenSim.Region.Framework.Scenes | |||
73 | 75 | ||
74 | public class ScenePresence : EntityBase, IScenePresence | 76 | public class ScenePresence : EntityBase, IScenePresence |
75 | { | 77 | { |
76 | public bool Invisible = false; | 78 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
77 | 79 | ||
78 | // ~ScenePresence() | 80 | // ~ScenePresence() |
79 | // { | 81 | // { |
80 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); | 82 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); |
81 | // } | 83 | // } |
82 | 84 | ||
83 | private void TriggerScenePresenceUpdated() | 85 | public void TriggerScenePresenceUpdated() |
84 | { | 86 | { |
85 | if (m_scene != null) | 87 | if (m_scene != null) |
86 | m_scene.EventManager.TriggerScenePresenceUpdated(this); | 88 | m_scene.EventManager.TriggerScenePresenceUpdated(this); |
87 | } | 89 | } |
88 | 90 | ||
89 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 91 | public bool isNPC { get; private set; } |
92 | |||
93 | public bool Invisible { get; set; } | ||
94 | private PresenceType m_presenceType; | ||
95 | public PresenceType PresenceType { | ||
96 | get {return m_presenceType;} | ||
97 | private set | ||
98 | { | ||
99 | m_presenceType = value; | ||
100 | isNPC = (m_presenceType == PresenceType.Npc); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | private ScenePresenceStateMachine m_stateMachine; | ||
105 | |||
106 | /// <summary> | ||
107 | /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine | ||
108 | /// for more details. | ||
109 | /// </summary> | ||
110 | public ScenePresenceState LifecycleState | ||
111 | { | ||
112 | get | ||
113 | { | ||
114 | return m_stateMachine.GetState(); | ||
115 | } | ||
116 | |||
117 | set | ||
118 | { | ||
119 | m_stateMachine.SetState(value); | ||
120 | } | ||
121 | } | ||
90 | 122 | ||
91 | public PresenceType PresenceType { get; private set; } | 123 | /// <summary> |
124 | /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and | ||
125 | /// the viewer fires these in quick succession. | ||
126 | /// </summary> | ||
127 | /// <remarks> | ||
128 | /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement | ||
129 | /// regulation done there. | ||
130 | /// </remarks> | ||
131 | private object m_completeMovementLock = new object(); | ||
92 | 132 | ||
93 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); | 133 | // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); |
94 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); | 134 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); |
@@ -111,13 +151,100 @@ namespace OpenSim.Region.Framework.Scenes | |||
111 | /// </summary> | 151 | /// </summary> |
112 | public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; | 152 | public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; |
113 | 153 | ||
114 | public UUID currentParcelUUID = UUID.Zero; | 154 | private UUID m_previusParcelUUID = UUID.Zero; |
155 | private UUID m_currentParcelUUID = UUID.Zero; | ||
156 | private bool m_previusParcelHide = false; | ||
157 | private bool m_currentParcelHide = false; | ||
158 | private object parcelLock = new Object(); | ||
159 | |||
160 | public UUID currentParcelUUID | ||
161 | { | ||
162 | get { return m_currentParcelUUID; } | ||
163 | set | ||
164 | { | ||
165 | lock (parcelLock) | ||
166 | { | ||
167 | bool oldhide = m_currentParcelHide; | ||
168 | bool checksame = true; | ||
169 | if (value != m_currentParcelUUID) | ||
170 | { | ||
171 | m_previusParcelHide = m_currentParcelHide; | ||
172 | m_previusParcelUUID = m_currentParcelUUID; | ||
173 | checksame = false; | ||
174 | } | ||
175 | m_currentParcelUUID = value; | ||
176 | m_currentParcelHide = false; | ||
177 | |||
178 | ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y); | ||
179 | if (land != null && !land.LandData.SeeAVs) | ||
180 | m_currentParcelHide = true; | ||
115 | 181 | ||
182 | if (m_previusParcelUUID != UUID.Zero || checksame) | ||
183 | ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame); | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
188 | public void sitSOGmoved() | ||
189 | { | ||
190 | if (IsDeleted || !IsSatOnObject) | ||
191 | //what me? nahh | ||
192 | return; | ||
193 | if (IsInTransit) | ||
194 | return; | ||
195 | |||
196 | ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y); | ||
197 | if (land == null) | ||
198 | return; //?? | ||
199 | UUID parcelID = land.LandData.GlobalID; | ||
200 | if (m_currentParcelUUID != parcelID) | ||
201 | currentParcelUUID = parcelID; | ||
202 | } | ||
203 | |||
204 | |||
205 | public bool ParcelAllowThisAvatarSounds | ||
206 | { | ||
207 | get | ||
208 | { | ||
209 | try | ||
210 | { | ||
211 | lock (parcelLock) | ||
212 | { | ||
213 | ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y); | ||
214 | if (land == null) | ||
215 | return true; | ||
216 | if (land.LandData.AnyAVSounds) | ||
217 | return true; | ||
218 | if (!land.LandData.GroupAVSounds) | ||
219 | return false; | ||
220 | return land.LandData.GroupID == ControllingClient.ActiveGroupId; | ||
221 | } | ||
222 | } | ||
223 | catch | ||
224 | { | ||
225 | return true; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | public bool ParcelHideThisAvatar | ||
231 | { | ||
232 | get | ||
233 | { | ||
234 | return m_currentParcelHide; | ||
235 | } | ||
236 | } | ||
237 | |||
116 | /// <value> | 238 | /// <value> |
117 | /// The animator for this avatar | 239 | /// The animator for this avatar |
118 | /// </value> | 240 | /// </value> |
119 | public ScenePresenceAnimator Animator { get; private set; } | 241 | public ScenePresenceAnimator Animator { get; private set; } |
120 | 242 | ||
243 | /// <value> | ||
244 | /// Server Side Animation Override | ||
245 | /// </value> | ||
246 | public MovementAnimationOverrides Overrides { get; private set; } | ||
247 | public String sitAnimation = "SIT"; | ||
121 | /// <summary> | 248 | /// <summary> |
122 | /// Attachments recorded on this avatar. | 249 | /// Attachments recorded on this avatar. |
123 | /// </summary> | 250 | /// </summary> |
@@ -144,6 +271,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
144 | private Vector3 m_lastVelocity; | 271 | private Vector3 m_lastVelocity; |
145 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); | 272 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); |
146 | 273 | ||
274 | private bool m_followCamAuto = false; | ||
275 | |||
147 | 276 | ||
148 | private Vector3? m_forceToApply; | 277 | private Vector3? m_forceToApply; |
149 | private int m_userFlags; | 278 | private int m_userFlags; |
@@ -159,14 +288,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
159 | set { PhysicsActor.Flying = value; } | 288 | set { PhysicsActor.Flying = value; } |
160 | } | 289 | } |
161 | 290 | ||
162 | // add for fly velocity control | 291 | public bool IsColliding |
163 | private bool FlyingOld {get; set;} | ||
164 | public bool WasFlying | ||
165 | { | ||
166 | get; private set; | ||
167 | } | ||
168 | |||
169 | public bool IsColliding | ||
170 | { | 292 | { |
171 | get { return PhysicsActor != null && PhysicsActor.IsColliding; } | 293 | get { return PhysicsActor != null && PhysicsActor.IsColliding; } |
172 | // We would expect setting IsColliding to be private but it's used by a hack in Scene | 294 | // We would expect setting IsColliding to be private but it's used by a hack in Scene |
@@ -202,7 +324,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
202 | private float m_sitAvatarHeight = 2.0f; | 324 | private float m_sitAvatarHeight = 2.0f; |
203 | 325 | ||
204 | private Vector3 m_lastChildAgentUpdatePosition; | 326 | private Vector3 m_lastChildAgentUpdatePosition; |
205 | private Vector3 m_lastChildAgentUpdateCamPosition; | 327 | // private Vector3 m_lastChildAgentUpdateCamPosition; |
206 | 328 | ||
207 | private const int LAND_VELOCITYMAG_MAX = 12; | 329 | private const int LAND_VELOCITYMAG_MAX = 12; |
208 | 330 | ||
@@ -215,7 +337,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
215 | 337 | ||
216 | protected ulong crossingFromRegion; | 338 | protected ulong crossingFromRegion; |
217 | 339 | ||
218 | private readonly Vector3[] Dir_Vectors = new Vector3[11]; | 340 | private readonly Vector3[] Dir_Vectors = new Vector3[12]; |
219 | 341 | ||
220 | protected Timer m_reprioritization_timer; | 342 | protected Timer m_reprioritization_timer; |
221 | protected bool m_reprioritizing; | 343 | protected bool m_reprioritizing; |
@@ -272,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
272 | /// <summary> | 394 | /// <summary> |
273 | /// Implemented Control Flags | 395 | /// Implemented Control Flags |
274 | /// </summary> | 396 | /// </summary> |
275 | private enum Dir_ControlFlags | 397 | private enum Dir_ControlFlags:uint |
276 | { | 398 | { |
277 | DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, | 399 | DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, |
278 | DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, | 400 | DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, |
@@ -284,6 +406,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
284 | DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, | 406 | DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, |
285 | DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, | 407 | DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, |
286 | DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, | 408 | DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, |
409 | DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS, | ||
287 | DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG | 410 | DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG |
288 | } | 411 | } |
289 | 412 | ||
@@ -292,9 +415,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
292 | /// </summary> | 415 | /// </summary> |
293 | private Vector3 posLastSignificantMove; | 416 | private Vector3 posLastSignificantMove; |
294 | 417 | ||
295 | // For teleports and crossings callbacks | 418 | #region For teleports and crossings callbacks |
296 | string m_callbackURI; | 419 | |
297 | UUID m_originRegionID; | 420 | /// <summary> |
421 | /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address. | ||
422 | /// </summary> | ||
423 | private string m_callbackURI; | ||
424 | |||
425 | /// <summary> | ||
426 | /// Records the region from which this presence originated, if not from login. | ||
427 | /// </summary> | ||
428 | /// <remarks> | ||
429 | /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered | ||
430 | /// CompleteMovement and made the previous child agent a root agent. | ||
431 | /// </remarks> | ||
432 | private UUID m_originRegionID; | ||
433 | |||
434 | /// <summary> | ||
435 | /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing | ||
436 | /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as | ||
437 | /// it is a value type. | ||
438 | /// </summary> | ||
439 | private object m_originRegionIDAccessLock = new object(); | ||
440 | |||
441 | /// <summary> | ||
442 | /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent | ||
443 | /// teleport is reusing the connection. | ||
444 | /// </summary> | ||
445 | /// <remarks>May be refactored or move somewhere else soon.</remarks> | ||
446 | public bool DoNotCloseAfterTeleport { get; set; } | ||
447 | |||
448 | #endregion | ||
298 | 449 | ||
299 | /// <value> | 450 | /// <value> |
300 | /// Script engines present in the scene | 451 | /// Script engines present in the scene |
@@ -311,15 +462,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
311 | /// <summary> | 462 | /// <summary> |
312 | /// Record user movement inputs. | 463 | /// Record user movement inputs. |
313 | /// </summary> | 464 | /// </summary> |
314 | public byte MovementFlag { get; private set; } | 465 | public uint MovementFlag { get; private set; } |
315 | |||
316 | private bool m_updateflag; | ||
317 | 466 | ||
318 | public bool Updated | 467 | /// <summary> |
319 | { | 468 | /// Is the agent stop control flag currently active? |
320 | set { m_updateflag = value; } | 469 | /// </summary> |
321 | get { return m_updateflag; } | 470 | public bool AgentControlStopActive { get; private set; } |
322 | } | ||
323 | 471 | ||
324 | private bool m_invulnerable = true; | 472 | private bool m_invulnerable = true; |
325 | 473 | ||
@@ -346,11 +494,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
346 | } | 494 | } |
347 | 495 | ||
348 | private ulong m_rootRegionHandle; | 496 | private ulong m_rootRegionHandle; |
497 | private Vector3 m_rootRegionPosition = new Vector3(); | ||
349 | 498 | ||
350 | public ulong RegionHandle | 499 | public ulong RegionHandle |
351 | { | 500 | { |
352 | get { return m_rootRegionHandle; } | 501 | get { return m_rootRegionHandle; } |
353 | private set { m_rootRegionHandle = value; } | 502 | private set |
503 | { | ||
504 | m_rootRegionHandle = value; | ||
505 | // position rounded to lower multiple of 256m | ||
506 | m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00); | ||
507 | m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00); | ||
508 | } | ||
354 | } | 509 | } |
355 | 510 | ||
356 | #region Client Camera | 511 | #region Client Camera |
@@ -382,11 +537,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
382 | get | 537 | get |
383 | { | 538 | { |
384 | Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); | 539 | Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); |
385 | 540 | a.Normalize(); | |
386 | if (a == Vector3.Zero) | 541 | return a; |
387 | return a; | ||
388 | |||
389 | return Util.GetNormalizedVector(a); | ||
390 | } | 542 | } |
391 | } | 543 | } |
392 | #endregion | 544 | #endregion |
@@ -426,6 +578,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
426 | } | 578 | } |
427 | } | 579 | } |
428 | 580 | ||
581 | |||
429 | public byte State { get; set; } | 582 | public byte State { get; set; } |
430 | 583 | ||
431 | private AgentManager.ControlFlags m_AgentControlFlags; | 584 | private AgentManager.ControlFlags m_AgentControlFlags; |
@@ -464,6 +617,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
464 | } | 617 | } |
465 | else | 618 | else |
466 | { | 619 | { |
620 | // m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name); | ||
467 | // Obtain the correct position of a seated avatar. | 621 | // Obtain the correct position of a seated avatar. |
468 | // In addition to providing the correct position while | 622 | // In addition to providing the correct position while |
469 | // the avatar is seated, this value will also | 623 | // the avatar is seated, this value will also |
@@ -477,17 +631,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
477 | // in the sim unless the avatar is on a sit target. While | 631 | // in the sim unless the avatar is on a sit target. While |
478 | // on a sit target, m_pos will contain the desired offset | 632 | // on a sit target, m_pos will contain the desired offset |
479 | // without the parent rotation applied. | 633 | // without the parent rotation applied. |
480 | SceneObjectPart sitPart = ParentPart; | 634 | if (ParentPart != null) |
481 | 635 | { | |
482 | if (sitPart != null) | 636 | SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart; |
483 | return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); | 637 | // if (sitPart != null) |
638 | // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); | ||
639 | if (rootPart != null) | ||
640 | return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation()); | ||
641 | } | ||
484 | } | 642 | } |
485 | 643 | ||
486 | return m_pos; | 644 | return m_pos; |
487 | } | 645 | } |
488 | set | 646 | set |
489 | { | 647 | { |
490 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); | 648 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name); |
491 | // Util.PrintCallStack(); | 649 | // Util.PrintCallStack(); |
492 | 650 | ||
493 | if (PhysicsActor != null) | 651 | if (PhysicsActor != null) |
@@ -504,10 +662,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | 662 | ||
505 | // Don't update while sitting. The PhysicsActor above is null whilst sitting. | 663 | // Don't update while sitting. The PhysicsActor above is null whilst sitting. |
506 | if (ParentID == 0) | 664 | if (ParentID == 0) |
507 | { | ||
508 | m_pos = value; | 665 | m_pos = value; |
509 | // ParentPosition = Vector3.Zero; | ||
510 | } | ||
511 | 666 | ||
512 | //m_log.DebugFormat( | 667 | //m_log.DebugFormat( |
513 | // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", | 668 | // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", |
@@ -575,24 +730,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
575 | // Scene.RegionInfo.RegionName, Name, m_velocity); | 730 | // Scene.RegionInfo.RegionName, Name, m_velocity); |
576 | } | 731 | } |
577 | } | 732 | } |
578 | /* | ||
579 | public override Vector3 AngularVelocity | ||
580 | { | ||
581 | get | ||
582 | { | ||
583 | if (PhysicsActor != null) | ||
584 | { | ||
585 | m_rotationalvelocity = PhysicsActor.RotationalVelocity; | ||
586 | |||
587 | // m_log.DebugFormat( | ||
588 | // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", | ||
589 | // m_velocity, Name, Scene.RegionInfo.RegionName); | ||
590 | } | ||
591 | 733 | ||
592 | return m_rotationalvelocity; | ||
593 | } | ||
594 | } | ||
595 | */ | ||
596 | private Quaternion m_bodyRot = Quaternion.Identity; | 734 | private Quaternion m_bodyRot = Quaternion.Identity; |
597 | 735 | ||
598 | /// <summary> | 736 | /// <summary> |
@@ -762,6 +900,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
762 | } | 900 | } |
763 | } | 901 | } |
764 | 902 | ||
903 | |||
904 | /// <summary> | ||
905 | /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running | ||
906 | /// </summary> | ||
907 | /// <remarks> | ||
908 | /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. | ||
909 | /// </remarks> | ||
910 | private const float AgentControlStopSlowVel = 0.2f; | ||
911 | // velocities | ||
912 | public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently | ||
913 | public const float AgentControlNormalVel = 1.0f; | ||
914 | |||
915 | // old normal speed was tuned to match sl normal plus Fast modifiers | ||
916 | // so we need to rescale it | ||
765 | private float m_speedModifier = 1.0f; | 917 | private float m_speedModifier = 1.0f; |
766 | 918 | ||
767 | public float SpeedModifier | 919 | public float SpeedModifier |
@@ -797,13 +949,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
797 | 949 | ||
798 | public ScenePresence( | 950 | public ScenePresence( |
799 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) | 951 | IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) |
800 | { | 952 | { |
953 | Invisible = false; | ||
801 | AttachmentsSyncLock = new Object(); | 954 | AttachmentsSyncLock = new Object(); |
802 | AllowMovement = true; | 955 | AllowMovement = true; |
803 | IsChildAgent = true; | 956 | IsChildAgent = true; |
804 | IsLoggingIn = false; | 957 | IsLoggingIn = false; |
805 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; | 958 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; |
806 | Animator = new ScenePresenceAnimator(this); | 959 | Animator = new ScenePresenceAnimator(this); |
960 | Overrides = new MovementAnimationOverrides(); | ||
807 | PresenceType = type; | 961 | PresenceType = type; |
808 | DrawDistance = world.DefaultDrawDistance; | 962 | DrawDistance = world.DefaultDrawDistance; |
809 | RegionHandle = world.RegionInfo.RegionHandle; | 963 | RegionHandle = world.RegionInfo.RegionHandle; |
@@ -813,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
813 | m_name = String.Format("{0} {1}", Firstname, Lastname); | 967 | m_name = String.Format("{0} {1}", Firstname, Lastname); |
814 | m_scene = world; | 968 | m_scene = world; |
815 | m_uuid = client.AgentId; | 969 | m_uuid = client.AgentId; |
816 | LocalId = m_scene.AllocateLocalId(); | 970 | LocalId = m_scene.AllocatePresenceLocalId(); |
817 | 971 | ||
818 | UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); | 972 | UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); |
819 | if (account != null) | 973 | if (account != null) |
@@ -826,7 +980,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
826 | 980 | ||
827 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 981 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
828 | if (gm != null) | 982 | if (gm != null) |
829 | Grouptitle = gm.GetGroupTitle(m_uuid); | 983 | Grouptitle = gm.GetGroupTitle(m_uuid); |
830 | 984 | ||
831 | m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); | 985 | m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); |
832 | 986 | ||
@@ -843,6 +997,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
843 | SetDirectionVectors(); | 997 | SetDirectionVectors(); |
844 | 998 | ||
845 | Appearance = appearance; | 999 | Appearance = appearance; |
1000 | |||
1001 | m_stateMachine = new ScenePresenceStateMachine(this); | ||
846 | } | 1002 | } |
847 | 1003 | ||
848 | private void RegionHeartbeatEnd(Scene scene) | 1004 | private void RegionHeartbeatEnd(Scene scene) |
@@ -876,6 +1032,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
876 | { | 1032 | { |
877 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; | 1033 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; |
878 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; | 1034 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; |
1035 | ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate; | ||
879 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; | 1036 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; |
880 | ControllingClient.OnAgentSit += HandleAgentSit; | 1037 | ControllingClient.OnAgentSit += HandleAgentSit; |
881 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; | 1038 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; |
@@ -892,22 +1049,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
892 | 1049 | ||
893 | private void SetDirectionVectors() | 1050 | private void SetDirectionVectors() |
894 | { | 1051 | { |
895 | Dir_Vectors[0] = Vector3.UnitX; //FORWARD | 1052 | Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD |
896 | Dir_Vectors[1] = -Vector3.UnitX; //BACK | 1053 | Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK |
897 | Dir_Vectors[2] = Vector3.UnitY; //LEFT | 1054 | Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT |
898 | Dir_Vectors[3] = -Vector3.UnitY; //RIGHT | 1055 | Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT |
899 | Dir_Vectors[4] = Vector3.UnitZ; //UP | 1056 | Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP |
900 | Dir_Vectors[5] = -Vector3.UnitZ; //DOWN | 1057 | Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN |
901 | Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE | 1058 | Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE |
902 | Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE | 1059 | Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE |
903 | Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE | 1060 | Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE |
904 | Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE | 1061 | Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE |
905 | Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge | 1062 | Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge |
906 | } | 1063 | Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge |
907 | 1064 | } | |
1065 | |||
1066 | /* dont see any use for this | ||
908 | private Vector3[] GetWalkDirectionVectors() | 1067 | private Vector3[] GetWalkDirectionVectors() |
909 | { | 1068 | { |
910 | Vector3[] vector = new Vector3[11]; | 1069 | Vector3[] vector = new Vector3[12]; |
911 | vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD | 1070 | vector[0] = new Vector3(CameraUpAxis.Z, 0f, -CameraAtAxis.Z); //FORWARD |
912 | vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK | 1071 | vector[1] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK |
913 | vector[2] = Vector3.UnitY; //LEFT | 1072 | vector[2] = Vector3.UnitY; //LEFT |
@@ -918,10 +1077,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
918 | vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE | 1077 | vector[7] = new Vector3(-CameraUpAxis.Z, 0f, CameraAtAxis.Z); //BACK_NUDGE |
919 | vector[8] = Vector3.UnitY; //LEFT_NUDGE | 1078 | vector[8] = Vector3.UnitY; //LEFT_NUDGE |
920 | vector[9] = -Vector3.UnitY; //RIGHT_NUDGE | 1079 | vector[9] = -Vector3.UnitY; //RIGHT_NUDGE |
921 | vector[10] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE | 1080 | vector[10] = new Vector3(CameraAtAxis.Z, 0f, CameraUpAxis.Z); //UP_NUDGE |
1081 | vector[11] = new Vector3(-CameraAtAxis.Z, 0f, -CameraUpAxis.Z); //DOWN_NUDGE | ||
922 | return vector; | 1082 | return vector; |
923 | } | 1083 | } |
924 | 1084 | */ | |
925 | #endregion | 1085 | #endregion |
926 | 1086 | ||
927 | #region Status Methods | 1087 | #region Status Methods |
@@ -929,6 +1089,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
929 | /// <summary> | 1089 | /// <summary> |
930 | /// Turns a child agent into a root agent. | 1090 | /// Turns a child agent into a root agent. |
931 | /// </summary> | 1091 | /// </summary> |
1092 | /// <remarks> | ||
932 | /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the | 1093 | /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the |
933 | /// avatar is actual in the sim. They can perform all actions. | 1094 | /// avatar is actual in the sim. They can perform all actions. |
934 | /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, | 1095 | /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, |
@@ -936,90 +1097,81 @@ namespace OpenSim.Region.Framework.Scenes | |||
936 | /// | 1097 | /// |
937 | /// This method is on the critical path for transferring an avatar from one region to another. Delay here | 1098 | /// This method is on the critical path for transferring an avatar from one region to another. Delay here |
938 | /// delays that crossing. | 1099 | /// delays that crossing. |
939 | /// </summary> | 1100 | /// </remarks> |
940 | public void MakeRootAgent(Vector3 pos, bool isFlying) | 1101 | |
1102 | |||
1103 | // only in use as part of completemovement | ||
1104 | // other uses need fix | ||
1105 | private bool MakeRootAgent(Vector3 pos, bool isFlying) | ||
941 | { | 1106 | { |
942 | m_log.DebugFormat( | 1107 | int ts = Util.EnvironmentTickCount(); |
943 | "[SCENE]: Upgrading child to root agent for {0} in {1}", | ||
944 | Name, m_scene.RegionInfo.RegionName); | ||
945 | 1108 | ||
946 | if (ParentUUID != UUID.Zero) | 1109 | lock (m_completeMovementLock) |
947 | { | 1110 | { |
948 | m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); | 1111 | if (!IsChildAgent) |
949 | SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); | 1112 | return false; |
950 | if (part == null) | 1113 | |
1114 | m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1115 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | ||
1116 | |||
1117 | // m_log.InfoFormat( | ||
1118 | // "[SCENE]: Upgrading child to root agent for {0} in {1}", | ||
1119 | // Name, m_scene.RegionInfo.RegionName); | ||
1120 | |||
1121 | if (ParentUUID != UUID.Zero) | ||
951 | { | 1122 | { |
952 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); | 1123 | m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); |
1124 | SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); | ||
1125 | if (part == null) | ||
1126 | { | ||
1127 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); | ||
1128 | ParentID = 0; | ||
1129 | ParentPart = null; | ||
1130 | PrevSitOffset = Vector3.Zero; | ||
1131 | HandleForceReleaseControls(ControllingClient, UUID); // needs testing | ||
1132 | IsLoggingIn = false; | ||
1133 | } | ||
1134 | else | ||
1135 | { | ||
1136 | part.ParentGroup.AddAvatar(UUID); | ||
1137 | if (part.SitTargetPosition != Vector3.Zero) | ||
1138 | part.SitTargetAvatar = UUID; | ||
1139 | ParentID = part.LocalId; | ||
1140 | ParentPart = part; | ||
1141 | m_pos = PrevSitOffset; | ||
1142 | pos = part.GetWorldPosition(); | ||
1143 | } | ||
1144 | ParentUUID = UUID.Zero; | ||
953 | } | 1145 | } |
954 | else | 1146 | else |
955 | { | 1147 | { |
956 | part.ParentGroup.AddAvatar(UUID); | 1148 | IsLoggingIn = false; |
957 | if (part.SitTargetPosition != Vector3.Zero) | ||
958 | part.SitTargetAvatar = UUID; | ||
959 | // ParentPosition = part.GetWorldPosition(); | ||
960 | ParentID = part.LocalId; | ||
961 | ParentPart = part; | ||
962 | m_pos = PrevSitOffset; | ||
963 | // pos = ParentPosition; | ||
964 | pos = part.GetWorldPosition(); | ||
965 | } | 1149 | } |
966 | ParentUUID = UUID.Zero; | ||
967 | 1150 | ||
968 | IsChildAgent = false; | 1151 | IsChildAgent = false; |
969 | |||
970 | // Animator.TrySetMovementAnimation("SIT"); | ||
971 | } | ||
972 | else | ||
973 | { | ||
974 | IsChildAgent = false; | ||
975 | IsLoggingIn = false; | ||
976 | } | 1152 | } |
977 | 1153 | ||
978 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | 1154 | m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
979 | 1155 | ||
980 | IsChildAgent = false; | 1156 | // Must reset this here so that a teleport to a region next to an existing region does not keep the flag |
1157 | // set and prevent the close of the connection on a subsequent re-teleport. | ||
1158 | // Should not be needed if we are not trying to tell this region to close | ||
1159 | // DoNotCloseAfterTeleport = false; | ||
981 | 1160 | ||
982 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 1161 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
983 | if (gm != null) | 1162 | if (gm != null) |
984 | Grouptitle = gm.GetGroupTitle(m_uuid); | 1163 | Grouptitle = gm.GetGroupTitle(m_uuid); |
985 | 1164 | ||
1165 | m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1166 | |||
986 | RegionHandle = m_scene.RegionInfo.RegionHandle; | 1167 | RegionHandle = m_scene.RegionInfo.RegionHandle; |
987 | 1168 | ||
988 | m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); | 1169 | m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); |
1170 | m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
989 | 1171 | ||
990 | UUID groupUUID = UUID.Zero; | ||
991 | string GroupName = string.Empty; | ||
992 | ulong groupPowers = 0; | ||
993 | |||
994 | // ---------------------------------- | ||
995 | // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status | ||
996 | try | ||
997 | { | ||
998 | if (gm != null) | ||
999 | { | ||
1000 | groupUUID = ControllingClient.ActiveGroupId; | ||
1001 | GroupRecord record = gm.GetGroupRecord(groupUUID); | ||
1002 | if (record != null) | ||
1003 | GroupName = record.GroupName; | ||
1004 | GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid); | ||
1005 | if (groupMembershipData != null) | ||
1006 | groupPowers = groupMembershipData.GroupPowers; | ||
1007 | } | ||
1008 | ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName, | ||
1009 | Grouptitle); | ||
1010 | } | ||
1011 | catch (Exception e) | ||
1012 | { | ||
1013 | m_log.Debug("[AGENTUPDATE]: " + e.ToString()); | ||
1014 | } | ||
1015 | // ------------------------------------ | ||
1016 | 1172 | ||
1017 | if (ParentID == 0) | 1173 | if (ParentID == 0) |
1018 | { | 1174 | { |
1019 | // Moved this from SendInitialData to ensure that Appearance is initialized | ||
1020 | // before the inventory is processed in MakeRootAgent. This fixes a race condition | ||
1021 | // related to the handling of attachments | ||
1022 | //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); | ||
1023 | if (m_scene.TestBorderCross(pos, Cardinals.E)) | 1175 | if (m_scene.TestBorderCross(pos, Cardinals.E)) |
1024 | { | 1176 | { |
1025 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); | 1177 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); |
@@ -1053,7 +1205,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1053 | 1205 | ||
1054 | if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) | 1206 | if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) |
1055 | posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; | 1207 | posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; |
1056 | 1208 | ||
1057 | float newPosZ = posZLimit + localAVHeight / 2; | 1209 | float newPosZ = posZLimit + localAVHeight / 2; |
1058 | if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) | 1210 | if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) |
1059 | { | 1211 | { |
@@ -1061,6 +1213,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1061 | } | 1213 | } |
1062 | AbsolutePosition = pos; | 1214 | AbsolutePosition = pos; |
1063 | 1215 | ||
1216 | |||
1064 | if (m_teleportFlags == TeleportFlags.Default) | 1217 | if (m_teleportFlags == TeleportFlags.Default) |
1065 | { | 1218 | { |
1066 | Vector3 vel = Velocity; | 1219 | Vector3 vel = Velocity; |
@@ -1071,12 +1224,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1071 | else | 1224 | else |
1072 | AddToPhysicalScene(isFlying); | 1225 | AddToPhysicalScene(isFlying); |
1073 | 1226 | ||
1074 | // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a | ||
1075 | // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it | ||
1076 | // since it requires a physics actor to be present. If it is left any later, then physics appears to reset | ||
1077 | // the value to a negative position which does not trigger the border cross. | ||
1078 | // This may not be the best location for this. | ||
1079 | CheckForBorderCrossing(); | ||
1080 | 1227 | ||
1081 | if (ForceFly) | 1228 | if (ForceFly) |
1082 | { | 1229 | { |
@@ -1086,66 +1233,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
1086 | { | 1233 | { |
1087 | Flying = false; | 1234 | Flying = false; |
1088 | } | 1235 | } |
1089 | } | ||
1090 | // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying | ||
1091 | // avatar to return to the standing position in mid-air. On login it looks like this is being sent | ||
1092 | // elsewhere anyway | ||
1093 | // Animator.SendAnimPack(); | ||
1094 | 1236 | ||
1095 | m_scene.SwapRootAgentCount(false); | 1237 | // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a |
1238 | // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it | ||
1239 | // since it requires a physics actor to be present. If it is left any later, then physics appears to reset | ||
1240 | // the value to a negative position which does not trigger the border cross. | ||
1241 | // This may not be the best location for this. | ||
1096 | 1242 | ||
1097 | // The initial login scene presence is already root when it gets here | ||
1098 | // and it has already rezzed the attachments and started their scripts. | ||
1099 | // We do the following only for non-login agents, because their scripts | ||
1100 | // haven't started yet. | ||
1101 | if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0) | ||
1102 | { | ||
1103 | // Viewers which have a current outfit folder will actually rez their own attachments. However, | ||
1104 | // viewers without (e.g. v1 viewers) will not, so we still need to make this call. | ||
1105 | if (Scene.AttachmentsModule != null) | ||
1106 | Util.FireAndForget( | ||
1107 | o => | ||
1108 | { | ||
1109 | // if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None) | ||
1110 | // System.Threading.Thread.Sleep(7000); | ||
1111 | 1243 | ||
1112 | Scene.AttachmentsModule.RezAttachments(this); | 1244 | // its not |
1113 | }); | 1245 | // CheckForBorderCrossing(); |
1114 | } | 1246 | } |
1115 | else | 1247 | |
1116 | { | 1248 | m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1117 | // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT | 1249 | m_scene.SwapRootAgentCount(false); |
1118 | // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently | ||
1119 | // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are | ||
1120 | // not transporting the required data. | ||
1121 | lock (m_attachments) | ||
1122 | { | ||
1123 | if (HasAttachments()) | ||
1124 | { | ||
1125 | m_log.DebugFormat( | ||
1126 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | ||
1127 | |||
1128 | // Resume scripts | ||
1129 | Util.FireAndForget(delegate(object x) { | ||
1130 | foreach (SceneObjectGroup sog in m_attachments) | ||
1131 | { | ||
1132 | sog.ScheduleGroupForFullUpdate(); | ||
1133 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | ||
1134 | sog.ResumeScripts(); | ||
1135 | } | ||
1136 | }); | ||
1137 | } | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | SendAvatarDataToAllAgents(); | ||
1142 | 1250 | ||
1143 | // send the animations of the other presences to me | ||
1144 | m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) | ||
1145 | { | ||
1146 | if (presence != this) | ||
1147 | presence.Animator.SendAnimPackToClient(ControllingClient); | ||
1148 | }); | ||
1149 | 1251 | ||
1150 | // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will | 1252 | // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will |
1151 | // stall on the border crossing since the existing child agent will still have the last movement | 1253 | // stall on the border crossing since the existing child agent will still have the last movement |
@@ -1154,8 +1256,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1154 | MovementFlag = 0; | 1256 | MovementFlag = 0; |
1155 | 1257 | ||
1156 | m_scene.EventManager.TriggerOnMakeRootAgent(this); | 1258 | m_scene.EventManager.TriggerOnMakeRootAgent(this); |
1259 | m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1157 | 1260 | ||
1158 | m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; | 1261 | return true; |
1159 | } | 1262 | } |
1160 | 1263 | ||
1161 | public int GetStateSource() | 1264 | public int GetStateSource() |
@@ -1181,11 +1284,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1181 | /// It doesn't get called for a teleport. Reason being, an agent that | 1284 | /// It doesn't get called for a teleport. Reason being, an agent that |
1182 | /// teleports out may not end up anywhere near this region | 1285 | /// teleports out may not end up anywhere near this region |
1183 | /// </remarks> | 1286 | /// </remarks> |
1184 | public void MakeChildAgent() | 1287 | public void MakeChildAgent(ulong newRegionHandle) |
1185 | { | 1288 | { |
1186 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; | 1289 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; |
1187 | 1290 | ||
1188 | m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); | 1291 | RegionHandle = newRegionHandle; |
1292 | |||
1293 | m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}", | ||
1294 | Name, Scene.RegionInfo.RegionName, newRegionHandle); | ||
1295 | |||
1296 | // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating | ||
1297 | // from the source simulator has completed on a V2 teleport. | ||
1298 | lock (m_originRegionIDAccessLock) | ||
1299 | m_originRegionID = UUID.Zero; | ||
1189 | 1300 | ||
1190 | // Reset these so that teleporting in and walking out isn't seen | 1301 | // Reset these so that teleporting in and walking out isn't seen |
1191 | // as teleporting back | 1302 | // as teleporting back |
@@ -1200,7 +1311,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1200 | else | 1311 | else |
1201 | Animator.ResetAnimations(); | 1312 | Animator.ResetAnimations(); |
1202 | 1313 | ||
1203 | 1314 | ||
1204 | // m_log.DebugFormat( | 1315 | // m_log.DebugFormat( |
1205 | // "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", | 1316 | // "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", |
1206 | // Name, UUID, m_scene.RegionInfo.RegionName); | 1317 | // Name, UUID, m_scene.RegionInfo.RegionName); |
@@ -1214,8 +1325,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1214 | RemoveFromPhysicalScene(); | 1325 | RemoveFromPhysicalScene(); |
1215 | ParentID = 0; // Child agents can't be sitting | 1326 | ParentID = 0; // Child agents can't be sitting |
1216 | 1327 | ||
1328 | // we dont have land information for child | ||
1329 | m_previusParcelHide = false; | ||
1330 | m_previusParcelUUID = UUID.Zero; | ||
1331 | m_currentParcelHide = false; | ||
1332 | m_currentParcelUUID = UUID.Zero; | ||
1217 | // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into | 1333 | // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into |
1218 | 1334 | ||
1335 | CollisionPlane = Vector4.UnitW; | ||
1336 | |||
1219 | m_scene.EventManager.TriggerOnMakeChildAgent(this); | 1337 | m_scene.EventManager.TriggerOnMakeChildAgent(this); |
1220 | } | 1338 | } |
1221 | 1339 | ||
@@ -1308,7 +1426,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
1308 | 1426 | ||
1309 | public void StopFlying() | 1427 | public void StopFlying() |
1310 | { | 1428 | { |
1311 | ControllingClient.StopFlying(this); | 1429 | if (IsInTransit) |
1430 | return; | ||
1431 | |||
1432 | Vector3 pos = AbsolutePosition; | ||
1433 | if (Appearance.AvatarHeight != 127.0f) | ||
1434 | pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); | ||
1435 | else | ||
1436 | pos += new Vector3(0f, 0f, (1.56f / 6f)); | ||
1437 | |||
1438 | AbsolutePosition = pos; | ||
1439 | |||
1440 | // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. | ||
1441 | // Collision plane below the avatar's position a 6th of the avatar's height is suitable. | ||
1442 | // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a | ||
1443 | // certain amount.. because the LLClient wouldn't land in that situation anyway. | ||
1444 | |||
1445 | // why are we still testing for this really old height value default??? | ||
1446 | if (Appearance.AvatarHeight != 127.0f) | ||
1447 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f); | ||
1448 | else | ||
1449 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); | ||
1450 | |||
1451 | SendAgentTerseUpdate(this); | ||
1312 | } | 1452 | } |
1313 | 1453 | ||
1314 | /// <summary> | 1454 | /// <summary> |
@@ -1428,6 +1568,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1428 | } | 1568 | } |
1429 | } | 1569 | } |
1430 | 1570 | ||
1571 | public void DropThisRootRegionFromNeighbours() | ||
1572 | { | ||
1573 | ulong handle = m_scene.RegionInfo.RegionHandle; | ||
1574 | RemoveNeighbourRegion(handle); | ||
1575 | Scene.CapsModule.DropChildSeed(UUID, handle); | ||
1576 | } | ||
1577 | |||
1578 | |||
1431 | public Dictionary<ulong, string> KnownRegions | 1579 | public Dictionary<ulong, string> KnownRegions |
1432 | { | 1580 | { |
1433 | get | 1581 | get |
@@ -1482,6 +1630,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
1482 | 1630 | ||
1483 | } | 1631 | } |
1484 | 1632 | ||
1633 | private bool WaitForUpdateAgent(IClientAPI client) | ||
1634 | { | ||
1635 | // Before the source region executes UpdateAgent | ||
1636 | // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, | ||
1637 | // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the | ||
1638 | // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero | ||
1639 | int count = 50; | ||
1640 | UUID originID; | ||
1641 | |||
1642 | lock (m_originRegionIDAccessLock) | ||
1643 | originID = m_originRegionID; | ||
1644 | |||
1645 | while (originID.Equals(UUID.Zero) && count-- > 0) | ||
1646 | { | ||
1647 | lock (m_originRegionIDAccessLock) | ||
1648 | originID = m_originRegionID; | ||
1649 | |||
1650 | m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name); | ||
1651 | Thread.Sleep(200); | ||
1652 | } | ||
1653 | |||
1654 | if (originID.Equals(UUID.Zero)) | ||
1655 | { | ||
1656 | // Movement into region will fail | ||
1657 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); | ||
1658 | return false; | ||
1659 | } | ||
1660 | |||
1661 | return true; | ||
1662 | } | ||
1663 | |||
1485 | /// <summary> | 1664 | /// <summary> |
1486 | /// Complete Avatar's movement into the region. | 1665 | /// Complete Avatar's movement into the region. |
1487 | /// </summary> | 1666 | /// </summary> |
@@ -1493,53 +1672,88 @@ namespace OpenSim.Region.Framework.Scenes | |||
1493 | /// </param> | 1672 | /// </param> |
1494 | public void CompleteMovement(IClientAPI client, bool openChildAgents) | 1673 | public void CompleteMovement(IClientAPI client, bool openChildAgents) |
1495 | { | 1674 | { |
1496 | // DateTime startTime = DateTime.Now; | 1675 | int ts = Util.EnvironmentTickCount(); |
1497 | 1676 | ||
1498 | m_log.DebugFormat( | 1677 | m_log.InfoFormat( |
1499 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", | 1678 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", |
1500 | client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); | 1679 | client.Name, Scene.Name, AbsolutePosition); |
1501 | 1680 | ||
1502 | Vector3 look = Velocity; | 1681 | m_inTransit = true; |
1503 | 1682 | ||
1504 | // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) | 1683 | try |
1505 | if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) | ||
1506 | { | 1684 | { |
1507 | look = new Vector3(0.99f, 0.042f, 0); | 1685 | // Make sure it's not a login agent. We don't want to wait for updates during login |
1508 | } | 1686 | if (!isNPC && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) |
1687 | { | ||
1509 | 1688 | ||
1510 | // Prevent teleporting to an underground location | 1689 | // Let's wait until UpdateAgent (called by departing region) is done |
1511 | // (may crash client otherwise) | 1690 | if (!WaitForUpdateAgent(client)) |
1512 | // | 1691 | // The sending region never sent the UpdateAgent data, we have to refuse |
1513 | Vector3 pos = AbsolutePosition; | 1692 | return; |
1514 | float ground = m_scene.GetGroundHeight(pos.X, pos.Y); | 1693 | } |
1515 | if (pos.Z < ground + 1.5f) | ||
1516 | { | ||
1517 | pos.Z = ground + 1.5f; | ||
1518 | AbsolutePosition = pos; | ||
1519 | } | ||
1520 | 1694 | ||
1521 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1695 | m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1522 | MakeRootAgent(AbsolutePosition, flying); | ||
1523 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | ||
1524 | 1696 | ||
1525 | // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); | 1697 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1526 | 1698 | ||
1527 | if ((m_callbackURI != null) && !m_callbackURI.Equals("")) | 1699 | if (!MakeRootAgent(AbsolutePosition, flying)) |
1528 | { | 1700 | { |
1529 | // We cannot sleep here since this would hold up the inbound packet processing thread, as | 1701 | m_log.DebugFormat( |
1530 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release | 1702 | "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", |
1531 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete | 1703 | Name, Scene.Name); |
1532 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this | 1704 | |
1533 | // region as the current region, meaning that a close sent before then will fail the teleport. | 1705 | return; |
1534 | // System.Threading.Thread.Sleep(2000); | 1706 | } |
1535 | 1707 | ||
1536 | m_log.DebugFormat( | 1708 | m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1537 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | ||
1538 | client.Name, client.AgentId, m_callbackURI); | ||
1539 | 1709 | ||
1540 | Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); | 1710 | Vector3 look = Lookat; |
1541 | m_callbackURI = null; | 1711 | if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01)) |
1542 | } | 1712 | { |
1713 | look = Velocity; | ||
1714 | look.Z = 0; | ||
1715 | look.Normalize(); | ||
1716 | if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) ) | ||
1717 | look = new Vector3(0.99f, 0.042f, 0); | ||
1718 | } | ||
1719 | |||
1720 | if (!IsChildAgent && !isNPC) | ||
1721 | { | ||
1722 | InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (AssetType)46); | ||
1723 | if (cof == null) | ||
1724 | COF = UUID.Zero; | ||
1725 | else | ||
1726 | COF = cof.ID; | ||
1727 | |||
1728 | m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF); | ||
1729 | } | ||
1730 | |||
1731 | // Tell the client that we're totally ready | ||
1732 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | ||
1733 | |||
1734 | m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1735 | |||
1736 | if (!string.IsNullOrEmpty(m_callbackURI)) | ||
1737 | { | ||
1738 | // We cannot sleep here since this would hold up the inbound packet processing thread, as | ||
1739 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release | ||
1740 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete | ||
1741 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this | ||
1742 | // region as the current region, meaning that a close sent before then will fail the teleport. | ||
1743 | // System.Threading.Thread.Sleep(2000); | ||
1744 | |||
1745 | m_log.DebugFormat( | ||
1746 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | ||
1747 | client.Name, client.AgentId, m_callbackURI); | ||
1748 | |||
1749 | UUID originID; | ||
1750 | |||
1751 | lock (m_originRegionIDAccessLock) | ||
1752 | originID = m_originRegionID; | ||
1753 | |||
1754 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | ||
1755 | m_callbackURI = null; | ||
1756 | } | ||
1543 | // else | 1757 | // else |
1544 | // { | 1758 | // { |
1545 | // m_log.DebugFormat( | 1759 | // m_log.DebugFormat( |
@@ -1547,34 +1761,181 @@ namespace OpenSim.Region.Framework.Scenes | |||
1547 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); | 1761 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); |
1548 | // } | 1762 | // } |
1549 | 1763 | ||
1550 | ValidateAndSendAppearanceAndAgentData(); | 1764 | m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1551 | 1765 | ||
1552 | // Create child agents in neighbouring regions | 1766 | m_previusParcelHide = false; |
1553 | if (openChildAgents && !IsChildAgent) | 1767 | m_previusParcelUUID = UUID.Zero; |
1554 | { | 1768 | m_currentParcelHide = false; |
1769 | m_currentParcelUUID = UUID.Zero; | ||
1555 | 1770 | ||
1556 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 1771 | // send initial land overlay and parcel |
1557 | if (m_agentTransfer != null) | 1772 | ILandChannel landch = m_scene.LandChannel; |
1558 | m_agentTransfer.EnableChildAgents(this); | 1773 | if (landch != null) |
1774 | landch.sendClientInitialLandInfo(client); | ||
1559 | 1775 | ||
1560 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); | 1776 | if (!IsChildAgent) |
1561 | if (friendsModule != null) | 1777 | { |
1562 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | ||
1563 | 1778 | ||
1564 | } | 1779 | // ValidateAndSendAppearanceAndAgentData(); |
1565 | 1780 | ||
1566 | // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region | 1781 | // do it here in line |
1567 | // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. | 1782 | // so sequence is clear |
1568 | // This may be due to viewer code or it may be something we're not doing properly simulator side. | 1783 | |
1569 | lock (m_attachments) | 1784 | // verify baked textures and cache |
1785 | |||
1786 | |||
1787 | bool cachedbaked = false; | ||
1788 | |||
1789 | if (isNPC) | ||
1790 | cachedbaked = true; | ||
1791 | else | ||
1792 | { | ||
1793 | if (m_scene.AvatarFactory != null) | ||
1794 | cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this); | ||
1795 | |||
1796 | // not sure we need this | ||
1797 | if (!cachedbaked) | ||
1798 | { | ||
1799 | if (m_scene.AvatarFactory != null) | ||
1800 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); | ||
1801 | } | ||
1802 | } | ||
1803 | |||
1804 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
1805 | |||
1806 | // send avatar object to all presences including us, so they cross it into region | ||
1807 | // then hide if necessary | ||
1808 | SendInitialAvatarDataToAllAgents(allpresences); | ||
1809 | |||
1810 | // send this look | ||
1811 | SendAppearanceToAgent(this); | ||
1812 | |||
1813 | // send this animations | ||
1814 | |||
1815 | UUID[] animIDs = null; | ||
1816 | int[] animseqs = null; | ||
1817 | UUID[] animsobjs = null; | ||
1818 | |||
1819 | if (Animator != null) | ||
1820 | Animator.GetArrays(out animIDs, out animseqs, out animsobjs); | ||
1821 | |||
1822 | bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null); | ||
1823 | |||
1824 | if(haveAnims) | ||
1825 | SendAnimPackToAgent(this, animIDs, animseqs, animsobjs); | ||
1826 | |||
1827 | // we should be able to receive updates, etc | ||
1828 | // so release them | ||
1829 | m_inTransit = false; | ||
1830 | |||
1831 | // send look and animations to others | ||
1832 | // if not cached we send greys | ||
1833 | // uncomented if will wait till avatar does baking | ||
1834 | //if (cachedbaked) | ||
1835 | { | ||
1836 | foreach (ScenePresence p in allpresences) | ||
1837 | { | ||
1838 | if (p == this) | ||
1839 | continue; | ||
1840 | |||
1841 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
1842 | continue; | ||
1843 | |||
1844 | SendAppearanceToAgentNF(p); | ||
1845 | if (haveAnims) | ||
1846 | SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs); | ||
1847 | } | ||
1848 | } // greys if | ||
1849 | |||
1850 | m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1851 | |||
1852 | // attachments | ||
1853 | |||
1854 | if (isNPC || (TeleportFlags & TeleportFlags.ViaLogin) != 0) | ||
1855 | { | ||
1856 | if (Scene.AttachmentsModule != null) | ||
1857 | // Util.FireAndForget( | ||
1858 | // o => | ||
1859 | // { | ||
1860 | Scene.AttachmentsModule.RezAttachments(this); | ||
1861 | // }); | ||
1862 | } | ||
1863 | else | ||
1864 | { | ||
1865 | if (m_attachments.Count > 0) | ||
1866 | { | ||
1867 | m_log.DebugFormat( | ||
1868 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | ||
1869 | |||
1870 | foreach(SceneObjectGroup sog in m_attachments) | ||
1871 | { | ||
1872 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | ||
1873 | sog.ResumeScripts(); | ||
1874 | } | ||
1875 | |||
1876 | foreach (ScenePresence p in allpresences) | ||
1877 | { | ||
1878 | if (p == this) | ||
1879 | { | ||
1880 | SendTerseUpdateToAgentNF(this); | ||
1881 | SendAttachmentsToAgentNF(this); | ||
1882 | continue; | ||
1883 | } | ||
1884 | |||
1885 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
1886 | continue; | ||
1887 | |||
1888 | SendTerseUpdateToAgentNF(p); | ||
1889 | SendAttachmentsToAgentNF(p); | ||
1890 | } | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1895 | |||
1896 | // Create child agents in neighbouring regions | ||
1897 | if (openChildAgents) | ||
1898 | { | ||
1899 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | ||
1900 | if (m_agentTransfer != null) | ||
1901 | { | ||
1902 | m_agentTransfer.EnableChildAgents(this); | ||
1903 | } | ||
1904 | } | ||
1905 | } | ||
1906 | |||
1907 | m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1908 | |||
1909 | // send the rest of the world | ||
1910 | if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide) | ||
1911 | SendInitialDataToMe(); | ||
1912 | |||
1913 | m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1914 | |||
1915 | if (!IsChildAgent && openChildAgents) | ||
1916 | { | ||
1917 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); | ||
1918 | if (friendsModule != null) | ||
1919 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | ||
1920 | |||
1921 | m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
1922 | |||
1923 | } | ||
1924 | } | ||
1925 | finally | ||
1570 | { | 1926 | { |
1571 | foreach (SceneObjectGroup sog in m_attachments) | 1927 | m_inTransit = false; |
1572 | sog.ScheduleGroupForFullUpdate(); | ||
1573 | } | 1928 | } |
1929 | // if hide force a check | ||
1930 | // if (!IsChildAgent && newhide) | ||
1931 | // { | ||
1932 | // ParcelLoginCheck(m_currentParcelUUID); | ||
1933 | // m_currentParcelHide = newhide; | ||
1934 | // } | ||
1574 | 1935 | ||
1575 | // m_log.DebugFormat( | 1936 | m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; |
1576 | // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", | 1937 | |
1577 | // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); | 1938 | m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
1578 | } | 1939 | } |
1579 | 1940 | ||
1580 | /// <summary> | 1941 | /// <summary> |
@@ -1655,9 +2016,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1655 | /// </summary> | 2016 | /// </summary> |
1656 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | 2017 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) |
1657 | { | 2018 | { |
1658 | // m_log.DebugFormat( | 2019 | //m_log.DebugFormat( |
1659 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", | 2020 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", |
1660 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | 2021 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); |
1661 | 2022 | ||
1662 | if (IsChildAgent) | 2023 | if (IsChildAgent) |
1663 | { | 2024 | { |
@@ -1665,9 +2026,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1665 | return; | 2026 | return; |
1666 | } | 2027 | } |
1667 | 2028 | ||
1668 | ++m_movementUpdateCount; | 2029 | if (IsInTransit) |
1669 | if (m_movementUpdateCount < 1) | 2030 | return; |
1670 | m_movementUpdateCount = 1; | ||
1671 | 2031 | ||
1672 | #region Sanity Checking | 2032 | #region Sanity Checking |
1673 | 2033 | ||
@@ -1699,27 +2059,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1699 | 2059 | ||
1700 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | 2060 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; |
1701 | 2061 | ||
1702 | // Camera location in world. We'll need to raytrace | ||
1703 | // from this location from time to time. | ||
1704 | CameraPosition = agentData.CameraCenter; | ||
1705 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
1706 | { | ||
1707 | ReprioritizeUpdates(); | ||
1708 | m_lastCameraPosition = CameraPosition; | ||
1709 | } | ||
1710 | |||
1711 | // Use these three vectors to figure out what the agent is looking at | ||
1712 | // Convert it to a Matrix and/or Quaternion | ||
1713 | CameraAtAxis = agentData.CameraAtAxis; | ||
1714 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
1715 | CameraUpAxis = agentData.CameraUpAxis; | ||
1716 | |||
1717 | // The Agent's Draw distance setting | 2062 | // The Agent's Draw distance setting |
1718 | // When we get to the point of re-computing neighbors everytime this | 2063 | // When we get to the point of re-computing neighbors everytime this |
1719 | // changes, then start using the agent's drawdistance rather than the | 2064 | // changes, then start using the agent's drawdistance rather than the |
1720 | // region's draw distance. | 2065 | // region's draw distance. |
1721 | // DrawDistance = agentData.Far; | 2066 | |
1722 | DrawDistance = Scene.DefaultDrawDistance; | 2067 | DrawDistance = Util.Clamp(agentData.Far, 32, m_scene.MaxDrawDistance); |
2068 | |||
2069 | // DrawDistance = Scene.DefaultDrawDistance; | ||
1723 | 2070 | ||
1724 | m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; | 2071 | m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; |
1725 | m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; | 2072 | m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; |
@@ -1735,6 +2082,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1735 | // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | 2082 | // (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) |
1736 | // m_updateCount = UPDATE_COUNT; | 2083 | // m_updateCount = UPDATE_COUNT; |
1737 | 2084 | ||
2085 | |||
1738 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) | 2086 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) |
1739 | { | 2087 | { |
1740 | StandUp(); | 2088 | StandUp(); |
@@ -1785,9 +2133,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1785 | // Here's where you get them. | 2133 | // Here's where you get them. |
1786 | m_AgentControlFlags = flags; | 2134 | m_AgentControlFlags = flags; |
1787 | m_headrotation = agentData.HeadRotation; | 2135 | m_headrotation = agentData.HeadRotation; |
2136 | byte oldState = State; | ||
1788 | State = agentData.State; | 2137 | State = agentData.State; |
1789 | 2138 | ||
2139 | // We need to send this back to the client in order to stop the edit beams | ||
2140 | if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) | ||
2141 | SendAgentTerseUpdate(this); | ||
2142 | |||
1790 | PhysicsActor actor = PhysicsActor; | 2143 | PhysicsActor actor = PhysicsActor; |
2144 | |||
2145 | // This will be the case if the agent is sitting on the groudn or on an object. | ||
1791 | if (actor == null) | 2146 | if (actor == null) |
1792 | { | 2147 | { |
1793 | SendControlsToScripts(flagsForScripts); | 2148 | SendControlsToScripts(flagsForScripts); |
@@ -1796,12 +2151,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1796 | 2151 | ||
1797 | if (AllowMovement && !SitGround) | 2152 | if (AllowMovement && !SitGround) |
1798 | { | 2153 | { |
1799 | Quaternion bodyRotation = agentData.BodyRotation; | 2154 | // m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); |
1800 | bool update_rotation = false; | 2155 | bool update_rotation = false; |
1801 | 2156 | if (agentData.BodyRotation != Rotation) | |
1802 | if (bodyRotation != Rotation) | ||
1803 | { | 2157 | { |
1804 | Rotation = bodyRotation; | 2158 | Rotation = agentData.BodyRotation; |
1805 | update_rotation = true; | 2159 | update_rotation = true; |
1806 | } | 2160 | } |
1807 | 2161 | ||
@@ -1817,7 +2171,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1817 | bool DCFlagKeyPressed = false; | 2171 | bool DCFlagKeyPressed = false; |
1818 | Vector3 agent_control_v3 = Vector3.Zero; | 2172 | Vector3 agent_control_v3 = Vector3.Zero; |
1819 | 2173 | ||
1820 | bool newFlying = actor.Flying; | 2174 | bool newFlying = false; |
1821 | 2175 | ||
1822 | if (ForceFly) | 2176 | if (ForceFly) |
1823 | newFlying = true; | 2177 | newFlying = true; |
@@ -1842,15 +2196,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1842 | 2196 | ||
1843 | // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying | 2197 | // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying |
1844 | // this prevents 'jumping' in inappropriate situations. | 2198 | // this prevents 'jumping' in inappropriate situations. |
1845 | if (!Flying && (m_mouseLook || m_leftButtonDown)) | 2199 | // if (!Flying && (m_mouseLook || m_leftButtonDown)) |
1846 | dirVectors = GetWalkDirectionVectors(); | 2200 | // dirVectors = GetWalkDirectionVectors(); |
1847 | else | 2201 | // else |
1848 | dirVectors = Dir_Vectors; | 2202 | dirVectors = Dir_Vectors; |
1849 | 2203 | ||
1850 | // The fact that MovementFlag is a byte needs to be fixed | 2204 | |
1851 | // it really should be a uint | ||
1852 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. | 2205 | // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. |
1853 | uint nudgehack = 250; | ||
1854 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) | 2206 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) |
1855 | { | 2207 | { |
1856 | if (((uint)flags & (uint)DCF) != 0) | 2208 | if (((uint)flags & (uint)DCF) != 0) |
@@ -1867,29 +2219,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1867 | // Why did I get this? | 2219 | // Why did I get this? |
1868 | } | 2220 | } |
1869 | 2221 | ||
1870 | if ((MovementFlag & (byte)(uint)DCF) == 0) | 2222 | if (((MovementFlag & (uint)DCF) == 0)) |
1871 | { | 2223 | { |
1872 | if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || | ||
1873 | DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) | ||
1874 | { | ||
1875 | MovementFlag |= (byte)nudgehack; | ||
1876 | } | ||
1877 | |||
1878 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); | 2224 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); |
1879 | MovementFlag += (byte)(uint)DCF; | 2225 | MovementFlag |= (uint)DCF; |
1880 | update_movementflag = true; | 2226 | update_movementflag = true; |
1881 | } | 2227 | } |
1882 | } | 2228 | } |
1883 | else | 2229 | else |
1884 | { | 2230 | { |
1885 | if ((MovementFlag & (byte)(uint)DCF) != 0 || | 2231 | if ((MovementFlag & (uint)DCF) != 0) |
1886 | ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE || | ||
1887 | DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE) | ||
1888 | && ((MovementFlag & (byte)nudgehack) == nudgehack)) | ||
1889 | ) // This or is for Nudge forward | ||
1890 | { | 2232 | { |
1891 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); | 2233 | //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); |
1892 | MovementFlag -= ((byte)(uint)DCF); | 2234 | MovementFlag &= (uint)~DCF; |
1893 | update_movementflag = true; | 2235 | update_movementflag = true; |
1894 | 2236 | ||
1895 | /* | 2237 | /* |
@@ -1909,6 +2251,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1909 | i++; | 2251 | i++; |
1910 | } | 2252 | } |
1911 | 2253 | ||
2254 | // Detect AGENT_CONTROL_STOP state changes | ||
2255 | if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0)) | ||
2256 | { | ||
2257 | AgentControlStopActive = !AgentControlStopActive; | ||
2258 | update_movementflag = true; | ||
2259 | } | ||
2260 | |||
1912 | if (MovingToTarget) | 2261 | if (MovingToTarget) |
1913 | { | 2262 | { |
1914 | // If the user has pressed a key then we want to cancel any move to target. | 2263 | // If the user has pressed a key then we want to cancel any move to target. |
@@ -1934,74 +2283,167 @@ namespace OpenSim.Region.Framework.Scenes | |||
1934 | // Only do this if we're flying | 2283 | // Only do this if we're flying |
1935 | if (Flying && !ForceFly) | 2284 | if (Flying && !ForceFly) |
1936 | { | 2285 | { |
1937 | // Landing detection code | 2286 | // Need to stop in mid air if user holds down AGENT_CONTROL_STOP |
1938 | 2287 | // if (AgentControlStopActive) | |
1939 | // Are the landing controls requirements filled? | 2288 | // { |
1940 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | 2289 | // agent_control_v3 = Vector3.Zero; |
1941 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | 2290 | // } |
1942 | 2291 | // else | |
1943 | //m_log.Debug("[CONTROL]: " +flags); | ||
1944 | // Applies a satisfying roll effect to the avatar when flying. | ||
1945 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||
1946 | { | ||
1947 | ApplyFlyingRoll( | ||
1948 | FLY_ROLL_RADIANS_PER_UPDATE, | ||
1949 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
1950 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1951 | } | ||
1952 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||
1953 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||
1954 | { | ||
1955 | ApplyFlyingRoll( | ||
1956 | -FLY_ROLL_RADIANS_PER_UPDATE, | ||
1957 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
1958 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1959 | } | ||
1960 | else | ||
1961 | { | 2292 | { |
1962 | if (m_AngularVelocity.Z != 0) | 2293 | // Landing detection code |
1963 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||
1964 | } | ||
1965 | 2294 | ||
1966 | if (Flying && IsColliding && controlland) | 2295 | // Are the landing controls requirements filled? |
1967 | { | 2296 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || |
1968 | // nesting this check because LengthSquared() is expensive and we don't | 2297 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); |
1969 | // want to do it every step when flying. | 2298 | |
1970 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | 2299 | //m_log.Debug("[CONTROL]: " +flags); |
1971 | StopFlying(); | 2300 | // Applies a satisfying roll effect to the avatar when flying. |
2301 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||
2302 | { | ||
2303 | ApplyFlyingRoll( | ||
2304 | FLY_ROLL_RADIANS_PER_UPDATE, | ||
2305 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
2306 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
2307 | } | ||
2308 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||
2309 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||
2310 | { | ||
2311 | ApplyFlyingRoll( | ||
2312 | -FLY_ROLL_RADIANS_PER_UPDATE, | ||
2313 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | ||
2314 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
2315 | } | ||
2316 | else | ||
2317 | { | ||
2318 | if (m_AngularVelocity.Z != 0) | ||
2319 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||
2320 | } | ||
2321 | |||
2322 | /* | ||
2323 | if (Flying && IsColliding && controlland) | ||
2324 | { | ||
2325 | // nesting this check because LengthSquared() is expensive and we don't | ||
2326 | // want to do it every step when flying. | ||
2327 | if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) | ||
2328 | StopFlying(); | ||
2329 | } | ||
2330 | */ | ||
1972 | } | 2331 | } |
1973 | } | 2332 | } |
2333 | else if (IsColliding && agent_control_v3.Z < 0f) | ||
2334 | agent_control_v3.Z = 0; | ||
2335 | // else if(AgentControlStopActive %% Velocity.Z <0.01f) | ||
2336 | |||
2337 | |||
2338 | // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); | ||
1974 | 2339 | ||
1975 | // If the agent update does move the avatar, then calculate the force ready for the velocity update, | 2340 | // If the agent update does move the avatar, then calculate the force ready for the velocity update, |
1976 | // which occurs later in the main scene loop | 2341 | // which occurs later in the main scene loop |
1977 | if (update_movementflag || (update_rotation && DCFlagKeyPressed)) | 2342 | // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they |
2343 | // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update | ||
2344 | // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the | ||
2345 | // avatar location in place). | ||
2346 | if (update_movementflag | ||
2347 | || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) | ||
1978 | { | 2348 | { |
1979 | // m_log.DebugFormat( | ||
1980 | // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", | ||
1981 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); | ||
1982 | 2349 | ||
1983 | AddNewMovement(agent_control_v3); | 2350 | if (AgentControlStopActive) |
2351 | { | ||
2352 | // if (MovementFlag == 0 && Animator.Falling) | ||
2353 | if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling) | ||
2354 | { | ||
2355 | AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true); | ||
2356 | } | ||
2357 | else | ||
2358 | AddNewMovement(agent_control_v3, AgentControlStopSlowVel); | ||
2359 | } | ||
2360 | else | ||
2361 | { | ||
2362 | AddNewMovement(agent_control_v3); | ||
2363 | } | ||
2364 | |||
1984 | } | 2365 | } |
1985 | // else | ||
1986 | // { | ||
1987 | // if (!update_movementflag) | ||
1988 | // { | ||
1989 | // m_log.DebugFormat( | ||
1990 | // "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false", | ||
1991 | // m_scene.RegionInfo.RegionName, agent_control_v3, Name); | ||
1992 | // } | ||
1993 | // } | ||
1994 | 2366 | ||
1995 | if (update_movementflag && ParentID == 0) | 2367 | if (update_movementflag && ParentID == 0) |
2368 | { | ||
2369 | // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); | ||
1996 | Animator.UpdateMovementAnimations(); | 2370 | Animator.UpdateMovementAnimations(); |
2371 | } | ||
1997 | 2372 | ||
1998 | SendControlsToScripts(flagsForScripts); | 2373 | SendControlsToScripts(flagsForScripts); |
1999 | } | 2374 | } |
2000 | 2375 | ||
2376 | // We need to send this back to the client in order to see the edit beams | ||
2377 | if ((State & (uint)AgentState.Editing) != 0) | ||
2378 | SendAgentTerseUpdate(this); | ||
2379 | |||
2001 | m_scene.EventManager.TriggerOnClientMovement(this); | 2380 | m_scene.EventManager.TriggerOnClientMovement(this); |
2002 | TriggerScenePresenceUpdated(); | ||
2003 | } | 2381 | } |
2004 | 2382 | ||
2383 | |||
2384 | /// <summary> | ||
2385 | /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. | ||
2386 | /// </summary> | ||
2387 | private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||
2388 | { | ||
2389 | //m_log.DebugFormat( | ||
2390 | // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}", | ||
2391 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | ||
2392 | |||
2393 | if (IsChildAgent) | ||
2394 | { | ||
2395 | // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); | ||
2396 | return; | ||
2397 | } | ||
2398 | |||
2399 | ++m_movementUpdateCount; | ||
2400 | if (m_movementUpdateCount < 1) | ||
2401 | m_movementUpdateCount = 1; | ||
2402 | |||
2403 | // AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | ||
2404 | |||
2405 | // Camera location in world. We'll need to raytrace | ||
2406 | // from this location from time to time. | ||
2407 | CameraPosition = agentData.CameraCenter; | ||
2408 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
2409 | { | ||
2410 | ReprioritizeUpdates(); | ||
2411 | m_lastCameraPosition = CameraPosition; | ||
2412 | } | ||
2413 | |||
2414 | // Use these three vectors to figure out what the agent is looking at | ||
2415 | // Convert it to a Matrix and/or Quaternion | ||
2416 | CameraAtAxis = agentData.CameraAtAxis; | ||
2417 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
2418 | CameraUpAxis = agentData.CameraUpAxis; | ||
2419 | |||
2420 | // The Agent's Draw distance setting | ||
2421 | // When we get to the point of re-computing neighbors everytime this | ||
2422 | // changes, then start using the agent's drawdistance rather than the | ||
2423 | // region's draw distance. | ||
2424 | DrawDistance = Util.Clamp(agentData.Far, 32, m_scene.MaxDrawDistance); | ||
2425 | |||
2426 | // Check if Client has camera in 'follow cam' or 'build' mode. | ||
2427 | Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); | ||
2428 | |||
2429 | m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) | ||
2430 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; | ||
2431 | |||
2432 | |||
2433 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); | ||
2434 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | ||
2435 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) | ||
2436 | { | ||
2437 | if (m_followCamAuto) | ||
2438 | { | ||
2439 | Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; | ||
2440 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); | ||
2441 | } | ||
2442 | } | ||
2443 | |||
2444 | TriggerScenePresenceUpdated(); | ||
2445 | } | ||
2446 | |||
2005 | /// <summary> | 2447 | /// <summary> |
2006 | /// Calculate an update to move the presence to the set target. | 2448 | /// Calculate an update to move the presence to the set target. |
2007 | /// </summary> | 2449 | /// </summary> |
@@ -2016,11 +2458,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2016 | 2458 | ||
2017 | bool updated = false; | 2459 | bool updated = false; |
2018 | 2460 | ||
2461 | Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition; | ||
2462 | |||
2019 | // m_log.DebugFormat( | 2463 | // m_log.DebugFormat( |
2020 | // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", | 2464 | // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", |
2021 | // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); | 2465 | // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); |
2022 | 2466 | ||
2023 | double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); | 2467 | double distanceToTarget = LocalVectorToTarget3D.Length(); |
2024 | 2468 | ||
2025 | // m_log.DebugFormat( | 2469 | // m_log.DebugFormat( |
2026 | // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", | 2470 | // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", |
@@ -2043,11 +2487,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2043 | // Theoretically we might need a more complex PID approach here if other | 2487 | // Theoretically we might need a more complex PID approach here if other |
2044 | // unknown forces are acting on the avatar and we need to adaptively respond | 2488 | // unknown forces are acting on the avatar and we need to adaptively respond |
2045 | // to such forces, but the following simple approach seems to works fine. | 2489 | // to such forces, but the following simple approach seems to works fine. |
2046 | Vector3 LocalVectorToTarget3D = | 2490 | |
2047 | (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords | 2491 | LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords |
2048 | * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords | ||
2049 | // Ignore z component of vector | 2492 | // Ignore z component of vector |
2050 | // Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); | 2493 | // Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); |
2494 | |||
2051 | LocalVectorToTarget3D.Normalize(); | 2495 | LocalVectorToTarget3D.Normalize(); |
2052 | 2496 | ||
2053 | // update avatar movement flags. the avatar coordinate system is as follows: | 2497 | // update avatar movement flags. the avatar coordinate system is as follows: |
@@ -2071,28 +2515,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
2071 | 2515 | ||
2072 | // based on the above avatar coordinate system, classify the movement into | 2516 | // based on the above avatar coordinate system, classify the movement into |
2073 | // one of left/right/back/forward. | 2517 | // one of left/right/back/forward. |
2518 | |||
2519 | const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK | | ||
2520 | Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT | | ||
2521 | Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP | | ||
2522 | Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)); | ||
2523 | |||
2524 | MovementFlag &= noMovFlagsMask; | ||
2525 | AgentControlFlags &= noMovFlagsMask; | ||
2526 | |||
2074 | if (LocalVectorToTarget3D.X < 0) //MoveBack | 2527 | if (LocalVectorToTarget3D.X < 0) //MoveBack |
2075 | { | 2528 | { |
2076 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; | 2529 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; |
2077 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; | 2530 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; |
2078 | updated = true; | 2531 | updated = true; |
2079 | } | 2532 | } |
2080 | else if (LocalVectorToTarget3D.X > 0) //Move Forward | 2533 | else if (LocalVectorToTarget3D.X > 0) //Move Forward |
2081 | { | 2534 | { |
2082 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; | 2535 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; |
2083 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; | 2536 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; |
2084 | updated = true; | 2537 | updated = true; |
2085 | } | 2538 | } |
2086 | 2539 | ||
2087 | if (LocalVectorToTarget3D.Y > 0) //MoveLeft | 2540 | if (LocalVectorToTarget3D.Y > 0) //MoveLeft |
2088 | { | 2541 | { |
2089 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; | 2542 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; |
2090 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; | 2543 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; |
2091 | updated = true; | 2544 | updated = true; |
2092 | } | 2545 | } |
2093 | else if (LocalVectorToTarget3D.Y < 0) //MoveRight | 2546 | else if (LocalVectorToTarget3D.Y < 0) //MoveRight |
2094 | { | 2547 | { |
2095 | MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; | 2548 | MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; |
2096 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; | 2549 | AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; |
2097 | updated = true; | 2550 | updated = true; |
2098 | } | 2551 | } |
@@ -2187,6 +2640,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2187 | targetScene = m_scene; | 2640 | targetScene = m_scene; |
2188 | 2641 | ||
2189 | float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; | 2642 | float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; |
2643 | // dont try to land underground | ||
2644 | terrainHeight += Appearance.AvatarHeight / 2; | ||
2190 | pos.Z = Math.Max(terrainHeight, pos.Z); | 2645 | pos.Z = Math.Max(terrainHeight, pos.Z); |
2191 | 2646 | ||
2192 | // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is | 2647 | // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is |
@@ -2198,10 +2653,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2198 | // m_log.DebugFormat( | 2653 | // m_log.DebugFormat( |
2199 | // "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", | 2654 | // "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", |
2200 | // Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); | 2655 | // Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); |
2656 | |||
2201 | 2657 | ||
2202 | if (noFly) | 2658 | if (noFly) |
2203 | Flying = false; | 2659 | Flying = false; |
2204 | else if (pos.Z > terrainHeight) | 2660 | else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying) |
2205 | Flying = true; | 2661 | Flying = true; |
2206 | 2662 | ||
2207 | LandAtTarget = landAtTarget; | 2663 | LandAtTarget = landAtTarget; |
@@ -2254,17 +2710,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2254 | { | 2710 | { |
2255 | // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); | 2711 | // m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); |
2256 | 2712 | ||
2713 | bool satOnObject = IsSatOnObject; | ||
2714 | SceneObjectPart part = ParentPart; | ||
2257 | SitGround = false; | 2715 | SitGround = false; |
2258 | 2716 | ||
2259 | /* move this down so avatar gets physical in the new position and not where it is siting | 2717 | if (satOnObject) |
2260 | if (PhysicsActor == null) | ||
2261 | AddToPhysicalScene(false); | ||
2262 | */ | ||
2263 | |||
2264 | if (ParentID != 0) | ||
2265 | { | 2718 | { |
2266 | PrevSitOffset = m_pos; // Save sit offset | 2719 | PrevSitOffset = m_pos; // Save sit offset |
2267 | SceneObjectPart part = ParentPart; | ||
2268 | UnRegisterSeatControls(part.ParentGroup.UUID); | 2720 | UnRegisterSeatControls(part.ParentGroup.UUID); |
2269 | 2721 | ||
2270 | TaskInventoryDictionary taskIDict = part.TaskInventory; | 2722 | TaskInventoryDictionary taskIDict = part.TaskInventory; |
@@ -2283,34 +2735,64 @@ namespace OpenSim.Region.Framework.Scenes | |||
2283 | } | 2735 | } |
2284 | 2736 | ||
2285 | part.ParentGroup.DeleteAvatar(UUID); | 2737 | part.ParentGroup.DeleteAvatar(UUID); |
2286 | // ParentPosition = part.GetWorldPosition(); | ||
2287 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); | ||
2288 | 2738 | ||
2289 | // m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | 2739 | Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset; |
2290 | // ParentPosition = Vector3.Zero; | 2740 | Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation; |
2291 | m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); | 2741 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); |
2292 | if (part.SitTargetAvatar == UUID) | ||
2293 | m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation; | ||
2294 | 2742 | ||
2295 | ParentID = 0; | 2743 | ParentID = 0; |
2296 | ParentPart = null; | 2744 | ParentPart = null; |
2297 | 2745 | ||
2298 | if (PhysicsActor == null) | 2746 | if (part.SitTargetAvatar == UUID) |
2299 | AddToPhysicalScene(false); | 2747 | standRotation = standRotation * part.SitTargetOrientation; |
2748 | else | ||
2749 | standRotation = standRotation * m_bodyRot; | ||
2300 | 2750 | ||
2301 | SendAvatarDataToAllAgents(); | 2751 | m_bodyRot = standRotation; |
2302 | m_requestedSitTargetID = 0; | ||
2303 | 2752 | ||
2304 | part.RemoveSittingAvatar(UUID); | 2753 | Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W); |
2305 | 2754 | ||
2306 | if (part != null) | 2755 | float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z; |
2307 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | 2756 | if (t > 0) |
2757 | { | ||
2758 | t = 1.0f / (float)Math.Sqrt(t); | ||
2759 | standRotationZ.W *= t; | ||
2760 | standRotationZ.Z *= t; | ||
2761 | } | ||
2762 | else | ||
2763 | { | ||
2764 | standRotationZ.W = 1.0f; | ||
2765 | standRotationZ.Z = 0f; | ||
2766 | } | ||
2767 | |||
2768 | Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ; | ||
2769 | |||
2770 | Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose; | ||
2771 | |||
2772 | m_pos = standPos; | ||
2308 | } | 2773 | } |
2309 | 2774 | ||
2310 | else if (PhysicsActor == null) | 2775 | // We need to wait until we have calculated proper stand positions before sitting up the physical |
2776 | // avatar to avoid race conditions. | ||
2777 | if (PhysicsActor == null) | ||
2311 | AddToPhysicalScene(false); | 2778 | AddToPhysicalScene(false); |
2312 | 2779 | ||
2313 | Animator.TrySetMovementAnimation("STAND"); | 2780 | if (satOnObject) |
2781 | { | ||
2782 | m_requestedSitTargetID = 0; | ||
2783 | part.RemoveSittingAvatar(UUID); | ||
2784 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | ||
2785 | |||
2786 | SendAvatarDataToAllAgents(); | ||
2787 | } | ||
2788 | |||
2789 | // reset to default sitAnimation | ||
2790 | sitAnimation = "SIT"; | ||
2791 | |||
2792 | // Animator.TrySetMovementAnimation("STAND"); | ||
2793 | Animator.SetMovementAnimations("STAND"); | ||
2794 | |||
2795 | TriggerScenePresenceUpdated(); | ||
2314 | } | 2796 | } |
2315 | 2797 | ||
2316 | private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) | 2798 | private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) |
@@ -2357,20 +2839,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2357 | if (part == null) | 2839 | if (part == null) |
2358 | return; | 2840 | return; |
2359 | 2841 | ||
2842 | |||
2360 | if (PhysicsActor != null) | 2843 | if (PhysicsActor != null) |
2361 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; | 2844 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; |
2362 | 2845 | ||
2363 | bool canSit = false; | 2846 | bool canSit = false; |
2364 | Vector3 pos = part.AbsolutePosition + offset; | ||
2365 | 2847 | ||
2366 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) | 2848 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) |
2367 | { | 2849 | { |
2368 | // m_log.DebugFormat( | ||
2369 | // "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied", | ||
2370 | // Name, part.Name, part.LocalId); | ||
2371 | |||
2372 | offset = part.SitTargetPosition; | 2850 | offset = part.SitTargetPosition; |
2373 | sitOrientation = part.SitTargetOrientation; | 2851 | sitOrientation = part.SitTargetOrientation; |
2852 | |||
2374 | canSit = true; | 2853 | canSit = true; |
2375 | } | 2854 | } |
2376 | else | 2855 | else |
@@ -2378,9 +2857,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2378 | if (PhysicsSit(part,offset)) // physics engine | 2857 | if (PhysicsSit(part,offset)) // physics engine |
2379 | return; | 2858 | return; |
2380 | 2859 | ||
2860 | Vector3 pos = part.AbsolutePosition + offset; | ||
2861 | |||
2381 | if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) | 2862 | if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) |
2382 | { | 2863 | { |
2383 | |||
2384 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); | 2864 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); |
2385 | canSit = true; | 2865 | canSit = true; |
2386 | } | 2866 | } |
@@ -2406,10 +2886,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
2406 | cameraEyeOffset = part.GetCameraEyeOffset(); | 2886 | cameraEyeOffset = part.GetCameraEyeOffset(); |
2407 | forceMouselook = part.GetForceMouselook(); | 2887 | forceMouselook = part.GetForceMouselook(); |
2408 | 2888 | ||
2889 | if (!part.IsRoot) | ||
2890 | { | ||
2891 | sitOrientation = part.RotationOffset * sitOrientation; | ||
2892 | offset = offset * part.RotationOffset; | ||
2893 | offset += part.OffsetPosition; | ||
2894 | |||
2895 | if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero) | ||
2896 | { | ||
2897 | CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset(); | ||
2898 | cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset(); | ||
2899 | } | ||
2900 | else | ||
2901 | { | ||
2902 | cameraAtOffset = cameraAtOffset * part.RotationOffset; | ||
2903 | cameraAtOffset += part.OffsetPosition; | ||
2904 | cameraEyeOffset = cameraEyeOffset * part.RotationOffset; | ||
2905 | cameraEyeOffset += part.OffsetPosition; | ||
2906 | } | ||
2907 | } | ||
2908 | |||
2909 | |||
2409 | ControllingClient.SendSitResponse( | 2910 | ControllingClient.SendSitResponse( |
2410 | part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | 2911 | part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); |
2411 | 2912 | ||
2412 | m_requestedSitTargetUUID = targetID; | 2913 | m_requestedSitTargetUUID = part.UUID; |
2413 | 2914 | ||
2414 | HandleAgentSit(ControllingClient, UUID); | 2915 | HandleAgentSit(ControllingClient, UUID); |
2415 | 2916 | ||
@@ -2437,7 +2938,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2437 | if (part != null) | 2938 | if (part != null) |
2438 | { | 2939 | { |
2439 | m_requestedSitTargetID = part.LocalId; | 2940 | m_requestedSitTargetID = part.LocalId; |
2440 | m_requestedSitTargetUUID = targetID; | 2941 | m_requestedSitTargetUUID = part.UUID; |
2441 | 2942 | ||
2442 | } | 2943 | } |
2443 | else | 2944 | else |
@@ -2524,6 +3025,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2524 | ResetMoveToTarget(); | 3025 | ResetMoveToTarget(); |
2525 | 3026 | ||
2526 | Velocity = Vector3.Zero; | 3027 | Velocity = Vector3.Zero; |
3028 | m_AngularVelocity = Vector3.Zero; | ||
2527 | 3029 | ||
2528 | part.AddSittingAvatar(UUID); | 3030 | part.AddSittingAvatar(UUID); |
2529 | 3031 | ||
@@ -2531,24 +3033,55 @@ namespace OpenSim.Region.Framework.Scenes | |||
2531 | Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); | 3033 | Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); |
2532 | bool forceMouselook = part.GetForceMouselook(); | 3034 | bool forceMouselook = part.GetForceMouselook(); |
2533 | 3035 | ||
2534 | ControllingClient.SendSitResponse( | 3036 | m_bodyRot = Orientation; |
2535 | part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | ||
2536 | 3037 | ||
2537 | // not using autopilot | 3038 | if (!part.IsRoot) |
3039 | { | ||
3040 | Orientation = part.RotationOffset * Orientation; | ||
3041 | offset = offset * part.RotationOffset; | ||
3042 | offset += part.OffsetPosition; | ||
3043 | |||
3044 | if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero) | ||
3045 | { | ||
3046 | CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset(); | ||
3047 | cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset(); | ||
3048 | } | ||
3049 | else | ||
3050 | { | ||
3051 | cameraAtOffset = cameraAtOffset * part.RotationOffset; | ||
3052 | cameraAtOffset += part.OffsetPosition; | ||
3053 | cameraEyeOffset = cameraEyeOffset * part.RotationOffset; | ||
3054 | cameraEyeOffset += part.OffsetPosition; | ||
3055 | } | ||
3056 | |||
3057 | } | ||
2538 | 3058 | ||
2539 | Rotation = Orientation; | ||
2540 | m_pos = offset; | 3059 | m_pos = offset; |
2541 | 3060 | ||
3061 | ControllingClient.SendSitResponse( | ||
3062 | part.ParentGroup.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); | ||
3063 | |||
3064 | |||
2542 | m_requestedSitTargetID = 0; | 3065 | m_requestedSitTargetID = 0; |
2543 | part.ParentGroup.AddAvatar(UUID); | 3066 | part.ParentGroup.AddAvatar(UUID); |
2544 | 3067 | ||
2545 | ParentPart = part; | 3068 | ParentPart = part; |
2546 | ParentID = part.LocalId; | 3069 | ParentID = part.LocalId; |
3070 | |||
3071 | SendAvatarDataToAllAgents(); | ||
3072 | |||
3073 | /* | ||
2547 | if(status == 3) | 3074 | if(status == 3) |
2548 | Animator.TrySetMovementAnimation("SIT_GROUND"); | 3075 | Animator.TrySetMovementAnimation("SIT_GROUND"); |
2549 | else | 3076 | else |
2550 | Animator.TrySetMovementAnimation("SIT"); | 3077 | Animator.TrySetMovementAnimation("SIT"); |
2551 | SendAvatarDataToAllAgents(); | 3078 | */ |
3079 | if (status == 3) | ||
3080 | sitAnimation = "SIT_GROUND"; | ||
3081 | else | ||
3082 | sitAnimation = "SIT"; | ||
3083 | |||
3084 | Animator.SetMovementAnimations("SIT"); | ||
2552 | 3085 | ||
2553 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | 3086 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
2554 | } | 3087 | } |
@@ -2556,6 +3089,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2556 | 3089 | ||
2557 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) | 3090 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) |
2558 | { | 3091 | { |
3092 | if (IsChildAgent) | ||
3093 | return; | ||
3094 | |||
2559 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 3095 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2560 | 3096 | ||
2561 | if (part != null) | 3097 | if (part != null) |
@@ -2605,47 +3141,74 @@ namespace OpenSim.Region.Framework.Scenes | |||
2605 | Vector3 up = new Vector3((float)x, (float)y, (float)z); | 3141 | Vector3 up = new Vector3((float)x, (float)y, (float)z); |
2606 | Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; | 3142 | Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; |
2607 | 3143 | ||
2608 | m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; | 3144 | Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; |
3145 | Quaternion newRot; | ||
3146 | |||
3147 | if (part.IsRoot) | ||
3148 | { | ||
3149 | newRot = sitTargetOrient; | ||
3150 | } | ||
3151 | else | ||
3152 | { | ||
3153 | newPos = newPos * part.RotationOffset; | ||
3154 | newRot = part.RotationOffset * sitTargetOrient; | ||
3155 | } | ||
3156 | |||
3157 | newPos += part.OffsetPosition; | ||
3158 | |||
3159 | m_pos = newPos; | ||
3160 | Rotation = newRot; | ||
2609 | 3161 | ||
2610 | // m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset; | ||
2611 | Rotation = sitTargetOrient; | ||
2612 | // ParentPosition = part.AbsolutePosition; | 3162 | // ParentPosition = part.AbsolutePosition; |
2613 | part.ParentGroup.AddAvatar(UUID); | ||
2614 | } | 3163 | } |
2615 | else | 3164 | else |
2616 | { | 3165 | { |
2617 | m_pos -= part.AbsolutePosition; | 3166 | // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is |
3167 | // being sat upon. | ||
3168 | m_pos -= part.GroupPosition; | ||
3169 | |||
2618 | // ParentPosition = part.AbsolutePosition; | 3170 | // ParentPosition = part.AbsolutePosition; |
2619 | part.ParentGroup.AddAvatar(UUID); | ||
2620 | 3171 | ||
2621 | // m_log.DebugFormat( | 3172 | // m_log.DebugFormat( |
2622 | // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", | 3173 | // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", |
2623 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); | 3174 | // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); |
2624 | } | 3175 | } |
2625 | 3176 | ||
3177 | part.ParentGroup.AddAvatar(UUID); | ||
2626 | ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 3178 | ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2627 | ParentID = m_requestedSitTargetID; | 3179 | ParentID = m_requestedSitTargetID; |
2628 | m_AngularVelocity = Vector3.Zero; | 3180 | m_AngularVelocity = Vector3.Zero; |
2629 | Velocity = Vector3.Zero; | 3181 | Velocity = Vector3.Zero; |
2630 | RemoveFromPhysicalScene(); | 3182 | RemoveFromPhysicalScene(); |
2631 | 3183 | ||
2632 | String sitAnimation = "SIT"; | 3184 | SendAvatarDataToAllAgents(); |
3185 | |||
3186 | sitAnimation = "SIT"; | ||
2633 | if (!String.IsNullOrEmpty(part.SitAnimation)) | 3187 | if (!String.IsNullOrEmpty(part.SitAnimation)) |
2634 | { | 3188 | { |
2635 | sitAnimation = part.SitAnimation; | 3189 | sitAnimation = part.SitAnimation; |
2636 | } | 3190 | } |
2637 | Animator.TrySetMovementAnimation(sitAnimation); | 3191 | // Animator.TrySetMovementAnimation(sitAnimation); |
2638 | SendAvatarDataToAllAgents(); | 3192 | Animator.SetMovementAnimations("SIT"); |
3193 | TriggerScenePresenceUpdated(); | ||
2639 | } | 3194 | } |
2640 | } | 3195 | } |
2641 | 3196 | ||
2642 | public void HandleAgentSitOnGround() | 3197 | public void HandleAgentSitOnGround() |
2643 | { | 3198 | { |
3199 | if (IsChildAgent) | ||
3200 | return; | ||
3201 | |||
2644 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. | 3202 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. |
2645 | m_AngularVelocity = Vector3.Zero; | 3203 | m_AngularVelocity = Vector3.Zero; |
2646 | Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | 3204 | sitAnimation = "SIT_GROUND_CONSTRAINED"; |
3205 | // Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | ||
3206 | // TriggerScenePresenceUpdated(); | ||
2647 | SitGround = true; | 3207 | SitGround = true; |
2648 | RemoveFromPhysicalScene(); | 3208 | RemoveFromPhysicalScene(); |
3209 | |||
3210 | Animator.SetMovementAnimations("SITGROUND"); | ||
3211 | TriggerScenePresenceUpdated(); | ||
2649 | } | 3212 | } |
2650 | 3213 | ||
2651 | /// <summary> | 3214 | /// <summary> |
@@ -2660,11 +3223,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2660 | public void HandleStartAnim(IClientAPI remoteClient, UUID animID) | 3223 | public void HandleStartAnim(IClientAPI remoteClient, UUID animID) |
2661 | { | 3224 | { |
2662 | Animator.AddAnimation(animID, UUID.Zero); | 3225 | Animator.AddAnimation(animID, UUID.Zero); |
3226 | TriggerScenePresenceUpdated(); | ||
2663 | } | 3227 | } |
2664 | 3228 | ||
2665 | public void HandleStopAnim(IClientAPI remoteClient, UUID animID) | 3229 | public void HandleStopAnim(IClientAPI remoteClient, UUID animID) |
2666 | { | 3230 | { |
2667 | Animator.RemoveAnimation(animID, false); | 3231 | Animator.RemoveAnimation(animID, false); |
3232 | TriggerScenePresenceUpdated(); | ||
2668 | } | 3233 | } |
2669 | 3234 | ||
2670 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) | 3235 | public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) |
@@ -2678,67 +3243,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
2678 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector | 3243 | /// Rotate the avatar to the given rotation and apply a movement in the given relative vector |
2679 | /// </summary> | 3244 | /// </summary> |
2680 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> | 3245 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> |
2681 | public void AddNewMovement(Vector3 vec) | 3246 | /// <param name="thisAddSpeedModifier"> |
3247 | /// Optional additional speed modifier for this particular add. Default is 1</param> | ||
3248 | public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false) | ||
2682 | { | 3249 | { |
2683 | // m_log.DebugFormat( | 3250 | // m_log.DebugFormat( |
2684 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); | 3251 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", |
3252 | // vec, Rotation, thisAddSpeedModifier, Name); | ||
2685 | 3253 | ||
3254 | // rotate from avatar coord space to world | ||
3255 | // for now all controls assume this is only a rotation around Z | ||
3256 | // if not all checks below need to be done before this rotation | ||
2686 | Vector3 direc = vec * Rotation; | 3257 | Vector3 direc = vec * Rotation; |
2687 | direc.Normalize(); | 3258 | direc.Normalize(); |
2688 | 3259 | ||
2689 | if (Flying != FlyingOld) // add for fly velocity control | 3260 | // mouse look situation ? |
2690 | { | ||
2691 | FlyingOld = Flying; // add for fly velocity control | ||
2692 | if (!Flying) | ||
2693 | WasFlying = true; // add for fly velocity control | ||
2694 | } | ||
2695 | |||
2696 | if (IsColliding) | ||
2697 | WasFlying = false; // add for fly velocity control | ||
2698 | |||
2699 | if ((vec.Z == 0f) && !Flying) | 3261 | if ((vec.Z == 0f) && !Flying) |
2700 | direc.Z = 0f; // Prevent camera WASD up. | 3262 | direc.Z = 0f; // Prevent camera WASD up. |
2701 | 3263 | ||
2702 | direc *= 0.03f * 128f * SpeedModifier; | 3264 | // odd rescalings |
3265 | direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; | ||
2703 | 3266 | ||
2704 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); | 3267 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); |
2705 | 3268 | ||
2706 | if (PhysicsActor != null) | 3269 | if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling) |
2707 | { | 3270 | { |
2708 | if (Flying) | 3271 | if (breaking) |
2709 | { | 3272 | direc.Z = -9999f; //hack to tell physics to stop on Z |
3273 | else | ||
3274 | direc = Vector3.Zero; | ||
3275 | } | ||
3276 | else if (Flying) | ||
3277 | { | ||
3278 | if (IsColliding && direc.Z < 0) | ||
3279 | // landing situation, prevent avatar moving or it may fail to land | ||
3280 | // animator will handle this condition and do the land | ||
3281 | direc = Vector3.Zero; | ||
3282 | else | ||
2710 | direc *= 4.0f; | 3283 | direc *= 4.0f; |
2711 | //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | 3284 | } |
2712 | //if (controlland) | 3285 | else if (IsColliding) |
2713 | // m_log.Info("[AGENT]: landCommand"); | 3286 | { |
2714 | //if (IsColliding) | 3287 | if (direc.Z > 2.0f) // reinforce jumps |
2715 | // m_log.Info("[AGENT]: colliding"); | ||
2716 | //if (Flying && IsColliding && controlland) | ||
2717 | //{ | ||
2718 | // StopFlying(); | ||
2719 | // m_log.Info("[AGENT]: Stop Flying"); | ||
2720 | //} | ||
2721 | } | ||
2722 | if (Animator.Falling && WasFlying) // if falling from flying, disable motion add | ||
2723 | { | ||
2724 | direc *= 0.0f; | ||
2725 | } | ||
2726 | else if (!Flying && IsColliding) | ||
2727 | { | 3288 | { |
2728 | if (direc.Z > 2.0f) | 3289 | direc.Z *= 2.6f; |
2729 | { | ||
2730 | direc.Z *= 2.6f; | ||
2731 | |||
2732 | // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. | ||
2733 | // Animator.TrySetMovementAnimation("PREJUMP"); | ||
2734 | // Animator.TrySetMovementAnimation("JUMP"); | ||
2735 | } | ||
2736 | } | 3290 | } |
3291 | else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation | ||
3292 | direc.Z = 0; | ||
2737 | } | 3293 | } |
2738 | 3294 | ||
2739 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); | 3295 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); |
2740 | 3296 | ||
2741 | // TODO: Add the force instead of only setting it to support multiple forces per frame? | ||
2742 | m_forceToApply = direc; | 3297 | m_forceToApply = direc; |
2743 | Animator.UpdateMovementAnimations(); | 3298 | Animator.UpdateMovementAnimations(); |
2744 | } | 3299 | } |
@@ -2755,6 +3310,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2755 | 3310 | ||
2756 | if (IsChildAgent == false) | 3311 | if (IsChildAgent == false) |
2757 | { | 3312 | { |
3313 | CheckForBorderCrossing(); | ||
3314 | |||
3315 | if (IsInTransit) | ||
3316 | return; | ||
3317 | |||
2758 | // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to | 3318 | // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to |
2759 | // grab the latest PhysicsActor velocity, whereas m_velocity is often | 3319 | // grab the latest PhysicsActor velocity, whereas m_velocity is often |
2760 | // storing a requested force instead of an actual traveling velocity | 3320 | // storing a requested force instead of an actual traveling velocity |
@@ -2773,8 +3333,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2773 | m_lastVelocity = Velocity; | 3333 | m_lastVelocity = Velocity; |
2774 | } | 3334 | } |
2775 | 3335 | ||
2776 | CheckForBorderCrossing(); | ||
2777 | |||
2778 | CheckForSignificantMovement(); // sends update to the modules. | 3336 | CheckForSignificantMovement(); // sends update to the modules. |
2779 | } | 3337 | } |
2780 | } | 3338 | } |
@@ -2783,9 +3341,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
2783 | 3341 | ||
2784 | #region Update Client(s) | 3342 | #region Update Client(s) |
2785 | 3343 | ||
3344 | public void SendUpdateToAgent(ScenePresence p) | ||
3345 | { | ||
3346 | IClientAPI remoteClient = p.ControllingClient; | ||
3347 | |||
3348 | if (remoteClient.IsActive) | ||
3349 | { | ||
3350 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | ||
3351 | remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate); | ||
3352 | m_scene.StatsReporter.AddAgentUpdates(1); | ||
3353 | } | ||
3354 | } | ||
3355 | |||
3356 | public void SendFullUpdateToClient(IClientAPI remoteClient) | ||
3357 | { | ||
3358 | if (remoteClient.IsActive) | ||
3359 | { | ||
3360 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | ||
3361 | remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate); | ||
3362 | m_scene.StatsReporter.AddAgentUpdates(1); | ||
3363 | } | ||
3364 | } | ||
3365 | |||
3366 | // this is diferente from SendTerseUpdateToClient | ||
3367 | // this sends bypassing entities updates | ||
3368 | public void SendAgentTerseUpdate(ISceneEntity p) | ||
3369 | { | ||
3370 | ControllingClient.SendAgentTerseUpdate(p); | ||
3371 | } | ||
2786 | 3372 | ||
2787 | /// <summary> | 3373 | /// <summary> |
2788 | /// Sends a location update to the client connected to this scenePresence | 3374 | /// Sends a location update to the client connected to this scenePresence |
3375 | /// via entity updates | ||
2789 | /// </summary> | 3376 | /// </summary> |
2790 | /// <param name="remoteClient"></param> | 3377 | /// <param name="remoteClient"></param> |
2791 | public void SendTerseUpdateToClient(IClientAPI remoteClient) | 3378 | public void SendTerseUpdateToClient(IClientAPI remoteClient) |
@@ -2795,7 +3382,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2795 | if (remoteClient.IsActive) | 3382 | if (remoteClient.IsActive) |
2796 | { | 3383 | { |
2797 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | 3384 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); |
2798 | |||
2799 | remoteClient.SendEntityUpdate( | 3385 | remoteClient.SendEntityUpdate( |
2800 | this, | 3386 | this, |
2801 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | 3387 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity |
@@ -2805,6 +3391,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
2805 | } | 3391 | } |
2806 | } | 3392 | } |
2807 | 3393 | ||
3394 | public void SendTerseUpdateToAgent(ScenePresence p) | ||
3395 | { | ||
3396 | IClientAPI remoteClient = p.ControllingClient; | ||
3397 | |||
3398 | if (!remoteClient.IsActive) | ||
3399 | return; | ||
3400 | |||
3401 | if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200) | ||
3402 | return; | ||
3403 | |||
3404 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | ||
3405 | remoteClient.SendEntityUpdate( | ||
3406 | this, | ||
3407 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
3408 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | ||
3409 | |||
3410 | m_scene.StatsReporter.AddAgentUpdates(1); | ||
3411 | } | ||
3412 | |||
3413 | public void SendTerseUpdateToAgentNF(ScenePresence p) | ||
3414 | { | ||
3415 | IClientAPI remoteClient = p.ControllingClient; | ||
3416 | if (remoteClient.IsActive) | ||
3417 | { | ||
3418 | //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); | ||
3419 | remoteClient.SendEntityUpdate(this, | ||
3420 | PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
3421 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); | ||
3422 | m_scene.StatsReporter.AddAgentUpdates(1); | ||
3423 | } | ||
3424 | } | ||
3425 | |||
2808 | 3426 | ||
2809 | // vars to support reduced update frequency when velocity is unchanged | 3427 | // vars to support reduced update frequency when velocity is unchanged |
2810 | private Vector3 lastVelocitySentToAllClients = Vector3.Zero; | 3428 | private Vector3 lastVelocitySentToAllClients = Vector3.Zero; |
@@ -2845,7 +3463,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2845 | lastTerseUpdateToAllClientsTick = currentTick; | 3463 | lastTerseUpdateToAllClientsTick = currentTick; |
2846 | lastPositionSentToAllClients = OffsetPosition; | 3464 | lastPositionSentToAllClients = OffsetPosition; |
2847 | 3465 | ||
2848 | m_scene.ForEachClient(SendTerseUpdateToClient); | 3466 | // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); |
3467 | // m_scene.ForEachClient(SendTerseUpdateToClient); | ||
3468 | m_scene.ForEachScenePresence(SendTerseUpdateToAgent); | ||
2849 | } | 3469 | } |
2850 | TriggerScenePresenceUpdated(); | 3470 | TriggerScenePresenceUpdated(); |
2851 | } | 3471 | } |
@@ -2878,13 +3498,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
2878 | // we created a new ScenePresence (a new child agent) in a fresh region. | 3498 | // we created a new ScenePresence (a new child agent) in a fresh region. |
2879 | // Request info about all the (root) agents in this region | 3499 | // Request info about all the (root) agents in this region |
2880 | // Note: This won't send data *to* other clients in that region (children don't send) | 3500 | // Note: This won't send data *to* other clients in that region (children don't send) |
2881 | SendOtherAgentsAvatarDataToMe(); | 3501 | if (m_teleportFlags <= 0) |
2882 | SendOtherAgentsAppearanceToMe(); | 3502 | { |
3503 | ILandChannel landch = m_scene.LandChannel; | ||
3504 | if (landch != null) | ||
3505 | { | ||
3506 | landch.sendClientInitialLandInfo(ControllingClient); | ||
3507 | } | ||
3508 | } | ||
2883 | 3509 | ||
3510 | SendOtherAgentsAvatarFullToMe(); | ||
2884 | EntityBase[] entities = Scene.Entities.GetEntities(); | 3511 | EntityBase[] entities = Scene.Entities.GetEntities(); |
2885 | foreach(EntityBase e in entities) | 3512 | foreach (EntityBase e in entities) |
2886 | { | 3513 | { |
2887 | if (e != null && e is SceneObjectGroup) | 3514 | if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) |
2888 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); | 3515 | ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); |
2889 | } | 3516 | } |
2890 | }); | 3517 | }); |
@@ -2894,6 +3521,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2894 | /// Do everything required once a client completes its movement into a region and becomes | 3521 | /// Do everything required once a client completes its movement into a region and becomes |
2895 | /// a root agent. | 3522 | /// a root agent. |
2896 | /// </summary> | 3523 | /// </summary> |
3524 | /// | ||
3525 | /* only called from on place, do done inline there | ||
2897 | private void ValidateAndSendAppearanceAndAgentData() | 3526 | private void ValidateAndSendAppearanceAndAgentData() |
2898 | { | 3527 | { |
2899 | //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); | 3528 | //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); |
@@ -2907,32 +3536,63 @@ namespace OpenSim.Region.Framework.Scenes | |||
2907 | // to see if all the baked textures are already here. | 3536 | // to see if all the baked textures are already here. |
2908 | if (m_scene.AvatarFactory != null) | 3537 | if (m_scene.AvatarFactory != null) |
2909 | cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); | 3538 | cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); |
2910 | 3539 | ||
2911 | // If we aren't using a cached appearance, then clear out the baked textures | 3540 | // If we aren't using a cached appearance, then clear out the baked textures |
2912 | if (!cachedappearance) | 3541 | if (!cachedappearance) |
2913 | { | 3542 | { |
2914 | Appearance.ResetAppearance(); | ||
2915 | if (m_scene.AvatarFactory != null) | 3543 | if (m_scene.AvatarFactory != null) |
2916 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); | 3544 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); |
2917 | } | 3545 | } |
2918 | 3546 | ||
2919 | // This agent just became root. We are going to tell everyone about it. The process of | 3547 | // send avatar object to all viewers so they cross it into region |
2920 | // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it | 3548 | bool newhide = m_currentParcelHide; |
2921 | // again here... this comes after the cached appearance check because the avatars | 3549 | m_currentParcelHide = false; |
2922 | // appearance goes into the avatar update packet | 3550 | |
2923 | SendAvatarDataToAllAgents(); | 3551 | SendAvatarDataToAllAgents(); |
3552 | |||
3553 | // now hide | ||
3554 | if (newhide) | ||
3555 | { | ||
3556 | ParcelLoginCheck(m_currentParcelUUID); | ||
3557 | m_currentParcelHide = true; | ||
3558 | } | ||
3559 | |||
2924 | SendAppearanceToAgent(this); | 3560 | SendAppearanceToAgent(this); |
2925 | 3561 | ||
2926 | // If we are using the the cached appearance then send it out to everyone | 3562 | m_inTransit = false; |
2927 | if (cachedappearance) | 3563 | |
3564 | SendAppearanceToAllOtherAgents(); | ||
3565 | |||
3566 | if(Animator!= null) | ||
3567 | Animator.SendAnimPack(); | ||
3568 | } | ||
3569 | */ | ||
3570 | /// <summary> | ||
3571 | /// Send avatar full data appearance and animations for all other root agents to this agent, this agent | ||
3572 | /// can be either a child or root | ||
3573 | /// </summary> | ||
3574 | public void SendOtherAgentsAvatarFullToMe() | ||
3575 | { | ||
3576 | int count = 0; | ||
3577 | m_scene.ForEachRootScenePresence(delegate(ScenePresence p) | ||
2928 | { | 3578 | { |
2929 | m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); | 3579 | // only send information about other root agents |
3580 | if (p.UUID == UUID) | ||
3581 | return; | ||
2930 | 3582 | ||
2931 | // If the avatars baked textures are all in the cache, then we have a | 3583 | // get the avatar, then a kill if can't see it |
2932 | // complete appearance... send it out, if not, then we'll send it when | 3584 | p.SendInitialAvatarDataToAgent(this); |
2933 | // the avatar finishes updating its appearance | 3585 | |
2934 | SendAppearanceToAllOtherAgents(); | 3586 | if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200) |
2935 | } | 3587 | return; |
3588 | |||
3589 | p.SendAppearanceToAgentNF(this); | ||
3590 | p.SendAnimPackToAgentNF(this); | ||
3591 | p.SendAttachmentsToAgentNF(this); | ||
3592 | count++; | ||
3593 | }); | ||
3594 | |||
3595 | m_scene.StatsReporter.AddAgentUpdates(count); | ||
2936 | } | 3596 | } |
2937 | 3597 | ||
2938 | /// <summary> | 3598 | /// <summary> |
@@ -2948,42 +3608,51 @@ namespace OpenSim.Region.Framework.Scenes | |||
2948 | m_log.WarnFormat( | 3608 | m_log.WarnFormat( |
2949 | "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", | 3609 | "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", |
2950 | Name, Scene.RegionInfo.RegionName); | 3610 | Name, Scene.RegionInfo.RegionName); |
2951 | |||
2952 | return; | 3611 | return; |
2953 | } | 3612 | } |
2954 | 3613 | ||
2955 | m_lastSize = Appearance.AvatarSize; | 3614 | m_lastSize = Appearance.AvatarSize; |
2956 | |||
2957 | int count = 0; | 3615 | int count = 0; |
3616 | |||
2958 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) | 3617 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) |
2959 | { | 3618 | { |
2960 | SendAvatarDataToAgent(scenePresence); | 3619 | SendAvatarDataToAgent(scenePresence); |
2961 | count++; | 3620 | count++; |
2962 | }); | 3621 | }); |
2963 | 3622 | ||
2964 | m_scene.StatsReporter.AddAgentUpdates(count); | 3623 | m_scene.StatsReporter.AddAgentUpdates(count); |
2965 | } | 3624 | } |
2966 | 3625 | ||
2967 | /// <summary> | 3626 | // sends avatar object to all clients so they cross it into region |
2968 | /// Send avatar data for all other root agents to this agent, this agent | 3627 | // then sends kills to hide |
2969 | /// can be either a child or root | 3628 | public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences) |
2970 | /// </summary> | ||
2971 | public void SendOtherAgentsAvatarDataToMe() | ||
2972 | { | 3629 | { |
3630 | m_lastSize = Appearance.AvatarSize; | ||
2973 | int count = 0; | 3631 | int count = 0; |
2974 | m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) | ||
2975 | { | ||
2976 | // only send information about other root agents | ||
2977 | if (scenePresence.UUID == UUID) | ||
2978 | return; | ||
2979 | |||
2980 | scenePresence.SendAvatarDataToAgent(this); | ||
2981 | count++; | ||
2982 | }); | ||
2983 | 3632 | ||
3633 | foreach (ScenePresence p in presences) | ||
3634 | { | ||
3635 | p.ControllingClient.SendAvatarDataImmediate(this); | ||
3636 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
3637 | // either just kill the object | ||
3638 | // p.ControllingClient.SendKillObject(new List<uint> {LocalId}); | ||
3639 | // or also attachments viewer may still know about | ||
3640 | SendKillTo(p); | ||
3641 | count++; | ||
3642 | } | ||
2984 | m_scene.StatsReporter.AddAgentUpdates(count); | 3643 | m_scene.StatsReporter.AddAgentUpdates(count); |
2985 | } | 3644 | } |
2986 | 3645 | ||
3646 | public void SendInitialAvatarDataToAgent(ScenePresence p) | ||
3647 | { | ||
3648 | p.ControllingClient.SendAvatarDataImmediate(this); | ||
3649 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
3650 | // either just kill the object | ||
3651 | // p.ControllingClient.SendKillObject(new List<uint> {LocalId}); | ||
3652 | // or also attachments viewer may still know about | ||
3653 | SendKillTo(p); | ||
3654 | } | ||
3655 | |||
2987 | /// <summary> | 3656 | /// <summary> |
2988 | /// Send avatar data to an agent. | 3657 | /// Send avatar data to an agent. |
2989 | /// </summary> | 3658 | /// </summary> |
@@ -2991,18 +3660,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
2991 | public void SendAvatarDataToAgent(ScenePresence avatar) | 3660 | public void SendAvatarDataToAgent(ScenePresence avatar) |
2992 | { | 3661 | { |
2993 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); | 3662 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); |
2994 | 3663 | if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200) | |
3664 | return; | ||
2995 | avatar.ControllingClient.SendAvatarDataImmediate(this); | 3665 | avatar.ControllingClient.SendAvatarDataImmediate(this); |
2996 | Animator.SendAnimPackToClient(avatar.ControllingClient); | ||
2997 | } | 3666 | } |
2998 | 3667 | ||
3668 | public void SendAvatarDataToAgentNF(ScenePresence avatar) | ||
3669 | { | ||
3670 | avatar.ControllingClient.SendAvatarDataImmediate(this); | ||
3671 | } | ||
3672 | |||
2999 | /// <summary> | 3673 | /// <summary> |
3000 | /// Send this agent's appearance to all other root and child agents in the scene | 3674 | /// Send this agent's appearance to all other root and child agents in the scene |
3001 | /// This agent must be root. | 3675 | /// This agent must be root. |
3002 | /// </summary> | 3676 | /// </summary> |
3003 | public void SendAppearanceToAllOtherAgents() | 3677 | public void SendAppearanceToAllOtherAgents() |
3004 | { | 3678 | { |
3005 | // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); | 3679 | // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID); |
3006 | 3680 | ||
3007 | // only send update from root agents to other clients; children are only "listening posts" | 3681 | // only send update from root agents to other clients; children are only "listening posts" |
3008 | if (IsChildAgent) | 3682 | if (IsChildAgent) |
@@ -3013,7 +3687,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3013 | 3687 | ||
3014 | return; | 3688 | return; |
3015 | } | 3689 | } |
3016 | 3690 | ||
3017 | int count = 0; | 3691 | int count = 0; |
3018 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) | 3692 | m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) |
3019 | { | 3693 | { |
@@ -3024,29 +3698,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3024 | SendAppearanceToAgent(scenePresence); | 3698 | SendAppearanceToAgent(scenePresence); |
3025 | count++; | 3699 | count++; |
3026 | }); | 3700 | }); |
3027 | |||
3028 | m_scene.StatsReporter.AddAgentUpdates(count); | ||
3029 | } | ||
3030 | |||
3031 | /// <summary> | ||
3032 | /// Send appearance from all other root agents to this agent. this agent | ||
3033 | /// can be either root or child | ||
3034 | /// </summary> | ||
3035 | public void SendOtherAgentsAppearanceToMe() | ||
3036 | { | ||
3037 | // m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID); | ||
3038 | |||
3039 | int count = 0; | ||
3040 | m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) | ||
3041 | { | ||
3042 | // only send information about other root agents | ||
3043 | if (scenePresence.UUID == UUID) | ||
3044 | return; | ||
3045 | |||
3046 | scenePresence.SendAppearanceToAgent(this); | ||
3047 | count++; | ||
3048 | }); | ||
3049 | |||
3050 | m_scene.StatsReporter.AddAgentUpdates(count); | 3701 | m_scene.StatsReporter.AddAgentUpdates(count); |
3051 | } | 3702 | } |
3052 | 3703 | ||
@@ -3058,11 +3709,66 @@ namespace OpenSim.Region.Framework.Scenes | |||
3058 | { | 3709 | { |
3059 | // m_log.DebugFormat( | 3710 | // m_log.DebugFormat( |
3060 | // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); | 3711 | // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); |
3712 | if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200) | ||
3713 | return; | ||
3714 | SendAppearanceToAgentNF(avatar); | ||
3715 | } | ||
3061 | 3716 | ||
3062 | avatar.ControllingClient.SendAppearance( | 3717 | public void SendAppearanceToAgentNF(ScenePresence avatar) |
3063 | UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); | 3718 | { |
3719 | if (Invisible) | ||
3720 | avatar.ControllingClient.SendAppearance( | ||
3721 | UUID, Appearance.VisualParams, AvatarAppearance.Invisible.GetBytes()); | ||
3722 | else | ||
3723 | avatar.ControllingClient.SendAppearance( | ||
3724 | UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); | ||
3725 | } | ||
3064 | 3726 | ||
3065 | 3727 | public void SendAnimPackToAgent(ScenePresence p) | |
3728 | { | ||
3729 | if (IsChildAgent || Animator == null) | ||
3730 | return; | ||
3731 | |||
3732 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
3733 | return; | ||
3734 | |||
3735 | Animator.SendAnimPackToClient(p.ControllingClient); | ||
3736 | } | ||
3737 | |||
3738 | public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs) | ||
3739 | { | ||
3740 | if (IsChildAgent) | ||
3741 | return; | ||
3742 | |||
3743 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
3744 | return; | ||
3745 | |||
3746 | p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); | ||
3747 | } | ||
3748 | |||
3749 | public void SendAnimPackToAgentNF(ScenePresence p) | ||
3750 | { | ||
3751 | if (IsChildAgent || Animator == null) | ||
3752 | return; | ||
3753 | Animator.SendAnimPackToClient(p.ControllingClient); | ||
3754 | } | ||
3755 | |||
3756 | public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs) | ||
3757 | { | ||
3758 | p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); | ||
3759 | } | ||
3760 | |||
3761 | public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) | ||
3762 | { | ||
3763 | if (IsChildAgent) | ||
3764 | return; | ||
3765 | |||
3766 | m_scene.ForEachScenePresence(delegate(ScenePresence p) | ||
3767 | { | ||
3768 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
3769 | return; | ||
3770 | p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); | ||
3771 | }); | ||
3066 | } | 3772 | } |
3067 | 3773 | ||
3068 | #endregion | 3774 | #endregion |
@@ -3081,12 +3787,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3081 | } | 3787 | } |
3082 | 3788 | ||
3083 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m | 3789 | // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m |
3084 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || | 3790 | if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance) |
3085 | Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) | ||
3086 | { | 3791 | { |
3087 | m_lastChildAgentUpdatePosition = AbsolutePosition; | 3792 | m_lastChildAgentUpdatePosition = AbsolutePosition; |
3088 | m_lastChildAgentUpdateCamPosition = CameraPosition; | 3793 | // m_lastChildAgentUpdateCamPosition = CameraPosition; |
3089 | 3794 | ||
3795 | /* cadu is not used | ||
3090 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); | 3796 | ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); |
3091 | cadu.ActiveGroupID = UUID.Zero.Guid; | 3797 | cadu.ActiveGroupID = UUID.Zero.Guid; |
3092 | cadu.AgentID = UUID.Guid; | 3798 | cadu.AgentID = UUID.Guid; |
@@ -3100,6 +3806,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3100 | 3806 | ||
3101 | // Throttles | 3807 | // Throttles |
3102 | float multiplier = 1; | 3808 | float multiplier = 1; |
3809 | |||
3103 | int childRegions = KnownRegionCount; | 3810 | int childRegions = KnownRegionCount; |
3104 | if (childRegions != 0) | 3811 | if (childRegions != 0) |
3105 | multiplier = 1f / childRegions; | 3812 | multiplier = 1f / childRegions; |
@@ -3110,9 +3817,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
3110 | 3817 | ||
3111 | cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); | 3818 | cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); |
3112 | cadu.Velocity = Velocity; | 3819 | cadu.Velocity = Velocity; |
3113 | 3820 | */ | |
3114 | AgentPosition agentpos = new AgentPosition(); | 3821 | AgentPosition agentpos = new AgentPosition(); |
3115 | agentpos.CopyFrom(cadu); | 3822 | // agentpos.CopyFrom(cadu, ControllingClient.SessionId); |
3823 | |||
3824 | agentpos.AgentID = new UUID(UUID.Guid); | ||
3825 | agentpos.SessionID = ControllingClient.SessionId; | ||
3826 | |||
3827 | agentpos.Size = Appearance.AvatarSize; | ||
3828 | |||
3829 | agentpos.Center = CameraPosition; | ||
3830 | agentpos.Far = DrawDistance; | ||
3831 | agentpos.Position = AbsolutePosition; | ||
3832 | agentpos.Velocity = Velocity; | ||
3833 | agentpos.RegionHandle = RegionHandle; | ||
3834 | agentpos.Throttles = ControllingClient.GetThrottlesPacked(1); | ||
3835 | |||
3116 | 3836 | ||
3117 | // Let's get this out of the update loop | 3837 | // Let's get this out of the update loop |
3118 | Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); | 3838 | Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); |
@@ -3132,7 +3852,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3132 | protected void CheckForBorderCrossing() | 3852 | protected void CheckForBorderCrossing() |
3133 | { | 3853 | { |
3134 | // Check that we we are not a child | 3854 | // Check that we we are not a child |
3135 | if (IsChildAgent) | 3855 | if (IsChildAgent || IsInTransit) |
3136 | return; | 3856 | return; |
3137 | 3857 | ||
3138 | // If we don't have a PhysActor, we can't cross anyway | 3858 | // If we don't have a PhysActor, we can't cross anyway |
@@ -3142,140 +3862,72 @@ namespace OpenSim.Region.Framework.Scenes | |||
3142 | if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) | 3862 | if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) |
3143 | return; | 3863 | return; |
3144 | 3864 | ||
3145 | if (!IsInTransit) | 3865 | Vector3 pos2 = AbsolutePosition; |
3146 | { | 3866 | Vector3 vel = Velocity; |
3147 | Vector3 pos2 = AbsolutePosition; | ||
3148 | Vector3 vel = Velocity; | ||
3149 | int neighbor = 0; | ||
3150 | int[] fix = new int[2]; | ||
3151 | 3867 | ||
3152 | float timeStep = 0.1f; | 3868 | float timeStep = 0.1f; |
3153 | pos2.X = pos2.X + (vel.X * timeStep); | 3869 | pos2.X += vel.X * timeStep; |
3154 | pos2.Y = pos2.Y + (vel.Y * timeStep); | 3870 | pos2.Y += vel.Y * timeStep; |
3155 | pos2.Z = pos2.Z + (vel.Z * timeStep); | 3871 | pos2.Z += vel.Z * timeStep; |
3156 | 3872 | ||
3157 | if (!IsInTransit) | ||
3158 | { | ||
3159 | // m_log.DebugFormat( | 3873 | // m_log.DebugFormat( |
3160 | // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", | 3874 | // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", |
3161 | // pos2, Name, Scene.Name); | 3875 | // pos2, Name, Scene.Name); |
3162 | 3876 | ||
3163 | // Checks if where it's headed exists a region | 3877 | if( Scene.TestBorderCross(pos2, Cardinals.E) || |
3164 | bool needsTransit = false; | 3878 | Scene.TestBorderCross(pos2, Cardinals.W) || |
3165 | if (m_scene.TestBorderCross(pos2, Cardinals.W)) | 3879 | Scene.TestBorderCross(pos2, Cardinals.N) || |
3166 | { | 3880 | Scene.TestBorderCross(pos2, Cardinals.S) |
3167 | if (m_scene.TestBorderCross(pos2, Cardinals.S)) | 3881 | ) |
3168 | { | 3882 | { |
3169 | needsTransit = true; | 3883 | if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero) |
3170 | neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix); | ||
3171 | } | ||
3172 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) | ||
3173 | { | ||
3174 | needsTransit = true; | ||
3175 | neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix); | ||
3176 | } | ||
3177 | else | ||
3178 | { | ||
3179 | needsTransit = true; | ||
3180 | neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix); | ||
3181 | } | ||
3182 | } | ||
3183 | else if (m_scene.TestBorderCross(pos2, Cardinals.E)) | ||
3184 | { | ||
3185 | if (m_scene.TestBorderCross(pos2, Cardinals.S)) | ||
3186 | { | ||
3187 | needsTransit = true; | ||
3188 | neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix); | ||
3189 | } | ||
3190 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) | ||
3191 | { | ||
3192 | needsTransit = true; | ||
3193 | neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix); | ||
3194 | } | ||
3195 | else | ||
3196 | { | ||
3197 | needsTransit = true; | ||
3198 | neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix); | ||
3199 | } | ||
3200 | } | ||
3201 | else if (m_scene.TestBorderCross(pos2, Cardinals.S)) | ||
3202 | { | ||
3203 | needsTransit = true; | ||
3204 | neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix); | ||
3205 | } | ||
3206 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) | ||
3207 | { | ||
3208 | needsTransit = true; | ||
3209 | neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix); | ||
3210 | } | ||
3211 | |||
3212 | // Makes sure avatar does not end up outside region | ||
3213 | if (neighbor <= 0) | ||
3214 | { | ||
3215 | if (needsTransit) | ||
3216 | { | ||
3217 | if (m_requestedSitTargetUUID == UUID.Zero) | ||
3218 | { | ||
3219 | bool isFlying = Flying; | ||
3220 | RemoveFromPhysicalScene(); | ||
3221 | |||
3222 | Vector3 pos = AbsolutePosition; | ||
3223 | if (AbsolutePosition.X < 0) | ||
3224 | pos.X += Velocity.X * 2; | ||
3225 | else if (AbsolutePosition.X > Constants.RegionSize) | ||
3226 | pos.X -= Velocity.X * 2; | ||
3227 | if (AbsolutePosition.Y < 0) | ||
3228 | pos.Y += Velocity.Y * 2; | ||
3229 | else if (AbsolutePosition.Y > Constants.RegionSize) | ||
3230 | pos.Y -= Velocity.Y * 2; | ||
3231 | Velocity = Vector3.Zero; | ||
3232 | AbsolutePosition = pos; | ||
3233 | |||
3234 | // m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition); | ||
3235 | |||
3236 | AddToPhysicalScene(isFlying); | ||
3237 | } | ||
3238 | } | ||
3239 | } | ||
3240 | else if (neighbor > 0) | ||
3241 | { | ||
3242 | if (!CrossToNewRegion()) | ||
3243 | { | ||
3244 | if (m_requestedSitTargetUUID == UUID.Zero) | ||
3245 | { | ||
3246 | bool isFlying = Flying; | ||
3247 | RemoveFromPhysicalScene(); | ||
3248 | |||
3249 | Vector3 pos = AbsolutePosition; | ||
3250 | if (AbsolutePosition.X < 0) | ||
3251 | pos.X += Velocity.X * 2; | ||
3252 | else if (AbsolutePosition.X > Constants.RegionSize) | ||
3253 | pos.X -= Velocity.X * 2; | ||
3254 | if (AbsolutePosition.Y < 0) | ||
3255 | pos.Y += Velocity.Y * 2; | ||
3256 | else if (AbsolutePosition.Y > Constants.RegionSize) | ||
3257 | pos.Y -= Velocity.Y * 2; | ||
3258 | Velocity = Vector3.Zero; | ||
3259 | AbsolutePosition = pos; | ||
3260 | |||
3261 | AddToPhysicalScene(isFlying); | ||
3262 | } | ||
3263 | } | ||
3264 | } | ||
3265 | } | ||
3266 | else | ||
3267 | { | 3884 | { |
3268 | // This constant has been inferred from experimentation | 3885 | // we don't have entity transfer module |
3269 | // I'm not sure what this value should be, so I tried a few values. | 3886 | Vector3 pos = AbsolutePosition; |
3270 | timeStep = 0.04f; | 3887 | float px = pos.X; |
3271 | pos2 = AbsolutePosition; | 3888 | if (px < 0) |
3272 | pos2.X = pos2.X + (vel.X * timeStep); | 3889 | pos.X += Velocity.X * 2; |
3273 | pos2.Y = pos2.Y + (vel.Y * timeStep); | 3890 | else if (px > m_scene.RegionInfo.RegionSizeX) |
3274 | // Don't touch the Z | 3891 | pos.X -= Velocity.X * 2; |
3275 | m_pos = pos2; | 3892 | |
3276 | m_log.DebugFormat("[SCENE PRESENCE]: In transit m_pos={0}", m_pos); | 3893 | float py = pos.Y; |
3894 | if (py < 0) | ||
3895 | pos.Y += Velocity.Y * 2; | ||
3896 | else if (py > m_scene.RegionInfo.RegionSizeY) | ||
3897 | pos.Y -= Velocity.Y * 2; | ||
3898 | |||
3899 | Velocity = Vector3.Zero; | ||
3900 | AbsolutePosition = pos; | ||
3277 | } | 3901 | } |
3278 | } | 3902 | } |
3903 | } | ||
3904 | |||
3905 | public void CrossToNewRegionFail() | ||
3906 | { | ||
3907 | if (m_requestedSitTargetUUID == UUID.Zero) | ||
3908 | { | ||
3909 | bool isFlying = Flying; | ||
3910 | RemoveFromPhysicalScene(); | ||
3911 | |||
3912 | Vector3 pos = AbsolutePosition; | ||
3913 | float px = pos.X; | ||
3914 | if (px < 0) | ||
3915 | pos.X += Velocity.X * 2; | ||
3916 | else if (px > m_scene.RegionInfo.RegionSizeX) | ||
3917 | pos.X -= Velocity.X * 2; | ||
3918 | |||
3919 | float py = pos.Y; | ||
3920 | if (py < 0) | ||
3921 | pos.Y += Velocity.Y * 2; | ||
3922 | else if (py > m_scene.RegionInfo.RegionSizeY) | ||
3923 | pos.Y -= Velocity.Y * 2; | ||
3924 | |||
3925 | Velocity = Vector3.Zero; | ||
3926 | AbsolutePosition = pos; | ||
3927 | |||
3928 | AddToPhysicalScene(isFlying); | ||
3929 | } | ||
3930 | |||
3279 | } | 3931 | } |
3280 | 3932 | ||
3281 | /// <summary> | 3933 | /// <summary> |
@@ -3286,21 +3938,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3286 | /// </summary> | 3938 | /// </summary> |
3287 | protected bool CrossToNewRegion() | 3939 | protected bool CrossToNewRegion() |
3288 | { | 3940 | { |
3941 | bool result = false; | ||
3942 | // parcelRegionCross(false); | ||
3289 | try | 3943 | try |
3290 | { | 3944 | { |
3291 | return m_scene.CrossAgentToNewRegion(this, Flying); | 3945 | result = m_scene.CrossAgentToNewRegion(this, Flying); |
3292 | } | 3946 | } |
3293 | catch | 3947 | catch |
3294 | { | 3948 | { |
3295 | return m_scene.CrossAgentToNewRegion(this, false); | 3949 | // result = m_scene.CrossAgentToNewRegion(this, false); |
3950 | return false; | ||
3296 | } | 3951 | } |
3297 | } | 3952 | // if(!result) |
3953 | // parcelRegionCross(true); | ||
3954 | |||
3955 | return result; | ||
3298 | 3956 | ||
3299 | public void RestoreInCurrentScene() | ||
3300 | { | ||
3301 | AddToPhysicalScene(false); // not exactly false | ||
3302 | } | 3957 | } |
3303 | 3958 | ||
3959 | /* useless. Either use MakeChild or delete the presence | ||
3304 | public void Reset() | 3960 | public void Reset() |
3305 | { | 3961 | { |
3306 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); | 3962 | // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); |
@@ -3311,7 +3967,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3311 | 3967 | ||
3312 | Animator.ResetAnimations(); | 3968 | Animator.ResetAnimations(); |
3313 | } | 3969 | } |
3314 | 3970 | */ | |
3315 | /// <summary> | 3971 | /// <summary> |
3316 | /// Computes which child agents to close when the scene presence moves to another region. | 3972 | /// Computes which child agents to close when the scene presence moves to another region. |
3317 | /// Removes those regions from m_knownRegions. | 3973 | /// Removes those regions from m_knownRegions. |
@@ -3350,15 +4006,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
3350 | if (byebyeRegions.Count > 0) | 4006 | if (byebyeRegions.Count > 0) |
3351 | { | 4007 | { |
3352 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); | 4008 | m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); |
3353 | Util.FireAndForget(delegate | 4009 | |
3354 | { | 4010 | AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID); |
3355 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); | 4011 | string auth = string.Empty; |
3356 | }); | 4012 | if (acd != null) |
4013 | auth = acd.SessionID.ToString(); | ||
4014 | m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); | ||
3357 | } | 4015 | } |
3358 | 4016 | ||
3359 | foreach (ulong handle in byebyeRegions) | 4017 | foreach (ulong handle in byebyeRegions) |
3360 | { | 4018 | { |
3361 | RemoveNeighbourRegion(handle); | 4019 | RemoveNeighbourRegion(handle); |
4020 | Scene.CapsModule.DropChildSeed(UUID, handle); | ||
3362 | } | 4021 | } |
3363 | } | 4022 | } |
3364 | 4023 | ||
@@ -3370,6 +4029,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3370 | /// </summary> | 4029 | /// </summary> |
3371 | public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) | 4030 | public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) |
3372 | { | 4031 | { |
4032 | int oldgodlevel = GodLevel; | ||
4033 | |||
3373 | if (godStatus) | 4034 | if (godStatus) |
3374 | { | 4035 | { |
3375 | // For now, assign god level 200 to anyone | 4036 | // For now, assign god level 200 to anyone |
@@ -3390,11 +4051,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3390 | } | 4051 | } |
3391 | 4052 | ||
3392 | ControllingClient.SendAdminResponse(token, (uint)GodLevel); | 4053 | ControllingClient.SendAdminResponse(token, (uint)GodLevel); |
4054 | |||
4055 | if(oldgodlevel != GodLevel) | ||
4056 | parcelGodCheck(m_currentParcelUUID, GodLevel >= 200); | ||
3393 | } | 4057 | } |
3394 | 4058 | ||
3395 | #region Child Agent Updates | 4059 | #region Child Agent Updates |
3396 | 4060 | ||
3397 | public void ChildAgentDataUpdate(AgentData cAgentData) | 4061 | public void UpdateChildAgent(AgentData cAgentData) |
3398 | { | 4062 | { |
3399 | // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); | 4063 | // m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); |
3400 | if (!IsChildAgent) | 4064 | if (!IsChildAgent) |
@@ -3404,19 +4068,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
3404 | } | 4068 | } |
3405 | 4069 | ||
3406 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); | 4070 | private static Vector3 marker = new Vector3(-1f, -1f, -1f); |
4071 | |||
3407 | private void RaiseUpdateThrottles() | 4072 | private void RaiseUpdateThrottles() |
3408 | { | 4073 | { |
3409 | m_scene.EventManager.TriggerThrottleUpdate(this); | 4074 | m_scene.EventManager.TriggerThrottleUpdate(this); |
3410 | } | 4075 | } |
4076 | |||
3411 | /// <summary> | 4077 | /// <summary> |
3412 | /// This updates important decision making data about a child agent | 4078 | /// This updates important decision making data about a child agent |
3413 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region | 4079 | /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region |
3414 | /// </summary> | 4080 | /// </summary> |
3415 | public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) | 4081 | public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) |
3416 | { | 4082 | { |
3417 | if (!IsChildAgent) | 4083 | if (!IsChildAgent) |
3418 | return; | 4084 | return; |
3419 | 4085 | ||
4086 | RegionHandle = cAgentData.RegionHandle; | ||
4087 | |||
3420 | //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); | 4088 | //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); |
3421 | int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; | 4089 | int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; |
3422 | int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; | 4090 | int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; |
@@ -3426,8 +4094,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3426 | // When we get to the point of re-computing neighbors everytime this | 4094 | // When we get to the point of re-computing neighbors everytime this |
3427 | // changes, then start using the agent's drawdistance rather than the | 4095 | // changes, then start using the agent's drawdistance rather than the |
3428 | // region's draw distance. | 4096 | // region's draw distance. |
3429 | // DrawDistance = cAgentData.Far; | 4097 | DrawDistance = cAgentData.Far; |
3430 | DrawDistance = Scene.DefaultDrawDistance; | 4098 | // DrawDistance = Scene.DefaultDrawDistance; |
3431 | 4099 | ||
3432 | if (cAgentData.Position != marker) // UGH!! | 4100 | if (cAgentData.Position != marker) // UGH!! |
3433 | m_pos = cAgentData.Position + offset; | 4101 | m_pos = cAgentData.Position + offset; |
@@ -3441,10 +4109,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
3441 | CameraPosition = cAgentData.Center + offset; | 4109 | CameraPosition = cAgentData.Center + offset; |
3442 | 4110 | ||
3443 | if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) | 4111 | if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) |
3444 | ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); | 4112 | { |
4113 | // some scaling factor | ||
4114 | float x = m_pos.X; | ||
4115 | if (x > m_scene.RegionInfo.RegionSizeX) | ||
4116 | x -= m_scene.RegionInfo.RegionSizeX; | ||
4117 | float y = m_pos.Y; | ||
4118 | if (y > m_scene.RegionInfo.RegionSizeY) | ||
4119 | y -= m_scene.RegionInfo.RegionSizeY; | ||
4120 | |||
4121 | x = x * x + y * y; | ||
4122 | |||
4123 | const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize; | ||
4124 | float factor = 1.0f - distScale * x; | ||
4125 | if (factor < 0.2f) | ||
4126 | factor = 0.2f; | ||
4127 | |||
4128 | ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor); | ||
4129 | } | ||
4130 | |||
4131 | if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0) | ||
4132 | { | ||
4133 | if (Scene.CapsModule != null) | ||
4134 | { | ||
4135 | Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds); | ||
4136 | } | ||
4137 | |||
4138 | KnownRegions = cAgentData.ChildrenCapSeeds; | ||
4139 | } | ||
3445 | 4140 | ||
3446 | //cAgentData.AVHeight; | 4141 | //cAgentData.AVHeight; |
3447 | RegionHandle = cAgentData.RegionHandle; | ||
3448 | //m_velocity = cAgentData.Velocity; | 4142 | //m_velocity = cAgentData.Velocity; |
3449 | } | 4143 | } |
3450 | 4144 | ||
@@ -3454,6 +4148,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3454 | 4148 | ||
3455 | cAgent.AgentID = UUID; | 4149 | cAgent.AgentID = UUID; |
3456 | cAgent.RegionID = Scene.RegionInfo.RegionID; | 4150 | cAgent.RegionID = Scene.RegionInfo.RegionID; |
4151 | cAgent.SessionID = ControllingClient.SessionId; | ||
3457 | 4152 | ||
3458 | cAgent.Position = AbsolutePosition; | 4153 | cAgent.Position = AbsolutePosition; |
3459 | cAgent.Velocity = m_velocity; | 4154 | cAgent.Velocity = m_velocity; |
@@ -3465,16 +4160,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3465 | cAgent.Far = DrawDistance; | 4160 | cAgent.Far = DrawDistance; |
3466 | 4161 | ||
3467 | // Throttles | 4162 | // Throttles |
3468 | float multiplier = 1; | 4163 | cAgent.Throttles = ControllingClient.GetThrottlesPacked(1); |
3469 | int childRegions = KnownRegionCount; | ||
3470 | if (childRegions != 0) | ||
3471 | multiplier = 1f / childRegions; | ||
3472 | |||
3473 | // Minimum throttle for a child region is 1/4 of the root region throttle | ||
3474 | if (multiplier <= 0.25f) | ||
3475 | multiplier = 0.25f; | ||
3476 | |||
3477 | cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); | ||
3478 | 4164 | ||
3479 | cAgent.HeadRotation = m_headrotation; | 4165 | cAgent.HeadRotation = m_headrotation; |
3480 | cAgent.BodyRotation = Rotation; | 4166 | cAgent.BodyRotation = Rotation; |
@@ -3487,7 +4173,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3487 | 4173 | ||
3488 | cAgent.AlwaysRun = SetAlwaysRun; | 4174 | cAgent.AlwaysRun = SetAlwaysRun; |
3489 | 4175 | ||
3490 | cAgent.Appearance = new AvatarAppearance(Appearance); | 4176 | // make clear we want the all thing |
4177 | cAgent.Appearance = new AvatarAppearance(Appearance,true,true); | ||
3491 | 4178 | ||
3492 | cAgent.ParentPart = ParentUUID; | 4179 | cAgent.ParentPart = ParentUUID; |
3493 | cAgent.SitOffset = PrevSitOffset; | 4180 | cAgent.SitOffset = PrevSitOffset; |
@@ -3513,13 +4200,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
3513 | cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; | 4200 | cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; |
3514 | cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; | 4201 | cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; |
3515 | 4202 | ||
4203 | cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs(); | ||
4204 | |||
4205 | cAgent.MotionState = (byte)Animator.currentControlState; | ||
4206 | |||
3516 | if (Scene.AttachmentsModule != null) | 4207 | if (Scene.AttachmentsModule != null) |
3517 | Scene.AttachmentsModule.CopyAttachments(this, cAgent); | 4208 | Scene.AttachmentsModule.CopyAttachments(this, cAgent); |
3518 | } | 4209 | } |
3519 | 4210 | ||
3520 | private void CopyFrom(AgentData cAgent) | 4211 | private void CopyFrom(AgentData cAgent) |
3521 | { | 4212 | { |
3522 | m_originRegionID = cAgent.RegionID; | ||
3523 | 4213 | ||
3524 | m_callbackURI = cAgent.CallbackURI; | 4214 | m_callbackURI = cAgent.CallbackURI; |
3525 | // m_log.DebugFormat( | 4215 | // m_log.DebugFormat( |
@@ -3538,8 +4228,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3538 | // When we get to the point of re-computing neighbors everytime this | 4228 | // When we get to the point of re-computing neighbors everytime this |
3539 | // changes, then start using the agent's drawdistance rather than the | 4229 | // changes, then start using the agent's drawdistance rather than the |
3540 | // region's draw distance. | 4230 | // region's draw distance. |
3541 | // DrawDistance = cAgent.Far; | 4231 | DrawDistance = cAgent.Far; |
3542 | DrawDistance = Scene.DefaultDrawDistance; | 4232 | //DrawDistance = Scene.DefaultDrawDistance; |
4233 | |||
4234 | if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0) | ||
4235 | { | ||
4236 | if (Scene.CapsModule != null) | ||
4237 | { | ||
4238 | Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds); | ||
4239 | } | ||
4240 | KnownRegions = cAgent.ChildrenCapSeeds; | ||
4241 | } | ||
3543 | 4242 | ||
3544 | if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) | 4243 | if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) |
3545 | ControllingClient.SetChildAgentThrottle(cAgent.Throttles); | 4244 | ControllingClient.SetChildAgentThrottle(cAgent.Throttles); |
@@ -3552,14 +4251,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3552 | GodLevel = cAgent.GodLevel; | 4251 | GodLevel = cAgent.GodLevel; |
3553 | SetAlwaysRun = cAgent.AlwaysRun; | 4252 | SetAlwaysRun = cAgent.AlwaysRun; |
3554 | 4253 | ||
4254 | |||
3555 | Appearance = new AvatarAppearance(cAgent.Appearance); | 4255 | Appearance = new AvatarAppearance(cAgent.Appearance); |
4256 | /* | ||
4257 | bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | ||
4258 | |||
3556 | if (PhysicsActor != null) | 4259 | if (PhysicsActor != null) |
3557 | { | 4260 | { |
3558 | bool isFlying = Flying; | ||
3559 | RemoveFromPhysicalScene(); | 4261 | RemoveFromPhysicalScene(); |
3560 | AddToPhysicalScene(isFlying); | 4262 | AddToPhysicalScene(isFlying); |
3561 | } | 4263 | } |
3562 | 4264 | */ | |
3563 | try | 4265 | try |
3564 | { | 4266 | { |
3565 | lock (scriptedcontrols) | 4267 | lock (scriptedcontrols) |
@@ -3583,16 +4285,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
3583 | } | 4285 | } |
3584 | catch { } | 4286 | catch { } |
3585 | 4287 | ||
4288 | Animator.ResetAnimations(); | ||
4289 | |||
4290 | Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides); | ||
4291 | |||
3586 | // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? | 4292 | // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? |
3587 | if (cAgent.Anims != null) | ||
3588 | Animator.Animations.FromArray(cAgent.Anims); | ||
3589 | if (cAgent.DefaultAnim != null) | 4293 | if (cAgent.DefaultAnim != null) |
3590 | Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); | 4294 | Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); |
3591 | if (cAgent.AnimState != null) | 4295 | if (cAgent.AnimState != null) |
3592 | Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); | 4296 | Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); |
4297 | if (cAgent.Anims != null) | ||
4298 | Animator.Animations.FromArray(cAgent.Anims); | ||
4299 | if (cAgent.MotionState != 0) | ||
4300 | Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; | ||
3593 | 4301 | ||
3594 | if (Scene.AttachmentsModule != null) | 4302 | if (Scene.AttachmentsModule != null) |
3595 | Scene.AttachmentsModule.CopyAttachments(cAgent, this); | 4303 | Scene.AttachmentsModule.CopyAttachments(cAgent, this); |
4304 | |||
4305 | lock (m_originRegionIDAccessLock) | ||
4306 | m_originRegionID = cAgent.RegionID; | ||
4307 | |||
3596 | } | 4308 | } |
3597 | 4309 | ||
3598 | public bool CopyAgent(out IAgentData agent) | 4310 | public bool CopyAgent(out IAgentData agent) |
@@ -3609,12 +4321,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3609 | /// </summary> | 4321 | /// </summary> |
3610 | public void UpdateMovement() | 4322 | public void UpdateMovement() |
3611 | { | 4323 | { |
4324 | if (IsInTransit) | ||
4325 | return; | ||
3612 | if (m_forceToApply.HasValue) | 4326 | if (m_forceToApply.HasValue) |
3613 | { | 4327 | { |
3614 | Vector3 force = m_forceToApply.Value; | 4328 | Vector3 force = m_forceToApply.Value; |
3615 | 4329 | ||
3616 | Updated = true; | ||
3617 | |||
3618 | Velocity = force; | 4330 | Velocity = force; |
3619 | 4331 | ||
3620 | m_forceToApply = null; | 4332 | m_forceToApply = null; |
@@ -3689,14 +4401,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3689 | { | 4401 | { |
3690 | if (IsChildAgent || Animator == null) | 4402 | if (IsChildAgent || Animator == null) |
3691 | return; | 4403 | return; |
3692 | 4404 | ||
4405 | if(IsInTransit) | ||
4406 | return; | ||
3693 | //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) | 4407 | //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) |
3694 | // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( | 4408 | // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( |
3695 | // as of this comment the interval is set in AddToPhysicalScene | 4409 | // as of this comment the interval is set in AddToPhysicalScene |
3696 | 4410 | ||
3697 | // if (m_updateCount > 0) | 4411 | // if (m_updateCount > 0) |
3698 | // { | 4412 | // { |
3699 | Animator.UpdateMovementAnimations(); | 4413 | if (Animator.UpdateMovementAnimations()) |
4414 | TriggerScenePresenceUpdated(); | ||
3700 | // m_updateCount--; | 4415 | // m_updateCount--; |
3701 | // } | 4416 | // } |
3702 | 4417 | ||
@@ -3860,6 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3860 | // Animator.Close(); | 4575 | // Animator.Close(); |
3861 | Animator = null; | 4576 | Animator = null; |
3862 | 4577 | ||
4578 | LifecycleState = ScenePresenceState.Removed; | ||
3863 | } | 4579 | } |
3864 | 4580 | ||
3865 | public void AddAttachment(SceneObjectGroup gobj) | 4581 | public void AddAttachment(SceneObjectGroup gobj) |
@@ -4039,6 +4755,287 @@ namespace OpenSim.Region.Framework.Scenes | |||
4039 | return validated; | 4755 | return validated; |
4040 | } | 4756 | } |
4041 | 4757 | ||
4758 | public void SendAttachmentsToAllAgents() | ||
4759 | { | ||
4760 | lock (m_attachments) | ||
4761 | { | ||
4762 | foreach (SceneObjectGroup sog in m_attachments) | ||
4763 | { | ||
4764 | m_scene.ForEachScenePresence(delegate(ScenePresence p) | ||
4765 | { | ||
4766 | if (p != this && sog.HasPrivateAttachmentPoint) | ||
4767 | return; | ||
4768 | |||
4769 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
4770 | return; | ||
4771 | |||
4772 | SendTerseUpdateToAgentNF(p); | ||
4773 | SendAttachmentFullUpdateToAgentNF(sog, p); | ||
4774 | }); | ||
4775 | } | ||
4776 | } | ||
4777 | } | ||
4778 | |||
4779 | // send attachments to a client without filters except for huds | ||
4780 | // for now they are checked in several places down the line... | ||
4781 | public void SendAttachmentsToAgentNF(ScenePresence p) | ||
4782 | { | ||
4783 | SendTerseUpdateToAgentNF(p); | ||
4784 | lock (m_attachments) | ||
4785 | { | ||
4786 | foreach (SceneObjectGroup sog in m_attachments) | ||
4787 | { | ||
4788 | SendAttachmentFullUpdateToAgentNF(sog, p); | ||
4789 | } | ||
4790 | } | ||
4791 | } | ||
4792 | |||
4793 | public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p) | ||
4794 | { | ||
4795 | if (p != this && sog.HasPrivateAttachmentPoint) | ||
4796 | return; | ||
4797 | |||
4798 | SceneObjectPart[] parts = sog.Parts; | ||
4799 | SceneObjectPart rootpart = sog.RootPart; | ||
4800 | |||
4801 | p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate); | ||
4802 | |||
4803 | for (int i = 0; i < parts.Length; i++) | ||
4804 | { | ||
4805 | SceneObjectPart part = parts[i]; | ||
4806 | if (part == rootpart) | ||
4807 | continue; | ||
4808 | p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); | ||
4809 | } | ||
4810 | } | ||
4811 | |||
4812 | public void SendAttachmentScheduleUpdate(SceneObjectGroup sog) | ||
4813 | { | ||
4814 | if (IsChildAgent || IsInTransit) | ||
4815 | return; | ||
4816 | |||
4817 | SceneObjectPart[] origparts = sog.Parts; | ||
4818 | SceneObjectPart[] parts = new SceneObjectPart[origparts.Length]; | ||
4819 | PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length]; | ||
4820 | |||
4821 | SceneObjectPart rootpart = sog.RootPart; | ||
4822 | UpdateRequired rootreq = sog.RootPart.UpdateFlag; | ||
4823 | |||
4824 | int j = 0; | ||
4825 | bool allterse = true; | ||
4826 | for (int i = 0; i < origparts.Length; i++) | ||
4827 | { | ||
4828 | if (origparts[i] != rootpart) | ||
4829 | { | ||
4830 | switch (origparts[i].UpdateFlag) | ||
4831 | { | ||
4832 | case UpdateRequired.NONE: | ||
4833 | break; | ||
4834 | |||
4835 | case UpdateRequired.TERSE: | ||
4836 | flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
4837 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
4838 | parts[j] = origparts[i]; | ||
4839 | j++; | ||
4840 | break; | ||
4841 | |||
4842 | case UpdateRequired.FULL: | ||
4843 | flags[j] = PrimUpdateFlags.FullUpdate; | ||
4844 | allterse = false; | ||
4845 | parts[j] = origparts[i]; | ||
4846 | j++; | ||
4847 | break; | ||
4848 | } | ||
4849 | } | ||
4850 | origparts[i].UpdateFlag = 0; | ||
4851 | } | ||
4852 | |||
4853 | if (j == 0 && rootreq == UpdateRequired.NONE) | ||
4854 | return; | ||
4855 | |||
4856 | PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate; | ||
4857 | |||
4858 | if (rootreq != UpdateRequired.FULL && allterse) | ||
4859 | { | ||
4860 | rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
4861 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
4862 | } | ||
4863 | |||
4864 | int nparts = j; | ||
4865 | |||
4866 | ControllingClient.SendEntityUpdate(rootpart, rootflag); | ||
4867 | |||
4868 | for (int i = 0; i < nparts; i++) | ||
4869 | { | ||
4870 | ControllingClient.SendEntityUpdate(parts[i], flags[i]); | ||
4871 | } | ||
4872 | |||
4873 | if (sog.HasPrivateAttachmentPoint) | ||
4874 | return; | ||
4875 | |||
4876 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
4877 | foreach (ScenePresence p in allPresences) | ||
4878 | { | ||
4879 | if (p == this) | ||
4880 | continue; | ||
4881 | |||
4882 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
4883 | continue; | ||
4884 | |||
4885 | p.ControllingClient.SendEntityUpdate(rootpart, rootflag); | ||
4886 | |||
4887 | for (int i = 0; i < nparts; i++) | ||
4888 | { | ||
4889 | p.ControllingClient.SendEntityUpdate(parts[i], flags[i]); | ||
4890 | } | ||
4891 | } | ||
4892 | } | ||
4893 | |||
4894 | public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag) | ||
4895 | { | ||
4896 | if (IsChildAgent || IsInTransit) | ||
4897 | return; | ||
4898 | |||
4899 | PrimUpdateFlags flag; | ||
4900 | switch (UpdateFlag) | ||
4901 | { | ||
4902 | case UpdateRequired.TERSE: | ||
4903 | flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
4904 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
4905 | break; | ||
4906 | |||
4907 | case UpdateRequired.FULL: | ||
4908 | flag = PrimUpdateFlags.FullUpdate; | ||
4909 | break; | ||
4910 | |||
4911 | default: | ||
4912 | return; | ||
4913 | } | ||
4914 | |||
4915 | SceneObjectPart[] parts = sog.Parts; | ||
4916 | SceneObjectPart rootpart = sog.RootPart; | ||
4917 | |||
4918 | // rootpart.UpdateFlag = 0; | ||
4919 | |||
4920 | ControllingClient.SendEntityUpdate(rootpart, flag); | ||
4921 | |||
4922 | for (int i = 0; i < parts.Length; i++) | ||
4923 | { | ||
4924 | SceneObjectPart part = parts[i]; | ||
4925 | if (part == rootpart) | ||
4926 | continue; | ||
4927 | ControllingClient.SendEntityUpdate(part, flag); | ||
4928 | // part.UpdateFlag = 0; | ||
4929 | } | ||
4930 | |||
4931 | if (sog.HasPrivateAttachmentPoint) | ||
4932 | return; | ||
4933 | |||
4934 | |||
4935 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
4936 | foreach (ScenePresence p in allPresences) | ||
4937 | { | ||
4938 | if (p == this) | ||
4939 | continue; | ||
4940 | |||
4941 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
4942 | continue; | ||
4943 | |||
4944 | p.ControllingClient.SendEntityUpdate(rootpart, flag); | ||
4945 | |||
4946 | for (int i = 0; i < parts.Length; i++) | ||
4947 | { | ||
4948 | SceneObjectPart part = parts[i]; | ||
4949 | if (part == rootpart) | ||
4950 | continue; | ||
4951 | p.ControllingClient.SendEntityUpdate(part, flag); | ||
4952 | } | ||
4953 | } | ||
4954 | } | ||
4955 | |||
4956 | public void SendAttachmentScheduleUpdate(SceneObjectPart part) | ||
4957 | { | ||
4958 | if (IsChildAgent || IsInTransit) | ||
4959 | return; | ||
4960 | |||
4961 | |||
4962 | PrimUpdateFlags flag; | ||
4963 | switch (part.UpdateFlag) | ||
4964 | { | ||
4965 | case UpdateRequired.TERSE: | ||
4966 | flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
4967 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
4968 | break; | ||
4969 | |||
4970 | case UpdateRequired.FULL: | ||
4971 | flag = PrimUpdateFlags.FullUpdate; | ||
4972 | break; | ||
4973 | |||
4974 | default: | ||
4975 | return; | ||
4976 | } | ||
4977 | |||
4978 | part.UpdateFlag = 0; | ||
4979 | |||
4980 | ControllingClient.SendEntityUpdate(part, flag); | ||
4981 | |||
4982 | if (part.ParentGroup.HasPrivateAttachmentPoint) | ||
4983 | return; | ||
4984 | |||
4985 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
4986 | foreach (ScenePresence p in allPresences) | ||
4987 | { | ||
4988 | if (p == this) | ||
4989 | continue; | ||
4990 | |||
4991 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
4992 | continue; | ||
4993 | |||
4994 | p.ControllingClient.SendEntityUpdate(part, flag); | ||
4995 | } | ||
4996 | } | ||
4997 | |||
4998 | |||
4999 | public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag) | ||
5000 | { | ||
5001 | if (IsChildAgent || IsInTransit) | ||
5002 | return; | ||
5003 | |||
5004 | PrimUpdateFlags flag; | ||
5005 | switch (UpdateFlag) | ||
5006 | { | ||
5007 | case UpdateRequired.TERSE: | ||
5008 | flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | ||
5009 | | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; | ||
5010 | break; | ||
5011 | |||
5012 | case UpdateRequired.FULL: | ||
5013 | flag = PrimUpdateFlags.FullUpdate; | ||
5014 | break; | ||
5015 | |||
5016 | default: | ||
5017 | return; | ||
5018 | } | ||
5019 | |||
5020 | // part.UpdateFlag = 0; | ||
5021 | |||
5022 | ControllingClient.SendEntityUpdate(part, flag); | ||
5023 | |||
5024 | if (part.ParentGroup.HasPrivateAttachmentPoint) | ||
5025 | return; | ||
5026 | |||
5027 | List<ScenePresence> allPresences = m_scene.GetScenePresences(); | ||
5028 | foreach (ScenePresence p in allPresences) | ||
5029 | { | ||
5030 | if (p == this) | ||
5031 | continue; | ||
5032 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) | ||
5033 | continue; | ||
5034 | |||
5035 | p.ControllingClient.SendEntityUpdate(part, flag); | ||
5036 | } | ||
5037 | } | ||
5038 | |||
4042 | /// <summary> | 5039 | /// <summary> |
4043 | /// Send a script event to this scene presence's attachments | 5040 | /// Send a script event to this scene presence's attachments |
4044 | /// </summary> | 5041 | /// </summary> |
@@ -4157,6 +5154,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
4157 | ControllingClient.SendTakeControls(int.MaxValue, false, false); | 5154 | ControllingClient.SendTakeControls(int.MaxValue, false, false); |
4158 | } | 5155 | } |
4159 | 5156 | ||
5157 | public void ClearControls() | ||
5158 | { | ||
5159 | IgnoredControls = ScriptControlled.CONTROL_ZERO; | ||
5160 | lock (scriptedcontrols) | ||
5161 | { | ||
5162 | scriptedcontrols.Clear(); | ||
5163 | } | ||
5164 | } | ||
5165 | |||
4160 | private void UnRegisterSeatControls(UUID obj) | 5166 | private void UnRegisterSeatControls(UUID obj) |
4161 | { | 5167 | { |
4162 | List<UUID> takers = new List<UUID>(); | 5168 | List<UUID> takers = new List<UUID>(); |
@@ -4546,8 +5552,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
4546 | pos = land.LandData.UserLocation; | 5552 | pos = land.LandData.UserLocation; |
4547 | } | 5553 | } |
4548 | } | 5554 | } |
4549 | 5555 | // this is now done in completeMovement for all cases and not just this | |
4550 | land.SendLandUpdateToClient(ControllingClient); | 5556 | // land.SendLandUpdateToClient(ControllingClient); |
4551 | } | 5557 | } |
4552 | } | 5558 | } |
4553 | 5559 | ||
@@ -4562,6 +5568,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4562 | detobj.velVector = obj.Velocity; | 5568 | detobj.velVector = obj.Velocity; |
4563 | detobj.colliderType = 0; | 5569 | detobj.colliderType = 0; |
4564 | detobj.groupUUID = obj.GroupID; | 5570 | detobj.groupUUID = obj.GroupID; |
5571 | detobj.linkNumber = 0; | ||
4565 | 5572 | ||
4566 | return detobj; | 5573 | return detobj; |
4567 | } | 5574 | } |
@@ -4577,6 +5584,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4577 | detobj.velVector = av.Velocity; | 5584 | detobj.velVector = av.Velocity; |
4578 | detobj.colliderType = 0; | 5585 | detobj.colliderType = 0; |
4579 | detobj.groupUUID = av.ControllingClient.ActiveGroupId; | 5586 | detobj.groupUUID = av.ControllingClient.ActiveGroupId; |
5587 | detobj.linkNumber = 0; | ||
4580 | 5588 | ||
4581 | return detobj; | 5589 | return detobj; |
4582 | } | 5590 | } |
@@ -4592,7 +5600,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4592 | detobj.velVector = Vector3.Zero; | 5600 | detobj.velVector = Vector3.Zero; |
4593 | detobj.colliderType = 0; | 5601 | detobj.colliderType = 0; |
4594 | detobj.groupUUID = UUID.Zero; | 5602 | detobj.groupUUID = UUID.Zero; |
4595 | 5603 | detobj.linkNumber = 0; | |
4596 | return detobj; | 5604 | return detobj; |
4597 | } | 5605 | } |
4598 | 5606 | ||
@@ -4684,6 +5692,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
4684 | 5692 | ||
4685 | else | 5693 | else |
4686 | { | 5694 | { |
5695 | bool candoparcelSound = ParcelAllowThisAvatarSounds; | ||
5696 | |||
4687 | foreach (uint id in coldata.Keys) | 5697 | foreach (uint id in coldata.Keys) |
4688 | { | 5698 | { |
4689 | thisHitColliders.Add(id); | 5699 | thisHitColliders.Add(id); |
@@ -4691,7 +5701,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4691 | { | 5701 | { |
4692 | startedColliders.Add(id); | 5702 | startedColliders.Add(id); |
4693 | curcontact = coldata[id]; | 5703 | curcontact = coldata[id]; |
4694 | if (Math.Abs(curcontact.RelativeSpeed) > 0.2) | 5704 | if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2) |
4695 | { | 5705 | { |
4696 | soundinfo = new CollisionForSoundInfo(); | 5706 | soundinfo = new CollisionForSoundInfo(); |
4697 | soundinfo.colliderID = id; | 5707 | soundinfo.colliderID = id; |
@@ -4770,5 +5780,282 @@ namespace OpenSim.Region.Framework.Scenes | |||
4770 | m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); | 5780 | m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); |
4771 | 5781 | ||
4772 | } | 5782 | } |
5783 | |||
5784 | private void parcelGodCheck(UUID currentParcelID, bool isGod) | ||
5785 | { | ||
5786 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
5787 | |||
5788 | foreach (ScenePresence p in allpresences) | ||
5789 | { | ||
5790 | if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5791 | continue; | ||
5792 | |||
5793 | if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID) | ||
5794 | { | ||
5795 | if (isGod) | ||
5796 | p.SendViewTo(this); | ||
5797 | else | ||
5798 | p.SendKillTo(this); | ||
5799 | } | ||
5800 | } | ||
5801 | } | ||
5802 | |||
5803 | private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID, | ||
5804 | bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check) | ||
5805 | { | ||
5806 | List<ScenePresence> killsToSendto = new List<ScenePresence>(); | ||
5807 | List<ScenePresence> killsToSendme = new List<ScenePresence>(); | ||
5808 | List<ScenePresence> viewsToSendto = new List<ScenePresence>(); | ||
5809 | List<ScenePresence> viewsToSendme = new List<ScenePresence>(); | ||
5810 | List<ScenePresence> allpresences = null; | ||
5811 | |||
5812 | if (IsInTransit || IsChildAgent) | ||
5813 | return; | ||
5814 | |||
5815 | if (check) | ||
5816 | { | ||
5817 | // check is relative to current parcel only | ||
5818 | if (currentParcelUUID == null || oldhide == currentParcelHide) | ||
5819 | return; | ||
5820 | |||
5821 | allpresences = m_scene.GetScenePresences(); | ||
5822 | |||
5823 | if (oldhide) | ||
5824 | { // where private | ||
5825 | foreach (ScenePresence p in allpresences) | ||
5826 | { | ||
5827 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5828 | continue; | ||
5829 | |||
5830 | // those on not on parcel see me | ||
5831 | if (currentParcelID != p.currentParcelUUID) | ||
5832 | { | ||
5833 | viewsToSendto.Add(p); // they see me | ||
5834 | } | ||
5835 | } | ||
5836 | } // where private end | ||
5837 | |||
5838 | else | ||
5839 | { // where public | ||
5840 | foreach (ScenePresence p in allpresences) | ||
5841 | { | ||
5842 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5843 | continue; | ||
5844 | |||
5845 | // those not on parcel dont see me | ||
5846 | if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200) | ||
5847 | { | ||
5848 | killsToSendto.Add(p); // they dont see me | ||
5849 | } | ||
5850 | } | ||
5851 | } // where public end | ||
5852 | |||
5853 | allpresences.Clear(); | ||
5854 | } | ||
5855 | else | ||
5856 | { | ||
5857 | if (currentParcelHide) | ||
5858 | { | ||
5859 | // now on a private parcel | ||
5860 | allpresences = m_scene.GetScenePresences(); | ||
5861 | |||
5862 | if (previusParcelHide && previusParcelID != UUID.Zero) | ||
5863 | { | ||
5864 | foreach (ScenePresence p in allpresences) | ||
5865 | { | ||
5866 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5867 | continue; | ||
5868 | |||
5869 | // only those on previus parcel need receive kills | ||
5870 | if (previusParcelID == p.currentParcelUUID) | ||
5871 | { | ||
5872 | if(p.GodLevel < 200) | ||
5873 | killsToSendto.Add(p); // they dont see me | ||
5874 | if(GodLevel < 200) | ||
5875 | killsToSendme.Add(p); // i dont see them | ||
5876 | } | ||
5877 | // only those on new parcel need see | ||
5878 | if (currentParcelID == p.currentParcelUUID) | ||
5879 | { | ||
5880 | viewsToSendto.Add(p); // they see me | ||
5881 | viewsToSendme.Add(p); // i see them | ||
5882 | } | ||
5883 | } | ||
5884 | } | ||
5885 | else | ||
5886 | { | ||
5887 | //was on a public area | ||
5888 | allpresences = m_scene.GetScenePresences(); | ||
5889 | |||
5890 | foreach (ScenePresence p in allpresences) | ||
5891 | { | ||
5892 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5893 | continue; | ||
5894 | |||
5895 | // those not on new parcel dont see me | ||
5896 | if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200) | ||
5897 | { | ||
5898 | killsToSendto.Add(p); // they dont see me | ||
5899 | } | ||
5900 | else | ||
5901 | { | ||
5902 | viewsToSendme.Add(p); // i see those on it | ||
5903 | } | ||
5904 | } | ||
5905 | } | ||
5906 | allpresences.Clear(); | ||
5907 | } // now on a private parcel end | ||
5908 | |||
5909 | else | ||
5910 | { | ||
5911 | // now on public parcel | ||
5912 | if (previusParcelHide && previusParcelID != UUID.Zero) | ||
5913 | { | ||
5914 | // was on private area | ||
5915 | allpresences = m_scene.GetScenePresences(); | ||
5916 | |||
5917 | foreach (ScenePresence p in allpresences) | ||
5918 | { | ||
5919 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5920 | continue; | ||
5921 | // only those old parcel need kills | ||
5922 | if (previusParcelID == p.currentParcelUUID && GodLevel < 200) | ||
5923 | { | ||
5924 | killsToSendme.Add(p); // i dont see them | ||
5925 | } | ||
5926 | else | ||
5927 | { | ||
5928 | viewsToSendto.Add(p); // they see me | ||
5929 | } | ||
5930 | } | ||
5931 | } | ||
5932 | else | ||
5933 | return; // was on a public area also | ||
5934 | } // now on public parcel end | ||
5935 | } | ||
5936 | |||
5937 | // send the things | ||
5938 | |||
5939 | if (killsToSendto.Count > 0) | ||
5940 | { | ||
5941 | foreach (ScenePresence p in killsToSendto) | ||
5942 | { | ||
5943 | m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); | ||
5944 | SendKillTo(p); | ||
5945 | } | ||
5946 | } | ||
5947 | |||
5948 | if (killsToSendme.Count > 0) | ||
5949 | { | ||
5950 | foreach (ScenePresence p in killsToSendme) | ||
5951 | { | ||
5952 | m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname); | ||
5953 | p.SendKillTo(this); | ||
5954 | } | ||
5955 | } | ||
5956 | |||
5957 | if (viewsToSendto.Count > 0) | ||
5958 | { | ||
5959 | foreach (ScenePresence p in viewsToSendto) | ||
5960 | { | ||
5961 | SendViewTo(p); | ||
5962 | } | ||
5963 | } | ||
5964 | |||
5965 | if (viewsToSendme.Count > 0 ) | ||
5966 | { | ||
5967 | foreach (ScenePresence p in viewsToSendme) | ||
5968 | { | ||
5969 | if (p.IsChildAgent) | ||
5970 | continue; | ||
5971 | // m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname); | ||
5972 | p.SendViewTo(this); | ||
5973 | } | ||
5974 | } | ||
5975 | } | ||
5976 | |||
5977 | public void HasMovedAway(bool nearRegion) | ||
5978 | { | ||
5979 | |||
5980 | if (nearRegion) | ||
5981 | { | ||
5982 | if (Scene.AttachmentsModule != null) | ||
5983 | Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true); | ||
5984 | |||
5985 | if (!ParcelHideThisAvatar || GodLevel >= 200) | ||
5986 | return; | ||
5987 | |||
5988 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
5989 | foreach (ScenePresence p in allpresences) | ||
5990 | { | ||
5991 | if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive) | ||
5992 | continue; | ||
5993 | |||
5994 | if (p.currentParcelUUID == m_currentParcelUUID) | ||
5995 | { | ||
5996 | p.SendKillTo(this); | ||
5997 | } | ||
5998 | } | ||
5999 | } | ||
6000 | else | ||
6001 | { | ||
6002 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | ||
6003 | foreach (ScenePresence p in allpresences) | ||
6004 | { | ||
6005 | if (p == this) | ||
6006 | continue; | ||
6007 | SendKillTo(p); | ||
6008 | if (!p.IsChildAgent) | ||
6009 | p.SendKillTo(this); | ||
6010 | } | ||
6011 | |||
6012 | if (Scene.AttachmentsModule != null) | ||
6013 | Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true); | ||
6014 | } | ||
6015 | } | ||
6016 | |||
6017 | |||
6018 | // kill with attachs root kills | ||
6019 | public void SendKillTo(ScenePresence p) | ||
6020 | { | ||
6021 | List<uint> ids = new List<uint>(m_attachments.Count + 1); | ||
6022 | foreach (SceneObjectGroup sog in m_attachments) | ||
6023 | { | ||
6024 | ids.Add(sog.RootPart.LocalId); | ||
6025 | } | ||
6026 | |||
6027 | ids.Add(LocalId); | ||
6028 | p.ControllingClient.SendKillObject(ids); | ||
6029 | } | ||
6030 | |||
6031 | /* | ||
6032 | // kill with hack | ||
6033 | public void SendKillTo(ScenePresence p) | ||
6034 | { | ||
6035 | foreach (SceneObjectGroup sog in m_attachments) | ||
6036 | p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1); | ||
6037 | p.ControllingClient.SendKillObject(new List<uint> { LocalId }); | ||
6038 | } | ||
6039 | */ | ||
6040 | public void SendViewTo(ScenePresence p) | ||
6041 | { | ||
6042 | SendAvatarDataToAgentNF(p); | ||
6043 | SendAppearanceToAgent(p); | ||
6044 | if (Animator != null) | ||
6045 | Animator.SendAnimPackToClient(p.ControllingClient); | ||
6046 | SendAttachmentsToAgentNF(p); | ||
6047 | } | ||
6048 | |||
6049 | public void SetAnimationOverride(string animState, UUID animID) | ||
6050 | { | ||
6051 | Overrides.SetOverride(animState, animID); | ||
6052 | // Animator.SendAnimPack(); | ||
6053 | Animator.ForceUpdateMovementAnimations(); | ||
6054 | } | ||
6055 | |||
6056 | public UUID GetAnimationOverride(string animState) | ||
6057 | { | ||
6058 | return Overrides.GetOverriddenAnimation(animState); | ||
6059 | } | ||
4773 | } | 6060 | } |
4774 | } | 6061 | } |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs new file mode 100644 index 0000000..cae7fe5 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
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..40e88f1 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -271,7 +271,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
271 | // Script state may, or may not, exist. Not having any, is NOT | 271 | // Script state may, or may not, exist. Not having any, is NOT |
272 | // ever a problem. | 272 | // ever a problem. |
273 | sceneObject.LoadScriptState(doc); | 273 | sceneObject.LoadScriptState(doc); |
274 | 274 | ||
275 | return sceneObject; | 275 | return sceneObject; |
276 | } | 276 | } |
277 | catch (Exception e) | 277 | catch (Exception e) |
@@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
365 | m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); | 365 | m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); |
366 | m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); | 366 | m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); |
367 | m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); | 367 | m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); |
368 | m_SOPXmlProcessors.Add("AttachedPos", ProcessAttachedPos); | ||
368 | m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); | 369 | m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); |
369 | m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); | 370 | m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); |
370 | m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); | 371 | m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); |
@@ -390,6 +391,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
390 | m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset); | 391 | m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset); |
391 | m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset); | 392 | m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset); |
392 | 393 | ||
394 | m_SOPXmlProcessors.Add("SoundID", ProcessSoundID); | ||
395 | m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain); | ||
396 | m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags); | ||
397 | m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius); | ||
398 | m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing); | ||
399 | |||
393 | #endregion | 400 | #endregion |
394 | 401 | ||
395 | #region TaskInventoryXmlProcessors initialization | 402 | #region TaskInventoryXmlProcessors initialization |
@@ -443,6 +450,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
443 | m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); | 450 | m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); |
444 | m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); | 451 | m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); |
445 | m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); | 452 | m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); |
453 | m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach); | ||
446 | m_ShapeXmlProcessors.Add("State", ProcessShpState); | 454 | m_ShapeXmlProcessors.Add("State", ProcessShpState); |
447 | m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); | 455 | m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); |
448 | m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); | 456 | m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); |
@@ -652,6 +660,30 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
652 | obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset")); | 660 | obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset")); |
653 | } | 661 | } |
654 | 662 | ||
663 | private static void ProcessSoundID(SceneObjectPart obj, XmlTextReader reader) | ||
664 | { | ||
665 | obj.Sound = Util.ReadUUID(reader, "SoundID"); | ||
666 | } | ||
667 | |||
668 | private static void ProcessSoundGain(SceneObjectPart obj, XmlTextReader reader) | ||
669 | { | ||
670 | obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty); | ||
671 | } | ||
672 | |||
673 | private static void ProcessSoundFlags(SceneObjectPart obj, XmlTextReader reader) | ||
674 | { | ||
675 | obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty); | ||
676 | } | ||
677 | |||
678 | private static void ProcessSoundRadius(SceneObjectPart obj, XmlTextReader reader) | ||
679 | { | ||
680 | obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty); | ||
681 | } | ||
682 | |||
683 | private static void ProcessSoundQueueing(SceneObjectPart obj, XmlTextReader reader) | ||
684 | { | ||
685 | obj.SoundQueueing = Util.ReadBoolean(reader); | ||
686 | } | ||
655 | private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader) | 687 | private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader) |
656 | { | 688 | { |
657 | SOPVehicle vehicle = SOPVehicle.FromXml2(reader); | 689 | SOPVehicle vehicle = SOPVehicle.FromXml2(reader); |
@@ -798,6 +830,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
798 | obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); | 830 | obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); |
799 | } | 831 | } |
800 | 832 | ||
833 | private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader) | ||
834 | { | ||
835 | obj.AttachedPos = Util.ReadVector(reader, "AttachedPos"); | ||
836 | } | ||
837 | |||
801 | private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) | 838 | private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) |
802 | { | 839 | { |
803 | obj.DynAttrs.ReadXml(reader); | 840 | obj.DynAttrs.ReadXml(reader); |
@@ -1099,6 +1136,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1099 | shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); | 1136 | shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); |
1100 | } | 1137 | } |
1101 | 1138 | ||
1139 | private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader) | ||
1140 | { | ||
1141 | shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty); | ||
1142 | } | ||
1143 | |||
1102 | private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) | 1144 | private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) |
1103 | { | 1145 | { |
1104 | shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); | 1146 | shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); |
@@ -1253,6 +1295,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1253 | writer.WriteBase64(data, 0, data.Length); | 1295 | writer.WriteBase64(data, 0, data.Length); |
1254 | writer.WriteEndElement(); | 1296 | writer.WriteEndElement(); |
1255 | } | 1297 | } |
1298 | |||
1256 | 1299 | ||
1257 | writer.WriteEndElement(); | 1300 | writer.WriteEndElement(); |
1258 | } | 1301 | } |
@@ -1267,7 +1310,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1267 | 1310 | ||
1268 | WriteUUID(writer, "CreatorID", sop.CreatorID, options); | 1311 | WriteUUID(writer, "CreatorID", sop.CreatorID, options); |
1269 | 1312 | ||
1270 | if (sop.CreatorData != null && sop.CreatorData != string.Empty) | 1313 | if (!string.IsNullOrEmpty(sop.CreatorData)) |
1271 | writer.WriteElementString("CreatorData", sop.CreatorData); | 1314 | writer.WriteElementString("CreatorData", sop.CreatorData); |
1272 | else if (options.ContainsKey("home")) | 1315 | else if (options.ContainsKey("home")) |
1273 | { | 1316 | { |
@@ -1345,8 +1388,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1345 | writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); | 1388 | writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); |
1346 | if (sop.MediaUrl != null) | 1389 | if (sop.MediaUrl != null) |
1347 | writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); | 1390 | writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); |
1391 | WriteVector(writer, "AttachedPos", sop.AttachedPos); | ||
1348 | 1392 | ||
1349 | if (sop.DynAttrs.Count > 0) | 1393 | if (sop.DynAttrs.CountNamespaces > 0) |
1350 | { | 1394 | { |
1351 | writer.WriteStartElement("DynAttrs"); | 1395 | writer.WriteStartElement("DynAttrs"); |
1352 | sop.DynAttrs.WriteXml(writer); | 1396 | sop.DynAttrs.WriteXml(writer); |
@@ -1371,8 +1415,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1371 | if (sop.VehicleParams != null) | 1415 | if (sop.VehicleParams != null) |
1372 | sop.VehicleParams.ToXml2(writer); | 1416 | sop.VehicleParams.ToXml2(writer); |
1373 | 1417 | ||
1374 | if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) | 1418 | writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); |
1375 | writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); | ||
1376 | if (sop.Density != 1000.0f) | 1419 | if (sop.Density != 1000.0f) |
1377 | writer.WriteElementString("Density", sop.Density.ToString().ToLower()); | 1420 | writer.WriteElementString("Density", sop.Density.ToString().ToLower()); |
1378 | if (sop.Friction != 0.6f) | 1421 | if (sop.Friction != 0.6f) |
@@ -1384,6 +1427,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1384 | WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); | 1427 | WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); |
1385 | WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); | 1428 | WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); |
1386 | 1429 | ||
1430 | // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim | ||
1431 | { | ||
1432 | WriteUUID(writer, "SoundID", sop.Sound, options); | ||
1433 | writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower()); | ||
1434 | writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower()); | ||
1435 | writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower()); | ||
1436 | } | ||
1437 | writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower()); | ||
1438 | |||
1387 | writer.WriteEndElement(); | 1439 | writer.WriteEndElement(); |
1388 | } | 1440 | } |
1389 | 1441 | ||
@@ -1451,7 +1503,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1451 | 1503 | ||
1452 | WriteUUID(writer, "CreatorID", item.CreatorID, options); | 1504 | WriteUUID(writer, "CreatorID", item.CreatorID, options); |
1453 | 1505 | ||
1454 | if (item.CreatorData != null && item.CreatorData != string.Empty) | 1506 | if (!string.IsNullOrEmpty(item.CreatorData)) |
1455 | writer.WriteElementString("CreatorData", item.CreatorData); | 1507 | writer.WriteElementString("CreatorData", item.CreatorData); |
1456 | else if (options.ContainsKey("home")) | 1508 | else if (options.ContainsKey("home")) |
1457 | { | 1509 | { |
@@ -1539,6 +1591,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1539 | writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); | 1591 | writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); |
1540 | writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); | 1592 | writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); |
1541 | writer.WriteElementString("State", shp.State.ToString()); | 1593 | writer.WriteElementString("State", shp.State.ToString()); |
1594 | writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString()); | ||
1542 | 1595 | ||
1543 | WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); | 1596 | WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); |
1544 | WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); | 1597 | WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 5398ab9..bf32251 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -290,6 +290,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
290 | 290 | ||
291 | private void statsHeartBeat(object sender, EventArgs e) | 291 | private void statsHeartBeat(object sender, EventArgs e) |
292 | { | 292 | { |
293 | if (!m_scene.Active) | ||
294 | return; | ||
295 | |||
293 | SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; | 296 | SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; |
294 | SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); | 297 | SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); |
295 | 298 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs index 9557cd0..95b30d5 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs | |||
@@ -33,7 +33,9 @@ using NUnit.Framework; | |||
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 |