aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionConsole.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRestartModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISearchModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs373
-rw-r--r--OpenSim/Region/Framework/Scenes/CollisionSounds.cs304
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs280
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs72
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs792
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs440
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs156
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs6
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs1161
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs11
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SceneGraph.cs536
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs246
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1803
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1648
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs813
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2780
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs129
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SimStatsReporter.cs467
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs1
55 files changed, 9115 insertions, 3770 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
index 0cc8fb6..e0aad2b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, 36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
37 InventoryItemBase item); 37 InventoryItemBase item);
38 38
39 void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, 39 bool HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
40 uint callbackID, string description, string name, sbyte invType, 40 uint callbackID, string description, string name, sbyte invType,
41 sbyte type, byte wearableType, uint nextOwnerMask); 41 sbyte type, byte wearableType, uint nextOwnerMask);
42 42
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index d9901bd..3c1247f 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -89,7 +90,7 @@ namespace OpenSim.Region.Framework.Interfaces
89 /// <param name="addToInventory">If true then add object to user inventory</param> 90 /// <param name="addToInventory">If true then add object to user inventory</param>
90 /// <param name="append">Append to attachment point rather than replace.</param> 91 /// <param name="append">Append to attachment point rather than replace.</param>
91 /// <returns>true if the object was successfully attached, false otherwise</returns> 92 /// <returns>true if the object was successfully attached, false otherwise</returns>
92 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool addToInventory, bool append); 93 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool addToInventory, bool append);
93 94
94 /// <summary> 95 /// <summary>
95 /// Rez an attachment from user inventory and change inventory status to match. 96 /// Rez an attachment from user inventory and change inventory status to match.
@@ -98,7 +99,11 @@ namespace OpenSim.Region.Framework.Interfaces
98 /// <param name="itemID"></param> 99 /// <param name="itemID"></param>
99 /// <param name="AttachmentPt"></param> 100 /// <param name="AttachmentPt"></param>
100 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 101 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
101 SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 102 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
103
104 // Same as above, but also load script states from a separate doc
105 ISceneEntity RezSingleAttachmentFromInventory(
106 IScenePresence presence, UUID itemID, uint AttachmentPt, XmlDocument doc);
102 107
103 /// <summary> 108 /// <summary>
104 /// Rez multiple attachments from a user's inventory 109 /// Rez multiple attachments from a user's inventory
@@ -130,7 +135,6 @@ namespace OpenSim.Region.Framework.Interfaces
130 /// <param name="grp">The attachment to detach.</param> 135 /// <param name="grp">The attachment to detach.</param>
131 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp); 136 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
132 137
133 /// <summary>
134 /// Update the position of an attachment. 138 /// Update the position of an attachment.
135 /// </summary> 139 /// </summary>
136 /// <param name="sog"></param> 140 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index b536a49..4d8409be 100644
--- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -35,6 +35,9 @@ namespace OpenSim.Services.Interfaces
35 public interface IBakedTextureModule 35 public interface IBakedTextureModule
36 { 36 {
37 WearableCacheItem[] Get(UUID id); 37 WearableCacheItem[] Get(UUID id);
38 void Store(UUID id, WearableCacheItem[] data); 38
39 void Store(UUID id);
40 void Store(UUID id, WearableCacheItem[] WearableCache);
41 void UpdateMeshAvatar(UUID id);
39 } 42 }
40} 43}
diff --git a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
index 522c82d..30d404e 100644
--- a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
@@ -40,19 +40,19 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// </summary> 40 /// </summary>
41 /// <param name="agentId"></param> 41 /// <param name="agentId"></param>
42 /// <param name="capsObjectPath"></param> 42 /// <param name="capsObjectPath"></param>
43 void CreateCaps(UUID agentId); 43 void CreateCaps(UUID agentId, uint circuitCode);
44 44
45 /// <summary> 45 /// <summary>
46 /// Remove the caps handler for a given agent. 46 /// Remove the caps handler for a given agent.
47 /// </summary> 47 /// </summary>
48 /// <param name="agentId"></param> 48 /// <param name="agentId"></param>
49 void RemoveCaps(UUID agentId); 49 void RemoveCaps(UUID agentId, uint circuitCode);
50 50
51 /// <summary> 51 /// <summary>
52 /// Will return null if the agent doesn't have a caps handler registered 52 /// Will return null if the agent doesn't have a caps handler registered
53 /// </summary> 53 /// </summary>
54 /// <param name="agentId"></param> 54 /// <param name="agentId"></param>
55 Caps GetCapsForUser(UUID agentId); 55 Caps GetCapsForUser(uint circuitCode);
56 56
57 void SetAgentCapsSeeds(AgentCircuitData agent); 57 void SetAgentCapsSeeds(AgentCircuitData agent);
58 58
@@ -65,5 +65,7 @@ namespace OpenSim.Region.Framework.Interfaces
65 void DropChildSeed(UUID agentID, ulong handle); 65 void DropChildSeed(UUID agentID, ulong handle);
66 66
67 string GetCapsPath(UUID agentId); 67 string GetCapsPath(UUID agentId);
68
69 void ActivateCaps(uint circuitCode);
68 } 70 }
69} 71}
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
index 08b71e4..4d000b6 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
@@ -43,6 +43,7 @@ namespace OpenSim.Region.Framework.Interfaces
43 public enum UserMode : int 43 public enum UserMode : int
44 { 44 {
45 Normal = 0, 45 Normal = 0,
46 RegionManager = 2,
46 God = 3 47 God = 3
47 } 48 }
48 49
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 9ffda51..b85fd8b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -133,6 +133,8 @@ namespace OpenSim.Region.Framework.Interfaces
133 /// </returns> 133 /// </returns>
134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
135 135
136 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
137
136 /// <summary> 138 /// <summary>
137 /// Stop and remove a script which is in this prim's inventory from the scene. 139 /// Stop and remove a script which is in this prim's inventory from the scene.
138 /// </summary> 140 /// </summary>
@@ -244,7 +246,7 @@ namespace OpenSim.Region.Framework.Interfaces
244 /// <param name="objlist">The scene objects</param> 246 /// <param name="objlist">The scene objects</param>
245 /// <param name="veclist">Relative offsets for each object</param> 247 /// <param name="veclist">Relative offsets for each object</param>
246 /// <returns>true = success, false = the scene object asset couldn't be found</returns> 248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
247 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist); 249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
@@ -318,5 +320,6 @@ namespace OpenSim.Region.Framework.Interfaces
318 /// A <see cref="Dictionary`2"/> 320 /// A <see cref="Dictionary`2"/>
319 /// </returns> 321 /// </returns>
320 Dictionary<UUID, string> GetScriptStates(); 322 Dictionary<UUID, string> GetScriptStates();
323 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
321 } 324 }
322} 325}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1ebef90..80f8244 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Scenes;
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); 38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
39 public delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying);
39 40
40 public interface IEntityTransferModule 41 public interface IEntityTransferModule
41 { 42 {
@@ -92,10 +93,11 @@ namespace OpenSim.Region.Framework.Interfaces
92 93
93 void EnableChildAgent(ScenePresence agent, GridRegion region); 94 void EnableChildAgent(ScenePresence agent, GridRegion region);
94 95
95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, 96 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
96 out Vector3 newpos, out string reason); 97 GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos);
97 98 bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason);
98 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);
99 101
100 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);
101 103
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 124504c..efc9ddc 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -58,7 +58,6 @@ namespace OpenSim.Region.Framework.Interfaces
58 public interface IHttpRequestModule 58 public interface IHttpRequestModule
59 { 59 {
60 UUID MakeHttpRequest(string url, string parameters, string body); 60 UUID MakeHttpRequest(string url, string parameters, string body);
61
62 /// <summary> 61 /// <summary>
63 /// Starts the http request. 62 /// Starts the http request.
64 /// </summary> 63 /// </summary>
@@ -85,8 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
85 /// Stop and remove all http requests for the given script. 84 /// Stop and remove all http requests for the given script.
86 /// </summary> 85 /// </summary>
87 /// <param name='id'></param> 86 /// <param name='id'></param>
88 void StopHttpRequestsForScript(UUID id); 87 void StopHttpRequest(uint m_localID, UUID m_itemID);
89
90 IServiceRequest GetNextCompletedRequest(); 88 IServiceRequest GetNextCompletedRequest();
91 void RemoveCompletedRequest(UUID id); 89 void RemoveCompletedRequest(UUID id);
92 } 90 }
diff --git a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
index 6a7d4a1..5151567 100644
--- a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
@@ -25,13 +25,18 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System.Drawing; 28using OpenMetaverse;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using System.Drawing;
30 31
31namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
32{ 33{
33 public interface IMapImageUploadModule 34 public interface IMapImageUploadModule
34 { 35 {
36 /// <summary>
37 /// Upload a new maptile
38 /// </summary>
39 void UploadMapTile(IScene scene);
35 void UploadMapTile(IScene scene, Bitmap mapTile); 40 void UploadMapTile(IScene scene, Bitmap mapTile);
36 } 41 }
37} \ No newline at end of file 42}
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
index 4d261d6..5d5ce34 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
@@ -30,8 +30,12 @@ using OpenSim.Framework;
30 30
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public delegate void ConsoleMessage(UUID toAgentID, string message);
34
33 public interface IRegionConsole 35 public interface IRegionConsole
34 { 36 {
37 event ConsoleMessage OnConsoleMessage;
38
35 bool RunCommand(string command, UUID invokerID); 39 bool RunCommand(string command, UUID invokerID);
36 void SendConsoleOutput(UUID agentID, string message); 40 void SendConsoleOutput(UUID agentID, string message);
37 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn); 41 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn);
diff --git a/OpenSim/Region/Framework/Interfaces/IRestartModule.cs b/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
index c68550f..9b25beb 100644
--- a/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
@@ -35,5 +35,6 @@ namespace OpenSim.Region.Framework.Interfaces
35 TimeSpan TimeUntilRestart { get; } 35 TimeSpan TimeUntilRestart { get; }
36 void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice); 36 void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice);
37 void AbortRestart(string message); 37 void AbortRestart(string message);
38 void DelayRestart(int seconds, string message);
38 } 39 }
39} 40}
diff --git a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
index 64bf72c..d56d188 100644
--- a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
@@ -31,6 +31,6 @@ namespace OpenSim.Framework
31{ 31{
32 public interface ISearchModule 32 public interface ISearchModule
33 { 33 {
34 34 void Refresh();
35 } 35 }
36} 36}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 8948f04..13358cb 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -125,6 +125,8 @@ namespace OpenSim.Region.Framework.Interfaces
125 /// <param name="regionUUID">the region UUID</param> 125 /// <param name="regionUUID">the region UUID</param>
126 void RemoveRegionEnvironmentSettings(UUID regionUUID); 126 void RemoveRegionEnvironmentSettings(UUID regionUUID);
127 127
128 UUID[] GetObjectIDs(UUID regionID);
129
128 void SaveExtra(UUID regionID, string name, string value); 130 void SaveExtra(UUID regionID, string name, string value);
129 131
130 void RemoveExtra(UUID regionID, string name); 132 void RemoveExtra(UUID regionID, string name);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 917b5d1..e09f775 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -115,6 +115,7 @@ namespace OpenSim.Region.Framework.Interfaces
115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID); 115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID);
116 void StoreRegionWindlightSettings(RegionLightShareData wl); 116 void StoreRegionWindlightSettings(RegionLightShareData wl);
117 void RemoveRegionWindlightSettings(UUID regionID); 117 void RemoveRegionWindlightSettings(UUID regionID);
118 UUID[] GetObjectIDs(UUID regionID);
118 119
119 /// <summary> 120 /// <summary>
120 /// Load Environment settings from region storage 121 /// Load Environment settings from region storage
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 8372ddd..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.
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index 28f797a..472e5a5d 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -28,6 +28,8 @@ using System.IO;
28 28
29using OpenSim.Framework; 29using OpenSim.Framework;
30 30
31using System.IO;
32using OpenSim.Framework;
31using OpenMetaverse; 33using OpenMetaverse;
32 34
33namespace OpenSim.Region.Framework.Interfaces 35namespace OpenSim.Region.Framework.Interfaces
@@ -43,13 +45,13 @@ namespace OpenSim.Region.Framework.Interfaces
43 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight) 45 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight)
44 /// </summary> 46 /// </summary>
45 void TaintTerrain(); 47 void TaintTerrain();
46 48
47 /// <summary> 49 /// <summary>
48 /// When a client initially connects, all the terrain must be pushed to the viewer. 50 /// When a client initially connects, all the terrain must be pushed to the viewer.
49 /// This call causes all the terrain patches to be sent to the client. 51 /// This call causes all the terrain patches to be sent to the client.
50 /// </summary> 52 /// </summary>
51 void PushTerrain(IClientAPI pClient); 53 void PushTerrain(IClientAPI pClient);
52 54
53 /// <summary> 55 /// <summary>
54 /// Load a terrain from a stream. 56 /// Load a terrain from a stream.
55 /// </summary> 57 /// </summary>
@@ -58,8 +60,9 @@ namespace OpenSim.Region.Framework.Interfaces
58 /// </param> 60 /// </param>
59 /// <param name="stream"></param> 61 /// <param name="stream"></param>
60 void LoadFromStream(string filename, Stream stream); 62 void LoadFromStream(string filename, Stream stream);
61 void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream);
62 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); 63 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
64 void LoadFromStream(string filename, Vector3 displacement,
65 float radianRotation, Vector2 rotationDisplacement, Stream stream);
63 /// <summary> 66 /// <summary>
64 /// Save a terrain to a stream. 67 /// Save a terrain to a stream.
65 /// </summary> 68 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index d76a0d7..20e0199 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Interfaces
127 /// <param name='msg'> 127 /// <param name='msg'>
128 /// Message. 128 /// Message.
129 /// </param> 129 /// </param>
130 void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg); 130 bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg, out string error);
131 131
132 /// <summary> 132 /// <summary>
133 /// Are there any listen events ready to be dispatched? 133 /// Are there any listen events ready to be dispatched?
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
index 9c781e1..e9cf4ad 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
@@ -37,6 +37,6 @@ namespace OpenSim.Region.Framework.Interfaces
37 /// </summary> 37 /// </summary>
38 void GenerateMaptile(); 38 void GenerateMaptile();
39 List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag); 39 List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag);
40 MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag); 40 void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag);
41 } 41 }
42} 42}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
new file mode 100644
index 0000000..31fdb2c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
@@ -0,0 +1,101 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Xml;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Framework.Client;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes.Animation;
42using OpenSim.Region.Framework.Scenes.Types;
43using OpenSim.Region.Physics.Manager;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenSim.Services.Interfaces;
46using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
47
48namespace OpenSim.Region.Framework.Scenes
49{
50 public class MovementAnimationOverrides
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private Dictionary<string, UUID> m_overrides = new Dictionary<string, UUID>();
56 public void SetOverride(string state, UUID animID)
57 {
58 if (animID == UUID.Zero)
59 {
60 if (state == "ALL")
61 m_overrides.Clear();
62 else
63 m_overrides.Remove(state);
64 return;
65 }
66
67 m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
68
69 lock (m_overrides)
70 m_overrides[state] = animID;
71 }
72
73 public UUID GetOverriddenAnimation(string state)
74 {
75 lock (m_overrides)
76 {
77 if (m_overrides.ContainsKey(state))
78 return m_overrides[state];
79 }
80
81 return UUID.Zero;
82 }
83
84 public Dictionary<string, UUID> CloneAOPairs()
85 {
86 lock (m_overrides)
87 {
88 return new Dictionary<string, UUID>(m_overrides);
89 }
90 }
91
92 public void CopyAOPairsFrom(Dictionary<string, UUID> src)
93 {
94 lock (m_overrides)
95 {
96 m_overrides.Clear();
97 m_overrides = new Dictionary<string, UUID>(src);
98 }
99 }
100 }
101}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 6d51029..e80a33b 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,39 +56,42 @@ 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;
81 CurrentMovementAnimation = "CROUCH"; 83 CurrentMovementAnimation = "CROUCH";
82 } 84 }
83 85
84 public void AddAnimation(UUID animID, UUID objectID) 86 public void AddAnimation(UUID animID, UUID objectID)
85 { 87 {
86 if (m_scenePresence.IsChildAgent) 88 if (m_scenePresence.IsChildAgent)
87 return; 89 return;
88 90
91 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
89 if (m_scenePresence.Scene.DebugAnimations) 92 if (m_scenePresence.Scene.DebugAnimations)
90 m_log.DebugFormat( 93 m_log.DebugFormat(
91 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", 94 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}",
92 GetAnimName(animID), animID, m_scenePresence.Name); 95 GetAnimName(animID), animID, m_scenePresence.Name);
93 96
94 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 97 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
@@ -110,7 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
110 if (animID == UUID.Zero) 113 if (animID == UUID.Zero)
111 return; 114 return;
112 115
113// 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);
114 117
115 AddAnimation(animID, objectID); 118 AddAnimation(animID, objectID);
116 } 119 }
@@ -130,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
130 133
131 if (m_scenePresence.Scene.DebugAnimations) 134 if (m_scenePresence.Scene.DebugAnimations)
132 m_log.DebugFormat( 135 m_log.DebugFormat(
133 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}", 136 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}",
134 GetAnimName(animID), animID, m_scenePresence.Name); 137 GetAnimName(animID), animID, m_scenePresence.Name);
135 138
136 if (m_animations.Remove(animID, allowNoDefault)) 139 if (m_animations.Remove(animID, allowNoDefault))
@@ -140,6 +143,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
140 } 143 }
141 } 144 }
142 145
146 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
147 {
148 if (m_scenePresence.IsChildAgent)
149 return;
150
151 if (animID != UUID.Zero)
152 {
153 if (addRemove)
154 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
155 else
156 m_animations.Remove(animID, false);
157 }
158 if (sendPack)
159 SendAnimPack();
160 }
161
143 // Called from scripts 162 // Called from scripts
144 public void RemoveAnimation(string name) 163 public void RemoveAnimation(string name)
145 { 164 {
@@ -164,12 +183,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
164 183
165 m_animations.Clear(); 184 m_animations.Clear();
166 } 185 }
167 186
187
188 UUID aoSitGndAnim = UUID.Zero;
189
168 /// <summary> 190 /// <summary>
169 /// The movement animation is reserved for "main" animations 191 /// The movement animation is reserved for "main" animations
170 /// that are mutually exclusive, e.g. flying and sitting. 192 /// that are mutually exclusive, e.g. flying and sitting.
171 /// </summary> 193 /// </summary>
172 /// <returns>'true' if the animation was updated</returns> 194 /// <returns>'true' if the animation was updated</returns>
195 ///
196
197
198
173 public bool TrySetMovementAnimation(string anim) 199 public bool TrySetMovementAnimation(string anim)
174 { 200 {
175 bool ret = false; 201 bool ret = false;
@@ -179,17 +205,50 @@ namespace OpenSim.Region.Framework.Scenes.Animation
179// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", 205// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}",
180// anim, m_scenePresence.Name); 206// anim, m_scenePresence.Name);
181 207
182 if (m_animations.TrySetDefaultAnimation( 208 if (aoSitGndAnim != UUID.Zero)
183 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
184 { 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 {
185// m_log.DebugFormat( 243// m_log.DebugFormat(
186// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}", 244// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}",
187// anim, m_scenePresence.Name); 245// anim, m_scenePresence.Name);
188 246
189 // 16384 is CHANGED_ANIMATION 247 // 16384 is CHANGED_ANIMATION
190 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 248 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
191 SendAnimPack(); 249 SendAnimPack();
192 ret = true; 250 ret = true;
251 }
193 } 252 }
194 } 253 }
195 else 254 else
@@ -201,78 +260,119 @@ namespace OpenSim.Region.Framework.Scenes.Animation
201 return ret; 260 return ret;
202 } 261 }
203 262
263 public enum motionControlStates : byte
264 {
265 sitted = 0,
266 flying,
267 falling,
268 jumping,
269 landing,
270 onsurface
271 }
272
273 public motionControlStates currentControlState = motionControlStates.onsurface;
274
204 /// <summary> 275 /// <summary>
205 /// This method determines the proper movement related animation 276 /// This method determines the proper movement related animation
206 /// </summary> 277 /// </summary>
207 private string DetermineMovementAnimation() 278 private string DetermineMovementAnimation()
208 { 279 {
209 const float FALL_DELAY = 800f; 280 const int FALL_DELAY = 800;
210 const float PREJUMP_DELAY = 200f; 281 const int PREJUMP_DELAY = 200;
211 const float JUMP_PERIOD = 800f; 282 const int JUMP_PERIOD = 800;
212 #region Inputs 283 #region Inputs
213 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
214 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 299 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
215 PhysicsActor actor = m_scenePresence.PhysicsActor; 300 PhysicsActor actor = m_scenePresence.PhysicsActor;
216 301
217 // Create forward and left vectors from the current avatar rotation 302 const AgentManager.ControlFlags ANYXYMASK = (
218 Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation); 303 AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS |
219 Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix); 304 AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG |
220 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 );
221 308
222 // Check control flags 309 // Check control flags
223 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
224 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);
225 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);
226 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 */
227 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;
228 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;
229 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);
230 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);
231 //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;
232 //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;
233 if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown) 324
325 bool heldOnXY = ((controlFlags & ANYXYMASK) != 0);
326 if (heldOnXY || heldUp || heldDown)
234 { 327 {
235 heldTurnLeft = false; 328 heldTurnLeft = false;
236 heldTurnRight = false; 329 heldTurnRight = false;
237 } 330 }
238 331
239 // Direction in which the avatar is trying to move
240 Vector3 move = Vector3.Zero;
241 if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
242 if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
243 if (heldLeft) { move.X += left.X; move.Y += left.Y; }
244 if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
245 if (heldUp) { move.Z += 1; }
246 if (heldDown) { move.Z -= 1; }
247
248 // Is the avatar trying to move?
249// bool moving = (move != Vector3.Zero);
250 #endregion Inputs 332 #endregion Inputs
251 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
252 #region Flying 346 #region Flying
253 347
254 if (actor != null && actor.Flying) 348 bool isColliding = actor.IsColliding;
349
350 if (actor.Flying)
255 { 351 {
256 m_animTickFall = 0; 352 m_animTickFall = 0;
257 m_animTickJump = 0; 353 m_animTickJump = 0;
258 m_jumping = false; 354 m_jumping = false;
259 Falling = false; 355 Falling = false;
260 m_jumpVelocity = 0f;
261 actor.Selected = false;
262 m_fallHeight = actor.Position.Z; // save latest flying height
263 356
264 if (move.X != 0f || move.Y != 0f) 357 currentControlState = motionControlStates.flying;
358
359 if (heldOnXY)
265 { 360 {
266 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); 361 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
267 } 362 }
268 else if (move.Z > 0f) 363 else if (heldUp)
269 { 364 {
270 return "HOVER_UP"; 365 return "HOVER_UP";
271 } 366 }
272 else if (move.Z < 0f) 367 else if (heldDown)
273 { 368 {
274 if (actor != null && actor.IsColliding) 369 if (isColliding)
370 {
371 actor.Flying = false;
372 currentControlState = motionControlStates.landing;
373 m_animTickLand = Environment.TickCount;
275 return "LAND"; 374 return "LAND";
375 }
276 else 376 else
277 return "HOVER_DOWN"; 377 return "HOVER_DOWN";
278 } 378 }
@@ -281,128 +381,142 @@ namespace OpenSim.Region.Framework.Scenes.Animation
281 return "HOVER"; 381 return "HOVER";
282 } 382 }
283 } 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 }
284 393
285 #endregion Flying 394 #endregion Flying
286 395
287 #region Falling/Floating/Landing 396 #region Falling/Floating/Landing
288 397
289 if ((actor == null || !actor.IsColliding) && !m_jumping) 398 if (!isColliding && currentControlState != motionControlStates.jumping)
290 { 399 {
291 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); 400 float fallVelocity = actor.Velocity.Z;
292 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
293 401
294 if (!m_jumping && (fallVelocity < -3.0f)) 402 if (fallVelocity < -2.5f)
295 Falling = true; 403 Falling = true;
296 404
297 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) 405 if (m_animTickFall == 0 || (fallVelocity >= -0.5f))
298 { 406 {
299 // not falling yet, or going up
300 // reset start of fall time
301 m_animTickFall = Environment.TickCount; 407 m_animTickFall = Environment.TickCount;
302 } 408 }
303 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) 409 else
304 { 410 {
305 // Falling long enough to trigger the animation 411 int fallElapsed = (Environment.TickCount - m_animTickFall);
306 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 }
307 } 419 }
308 420
309 // Check if the user has stopped walking just now 421 // Check if the user has stopped walking just now
310 if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) 422 if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp)
311 return "STAND"; 423 return "STAND";
312 424
313 return CurrentMovementAnimation; 425 return CurrentMovementAnimation;
314 } 426 }
315 427
316 #endregion Falling/Floating/Landing 428 m_animTickFall = 0;
317 429
430 #endregion Falling/Floating/Landing
318 431
319 #region Jumping // section added for jumping... 432 #region Jumping // section added for jumping...
320 433
321 int jumptime; 434 if (isColliding && heldUp && currentControlState != motionControlStates.jumping)
322 jumptime = Environment.TickCount - m_animTickJump;
323
324 if ((move.Z > 0f) && (!m_jumping))
325 { 435 {
326 // Start jumping, prejump 436 // Start jumping, prejump
327 m_animTickFall = 0; 437 currentControlState = motionControlStates.jumping;
328 m_jumping = true; 438 m_jumping = true;
329 Falling = false; 439 Falling = false;
330 actor.Selected = true; // borrowed for jumping flag
331 m_animTickJump = Environment.TickCount; 440 m_animTickJump = Environment.TickCount;
332 m_jumpVelocity = 0.35f;
333 return "PREJUMP"; 441 return "PREJUMP";
334 } 442 }
335 443
336 if (m_jumping) 444 if (currentControlState == motionControlStates.jumping)
337 { 445 {
446 int jumptime = Environment.TickCount - m_animTickJump;
338 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) 447 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
339 { 448 {
340 // end jumping 449 // end jumping
341 m_jumping = false; 450 m_jumping = false;
342 Falling = false; 451 Falling = false;
343 actor.Selected = false; // borrowed for jumping flag 452 actor.Selected = false; // borrowed for jumping flag
344 m_jumpVelocity = 0f; 453 m_animTickLand = Environment.TickCount;
345 m_animTickFall = Environment.TickCount; 454 currentControlState = motionControlStates.landing;
346 return "LAND"; 455 return "LAND";
347 } 456 }
348 else if (jumptime > JUMP_PERIOD) 457 else if (jumptime > JUMP_PERIOD)
349 { 458 {
350 // jump down 459 // jump down
351 m_jumpVelocity = 0f;
352 return "JUMP"; 460 return "JUMP";
353 } 461 }
354 else if (jumptime > PREJUMP_DELAY) 462 else if (jumptime > PREJUMP_DELAY)
355 { 463 {
356 // jump up 464 // jump up
357 m_jumping = true; 465 m_jumping = true;
358 m_jumpVelocity = 10f;
359 return "JUMP"; 466 return "JUMP";
360 } 467 }
468 return CurrentMovementAnimation;
361 } 469 }
362 470
363 #endregion Jumping 471 #endregion Jumping
364 472
365 #region Ground Movement 473 #region Ground Movement
366 474
367 if (CurrentMovementAnimation == "FALLDOWN") 475 if (currentControlState == motionControlStates.falling)
368 { 476 {
369 Falling = false; 477 Falling = false;
370 m_animTickFall = Environment.TickCount; 478 currentControlState = motionControlStates.landing;
479 m_animTickLand = Environment.TickCount;
371 // TODO: SOFT_LAND support 480 // TODO: SOFT_LAND support
372 float fallHeight = m_fallHeight - actor.Position.Z; 481 float fallVsq = m_lastFallVelocity * m_lastFallVelocity;
373 if (fallHeight > 15.0f) 482 if (fallVsq > 300f) // aprox 20*h
374 return "STANDUP"; 483 return "STANDUP";
375 else if (fallHeight > 8.0f) 484 else if (fallVsq > 160f)
376 return "SOFT_LAND"; 485 return "SOFT_LAND";
377 else 486 else
378 return "LAND"; 487 return "LAND";
379 } 488 }
380 else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) 489
490
491 if (currentControlState == motionControlStates.landing)
381 { 492 {
382 int landElapsed = Environment.TickCount - m_animTickFall; 493 Falling = false;
494 int landElapsed = Environment.TickCount - m_animTickLand;
383 int limit = 1000; 495 int limit = 1000;
384 if (CurrentMovementAnimation == "LAND") 496 if (CurrentMovementAnimation == "LAND")
385 limit = 350; 497 limit = 350;
386 // 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
387 499
388 if ((m_animTickFall != 0) && (landElapsed <= limit)) 500 if ((m_animTickLand != 0) && (landElapsed <= limit))
389 { 501 {
390 return CurrentMovementAnimation; 502 return CurrentMovementAnimation;
391 } 503 }
392 else 504 else
393 { 505 {
394 m_fallHeight = actor.Position.Z; // save latest flying height 506 currentControlState = motionControlStates.onsurface;
507 m_animTickLand = 0;
395 return "STAND"; 508 return "STAND";
396 } 509 }
397 } 510 }
398 511
399 // next section moved outside paren. and realigned for jumping 512 // next section moved outside paren. and realigned for jumping
400 if (move.X != 0f || move.Y != 0f) 513
514 if (heldOnXY)
401 { 515 {
402 m_fallHeight = actor.Position.Z; // save latest flying height 516 currentControlState = motionControlStates.onsurface;
403 Falling = false; 517 Falling = false;
404 // Walking / crouchwalking / running 518 // Walking / crouchwalking / running
405 if (move.Z < 0f) 519 if (heldDown)
406 { 520 {
407 return "CROUCHWALK"; 521 return "CROUCHWALK";
408 } 522 }
@@ -416,11 +530,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
416 return "WALK"; 530 return "WALK";
417 } 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,8 +546,6 @@ 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
@@ -442,7 +555,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
442 /// <returns>'true' if the animation was changed</returns> 555 /// <returns>'true' if the animation was changed</returns>
443 public bool UpdateMovementAnimations() 556 public bool UpdateMovementAnimations()
444 { 557 {
445// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name); 558 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
446 559
447 bool ret = false; 560 bool ret = false;
448 lock (m_animations) 561 lock (m_animations)
@@ -450,7 +563,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 string newMovementAnimation = DetermineMovementAnimation(); 563 string newMovementAnimation = DetermineMovementAnimation();
451 if (CurrentMovementAnimation != newMovementAnimation) 564 if (CurrentMovementAnimation != newMovementAnimation)
452 { 565 {
453 CurrentMovementAnimation = DetermineMovementAnimation(); 566 CurrentMovementAnimation = newMovementAnimation;
454 567
455// m_log.DebugFormat( 568// m_log.DebugFormat(
456// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", 569// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
@@ -464,6 +577,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation
464 return ret; 577 return ret;
465 } 578 }
466 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 }
596 }
597
467 public UUID[] GetAnimationArray() 598 public UUID[] GetAnimationArray()
468 { 599 {
469 UUID[] animIDs; 600 UUID[] animIDs;
@@ -472,19 +603,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
472 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 603 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
473 return animIDs; 604 return animIDs;
474 } 605 }
475 606
476 public BinBVHAnimation GenerateRandomAnimation() 607 public BinBVHAnimation GenerateRandomAnimation()
477 { 608 {
478 int rnditerations = 3; 609 int rnditerations = 3;
479 BinBVHAnimation anim = new BinBVHAnimation(); 610 BinBVHAnimation anim = new BinBVHAnimation();
480 List<string> parts = new List<string>(); 611 List<string> parts = new List<string>();
481 parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); 612 parts.Add("mPelvis"); parts.Add("mHead"); parts.Add("mTorso");
482 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");
483 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");
484 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");
485 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");
486 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");
487 parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); 618 parts.Add("mFootLeft"); parts.Add("mFootRight"); parts.Add("mEyeLeft");
488 anim.HandPose = 1; 619 anim.HandPose = 1;
489 anim.InPoint = 0; 620 anim.InPoint = 0;
490 anim.OutPoint = (rnditerations * .10f); 621 anim.OutPoint = (rnditerations * .10f);
@@ -508,12 +639,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
508 for (int i = 0; i < rnditerations; i++) 639 for (int i = 0; i < rnditerations; i++)
509 { 640 {
510 anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); 641 anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
511 anim.Joints[j].rotationkeys[i].time = (i*.10f); 642 anim.Joints[j].rotationkeys[i].time = (i * .10f);
512 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);
513 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);
514 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);
515 anim.Joints[j].positionkeys[i] = new binBVHJointKey(); 646 anim.Joints[j].positionkeys[i] = new binBVHJointKey();
516 anim.Joints[j].positionkeys[i].time = (i*.10f); 647 anim.Joints[j].positionkeys[i].time = (i * .10f);
517 anim.Joints[j].positionkeys[i].key_element.X = 0; 648 anim.Joints[j].positionkeys[i].key_element.X = 0;
518 anim.Joints[j].positionkeys[i].key_element.Y = 0; 649 anim.Joints[j].positionkeys[i].key_element.Y = 0;
519 anim.Joints[j].positionkeys[i].key_element.Z = 0; 650 anim.Joints[j].positionkeys[i].key_element.Z = 0;
@@ -540,20 +671,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
540 /// <param name="objectIDs"></param> 671 /// <param name="objectIDs"></param>
541 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) 672 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
542 { 673 {
543 if (m_scenePresence.IsChildAgent) 674 m_scenePresence.SendAnimPack(animations, seqs, objectIDs);
544 return; 675 }
545 676
546// m_log.DebugFormat( 677 public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs)
547// "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'", 678 {
548// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), 679 animIDs = null;
549// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), 680 sequenceNums = null;
550// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); 681 objectIDs = null;
551 682
552 m_scenePresence.Scene.ForEachClient( 683 if (m_animations != null)
553 delegate(IClientAPI client) 684 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
554 {
555 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
556 });
557 } 685 }
558 686
559 public void SendAnimPackToClient(IClientAPI client) 687 public void SendAnimPackToClient(IClientAPI client)
@@ -575,7 +703,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
575 public void SendAnimPack() 703 public void SendAnimPack()
576 { 704 {
577 //m_log.Debug("Sending animation pack to all"); 705 //m_log.Debug("Sending animation pack to all");
578 706
579 if (m_scenePresence.IsChildAgent) 707 if (m_scenePresence.IsChildAgent)
580 return; 708 return;
581 709
@@ -585,7 +713,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
585 713
586 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 714 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
587 715
588 SendAnimPack(animIDs, sequenceNums, objectIDs); 716 // SendAnimPack(animIDs, sequenceNums, objectIDs);
717 m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs);
589 } 718 }
590 719
591 public string GetAnimName(UUID animId) 720 public string GetAnimName(UUID animId)
diff --git a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
new file mode 100644
index 0000000..075724e
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
@@ -0,0 +1,304 @@
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// Ubit 2012
28
29using System;
30using System.Reflection;
31using System.Collections.Generic;
32using OpenMetaverse;
33using OpenSim.Framework;
34using log4net;
35
36namespace OpenSim.Region.Framework.Scenes
37{
38 public struct CollisionForSoundInfo
39 {
40 public uint colliderID;
41 public Vector3 position;
42 public float relativeVel;
43 }
44
45 public static class CollisionSounds
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private const int MaxMaterials = 7;
50 // part part
51
52 private static UUID snd_StoneStone = new UUID("be7295c0-a158-11e1-b3dd-0800200c9a66");
53 private static UUID snd_StoneMetal = new UUID("be7295c0-a158-11e1-b3dd-0800201c9a66");
54 private static UUID snd_StoneGlass = new UUID("be7295c0-a158-11e1-b3dd-0800202c9a66");
55 private static UUID snd_StoneWood = new UUID("be7295c0-a158-11e1-b3dd-0800203c9a66");
56 private static UUID snd_StoneFlesh = new UUID("be7295c0-a158-11e1-b3dd-0800204c9a66");
57 private static UUID snd_StonePlastic = new UUID("be7295c0-a158-11e1-b3dd-0800205c9a66");
58 private static UUID snd_StoneRubber = new UUID("be7295c0-a158-11e1-b3dd-0800206c9a66");
59
60 private static UUID snd_MetalMetal = new UUID("be7295c0-a158-11e1-b3dd-0801201c9a66");
61 private static UUID snd_MetalGlass = new UUID("be7295c0-a158-11e1-b3dd-0801202c9a66");
62 private static UUID snd_MetalWood = new UUID("be7295c0-a158-11e1-b3dd-0801203c9a66");
63 private static UUID snd_MetalFlesh = new UUID("be7295c0-a158-11e1-b3dd-0801204c9a66");
64 private static UUID snd_MetalPlastic = new UUID("be7295c0-a158-11e1-b3dd-0801205c9a66");
65 private static UUID snd_MetalRubber = new UUID("be7295c0-a158-11e1-b3dd-0801206c9a66");
66
67 private static UUID snd_GlassGlass = new UUID("be7295c0-a158-11e1-b3dd-0802202c9a66");
68 private static UUID snd_GlassWood = new UUID("be7295c0-a158-11e1-b3dd-0802203c9a66");
69 private static UUID snd_GlassFlesh = new UUID("be7295c0-a158-11e1-b3dd-0802204c9a66");
70 private static UUID snd_GlassPlastic = new UUID("be7295c0-a158-11e1-b3dd-0802205c9a66");
71 private static UUID snd_GlassRubber = new UUID("be7295c0-a158-11e1-b3dd-0802206c9a66");
72
73 private static UUID snd_WoodWood = new UUID("be7295c0-a158-11e1-b3dd-0803203c9a66");
74 private static UUID snd_WoodFlesh = new UUID("be7295c0-a158-11e1-b3dd-0803204c9a66");
75 private static UUID snd_WoodPlastic = new UUID("be7295c0-a158-11e1-b3dd-0803205c9a66");
76 private static UUID snd_WoodRubber = new UUID("be7295c0-a158-11e1-b3dd-0803206c9a66");
77
78 private static UUID snd_FleshFlesh = new UUID("be7295c0-a158-11e1-b3dd-0804204c9a66");
79 private static UUID snd_FleshPlastic = new UUID("be7295c0-a158-11e1-b3dd-0804205c9a66");
80 private static UUID snd_FleshRubber = new UUID("be7295c0-a158-11e1-b3dd-0804206c9a66");
81
82 private static UUID snd_PlasticPlastic = new UUID("be7295c0-a158-11e1-b3dd-0805205c9a66");
83 private static UUID snd_PlasticRubber = new UUID("be7295c0-a158-11e1-b3dd-0805206c9a66");
84
85 private static UUID snd_RubberRubber = new UUID("be7295c0-a158-11e1-b3dd-0806206c9a66");
86
87 // terrain part
88 private static UUID snd_TerrainStone = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
89 private static UUID snd_TerrainMetal = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
90 private static UUID snd_TerrainGlass = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
91 private static UUID snd_TerrainWood = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
92 private static UUID snd_TerrainFlesh = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
93 private static UUID snd_TerrainPlastic = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
94 private static UUID snd_TerrainRubber = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
95
96 public static UUID[] m_TerrainPart = {
97 snd_TerrainStone,
98 snd_TerrainMetal,
99 snd_TerrainGlass,
100 snd_TerrainWood,
101 snd_TerrainFlesh,
102 snd_TerrainPlastic,
103 snd_TerrainRubber
104 };
105
106 // simetric sounds
107 public static UUID[] m_PartPart = {
108 snd_StoneStone, snd_StoneMetal, snd_StoneGlass, snd_StoneWood, snd_StoneFlesh, snd_StonePlastic, snd_StoneRubber,
109 snd_StoneMetal, snd_MetalMetal, snd_MetalGlass, snd_MetalWood, snd_MetalFlesh, snd_MetalPlastic, snd_MetalRubber,
110 snd_StoneGlass, snd_MetalGlass, snd_GlassGlass, snd_GlassWood, snd_GlassFlesh, snd_GlassPlastic, snd_GlassRubber,
111 snd_StoneWood, snd_MetalWood, snd_GlassWood, snd_WoodWood, snd_WoodFlesh, snd_WoodPlastic, snd_WoodRubber,
112 snd_StoneFlesh, snd_MetalFlesh, snd_GlassFlesh, snd_WoodFlesh, snd_FleshFlesh, snd_FleshPlastic, snd_FleshRubber,
113 snd_StonePlastic, snd_MetalPlastic, snd_GlassPlastic, snd_WoodPlastic, snd_FleshPlastic, snd_PlasticPlastic, snd_PlasticRubber,
114 snd_StoneRubber, snd_MetalRubber, snd_GlassRubber, snd_WoodRubber, snd_FleshRubber, snd_PlasticRubber, snd_RubberRubber
115 };
116
117 public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist)
118 {
119 if (collidersinfolist.Count == 0 || part == null)
120 return;
121
122 if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
123 return;
124
125 if (part.ParentGroup == null)
126 return;
127
128 if (part.CollisionSoundType < 0)
129 return;
130
131 float volume = 0.0f;
132 bool HaveSound = false;
133
134 UUID soundID = part.CollisionSound;
135
136 if (part.CollisionSoundType > 0)
137 {
138 // soundID = part.CollisionSound;
139 volume = part.CollisionSoundVolume;
140 if (volume == 0.0f)
141 return;
142 HaveSound = true;
143 }
144
145 bool doneownsound = false;
146
147 int thisMaterial = (int)part.Material;
148 if (thisMaterial >= MaxMaterials)
149 thisMaterial = 3;
150 int thisMatScaled = thisMaterial * MaxMaterials;
151
152 CollisionForSoundInfo colInfo;
153 uint id;
154
155 for(int i = 0; i< collidersinfolist.Count; i++)
156 {
157 colInfo = collidersinfolist[i];
158
159 id = colInfo.colliderID;
160 if (id == 0) // terrain collision
161 {
162 if (!doneownsound)
163 {
164 if (!HaveSound)
165 {
166 volume = Math.Abs(colInfo.relativeVel);
167 if (volume < 0.2f)
168 continue;
169
170 volume *= volume * .0625f; // 4m/s == full volume
171 if (volume > 1.0f)
172 volume = 1.0f;
173
174 soundID = m_TerrainPart[thisMaterial];
175 }
176 part.SendCollisionSound(soundID, volume, colInfo.position);
177 doneownsound = true;
178 }
179 continue;
180 }
181
182 SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id);
183 if (otherPart != null)
184 {
185 if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive)
186 continue;
187
188 if (!HaveSound)
189 {
190 if (otherPart.CollisionSoundType > 0)
191 {
192 soundID = otherPart.CollisionSound;
193 volume = otherPart.CollisionSoundVolume;
194 if (volume == 0.0f)
195 continue;
196 }
197 else
198 {
199 volume = Math.Abs(colInfo.relativeVel);
200 if (volume < 0.2f)
201 continue;
202
203 volume *= volume * .0625f; // 4m/s == full volume
204 if (volume > 1.0f)
205 volume = 1.0f;
206
207 int otherMaterial = (int)otherPart.Material;
208 if (otherMaterial >= MaxMaterials)
209 otherMaterial = 3;
210
211 soundID = m_PartPart[thisMatScaled + otherMaterial];
212 }
213 }
214
215 if (doneownsound)
216 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
217 else
218 {
219 part.SendCollisionSound(soundID, volume, colInfo.position);
220 doneownsound = true;
221 }
222 }
223 }
224 }
225
226 public static void AvatarCollisionSound(ScenePresence av, List<CollisionForSoundInfo> collidersinfolist)
227 {
228 if (collidersinfolist.Count == 0 || av == null)
229 return;
230
231 UUID soundID;
232 int otherMaterial;
233
234 int thisMaterial = 4; // flesh
235
236 int thisMatScaled = thisMaterial * MaxMaterials;
237
238 // bool doneownsound = false;
239
240 CollisionForSoundInfo colInfo;
241 uint id;
242 float volume;
243
244 for(int i = 0; i< collidersinfolist.Count; i++)
245 {
246 colInfo = collidersinfolist[i];
247
248 id = colInfo.colliderID;
249
250 if (id == 0) // no terrain collision sounds for now
251 {
252 continue;
253// volume = Math.Abs(colInfo.relativeVel);
254// if (volume < 0.2f)
255// continue;
256
257 }
258
259 SceneObjectPart otherPart = av.Scene.GetSceneObjectPart(id);
260 if (otherPart != null)
261 {
262 if (otherPart.CollisionSoundType < 0)
263 continue;
264 if (otherPart.CollisionSoundType > 0 && otherPart.CollisionSoundVolume > 0f)
265 otherPart.SendCollisionSound(otherPart.CollisionSound, otherPart.CollisionSoundVolume, colInfo.position);
266 else
267 {
268 volume = Math.Abs(colInfo.relativeVel);
269 // Most noral collisions (running into walls, stairs)
270 // should never be heard.
271 if (volume < 3.2f)
272 continue;
273// m_log.DebugFormat("Collision speed was {0}", volume);
274
275 // Cap to 0.2 times volume because climbing stairs should not be noisy
276 // Also changed scaling
277 volume *= volume * .0125f; // 4m/s == volume 0.2
278 if (volume > 0.2f)
279 volume = 0.2f;
280 otherMaterial = (int)otherPart.Material;
281 if (otherMaterial >= MaxMaterials)
282 otherMaterial = 3;
283
284 soundID = m_PartPart[thisMatScaled + otherMaterial];
285 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
286 }
287 continue;
288 }
289/*
290 else if (!doneownsound)
291 {
292 ScenePresence otherav = av.Scene.GetScenePresence(Id);
293 if (otherav != null && (!otherav.IsChildAgent))
294 {
295 soundID = snd_FleshFlesh;
296 av.SendCollisionSound(soundID, 1.0);
297 doneownsound = true;
298 }
299 }
300 */
301 }
302 }
303 }
304}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 97b9482..0a6bca4 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -80,6 +80,7 @@ namespace OpenSim.Region.Framework.Scenes
80 public event OnTerrainTaintedDelegate OnTerrainTainted; 80 public event OnTerrainTaintedDelegate OnTerrainTainted;
81 81
82 public delegate void OnTerrainTickDelegate(); 82 public delegate void OnTerrainTickDelegate();
83 public delegate void OnTerrainCheckUpdatesDelegate();
83 84
84 /// <summary> 85 /// <summary>
85 /// Triggered if the terrain has been edited 86 /// Triggered if the terrain has been edited
@@ -89,6 +90,11 @@ namespace OpenSim.Region.Framework.Scenes
89 /// but is used by core solely to update the physics engine. 90 /// but is used by core solely to update the physics engine.
90 /// </remarks> 91 /// </remarks>
91 public event OnTerrainTickDelegate OnTerrainTick; 92 public event OnTerrainTickDelegate OnTerrainTick;
93 public event OnTerrainCheckUpdatesDelegate OnTerrainCheckUpdates;
94
95 public delegate void OnTerrainUpdateDelegate();
96
97 public event OnTerrainUpdateDelegate OnTerrainUpdate;
92 98
93 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 99 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
94 100
@@ -339,8 +345,6 @@ namespace OpenSim.Region.Framework.Scenes
339 /// in <see cref="Scene.SetScriptRunning"/> 345 /// in <see cref="Scene.SetScriptRunning"/>
340 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>, 346 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>,
341 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/> 347 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/>
342 /// XXX: This is only triggered when it is the client that starts the script, not in other situations where
343 /// a script is started, unlike OnStopScript!
344 /// </remarks> 348 /// </remarks>
345 public event StartScript OnStartScript; 349 public event StartScript OnStartScript;
346 350
@@ -354,7 +358,6 @@ namespace OpenSim.Region.Framework.Scenes
354 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>, 358 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>,
355 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>, 359 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>,
356 /// <see cref="Scene.SetScriptRunning"/> 360 /// <see cref="Scene.SetScriptRunning"/>
357 /// XXX: This is triggered when a sciprt is stopped for any reason, unlike OnStartScript!
358 /// </remarks> 361 /// </remarks>
359 public event StopScript OnStopScript; 362 public event StopScript OnStopScript;
360 363
@@ -858,6 +861,10 @@ namespace OpenSim.Region.Framework.Scenes
858 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 861 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
859 public event GetScriptRunning OnGetScriptRunning; 862 public event GetScriptRunning OnGetScriptRunning;
860 863
864 public delegate void ThrottleUpdate(ScenePresence scenePresence);
865
866 public event ThrottleUpdate OnThrottleUpdate;
867
861 /// <summary> 868 /// <summary>
862 /// RegisterCapsEvent is called by Scene after the Caps object 869 /// RegisterCapsEvent is called by Scene after the Caps object
863 /// has been instantiated and before it is return to the 870 /// has been instantiated and before it is return to the
@@ -1377,7 +1384,9 @@ namespace OpenSim.Region.Framework.Scenes
1377 { 1384 {
1378 try 1385 try
1379 { 1386 {
1387// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate: {0}",d.Target.ToString());
1380 d(agentId); 1388 d(agentId);
1389// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate done ");
1381 } 1390 }
1382 catch (Exception e) 1391 catch (Exception e)
1383 { 1392 {
@@ -1451,6 +1460,26 @@ namespace OpenSim.Region.Framework.Scenes
1451 } 1460 }
1452 } 1461 }
1453 } 1462 }
1463 public void TriggerTerrainUpdate()
1464 {
1465 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
1466 if (handlerTerrainUpdate != null)
1467 {
1468 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
1469 {
1470 try
1471 {
1472 d();
1473 }
1474 catch (Exception e)
1475 {
1476 m_log.ErrorFormat(
1477 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
1478 e.Message, e.StackTrace);
1479 }
1480 }
1481 }
1482 }
1454 1483
1455 public void TriggerTerrainTick() 1484 public void TriggerTerrainTick()
1456 { 1485 {
@@ -1473,6 +1502,27 @@ namespace OpenSim.Region.Framework.Scenes
1473 } 1502 }
1474 } 1503 }
1475 1504
1505 public void TriggerTerrainCheckUpdates()
1506 {
1507 OnTerrainCheckUpdatesDelegate TerrainCheckUpdates = OnTerrainCheckUpdates;
1508 if (TerrainCheckUpdates != null)
1509 {
1510 foreach (OnTerrainCheckUpdatesDelegate d in TerrainCheckUpdates.GetInvocationList())
1511 {
1512 try
1513 {
1514 d();
1515 }
1516 catch (Exception e)
1517 {
1518 m_log.ErrorFormat(
1519 "[EVENT MANAGER]: Delegate for TerrainCheckUpdates failed - continuing. {0} {1}",
1520 e.Message, e.StackTrace);
1521 }
1522 }
1523 }
1524 }
1525
1476 public void TriggerTerrainTainted() 1526 public void TriggerTerrainTainted()
1477 { 1527 {
1478 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted; 1528 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted;
@@ -1808,6 +1858,7 @@ namespace OpenSim.Region.Framework.Scenes
1808 m_log.ErrorFormat( 1858 m_log.ErrorFormat(
1809 "[EVENT MANAGER]: Delegate for TriggerRemoveScript failed - continuing. {0} {1}", 1859 "[EVENT MANAGER]: Delegate for TriggerRemoveScript failed - continuing. {0} {1}",
1810 e.Message, e.StackTrace); 1860 e.Message, e.StackTrace);
1861 m_log.ErrorFormat(Environment.StackTrace);
1811 } 1862 }
1812 } 1863 }
1813 } 1864 }
@@ -2073,7 +2124,10 @@ namespace OpenSim.Region.Framework.Scenes
2073 { 2124 {
2074 try 2125 try
2075 { 2126 {
2127// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed: {0}", d.Target.ToString());
2076 d(ClientID, scene); 2128 d(ClientID, scene);
2129// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed done ");
2130
2077 } 2131 }
2078 catch (Exception e) 2132 catch (Exception e)
2079 { 2133 {
@@ -3107,6 +3161,7 @@ namespace OpenSim.Region.Framework.Scenes
3107 { 3161 {
3108 foreach (Action<Scene> d in handler.GetInvocationList()) 3162 foreach (Action<Scene> d in handler.GetInvocationList())
3109 { 3163 {
3164 m_log.InfoFormat("[EVENT MANAGER]: TriggerSceneShuttingDown invoque {0}", d.Method.Name.ToString());
3110 try 3165 try
3111 { 3166 {
3112 d(s); 3167 d(s);
@@ -3119,6 +3174,7 @@ namespace OpenSim.Region.Framework.Scenes
3119 } 3174 }
3120 } 3175 }
3121 } 3176 }
3177 m_log.Info("[EVENT MANAGER]: TriggerSceneShuttingDown done");
3122 } 3178 }
3123 3179
3124 public void TriggerOnRegionStarted(Scene scene) 3180 public void TriggerOnRegionStarted(Scene scene)
@@ -3310,6 +3366,15 @@ namespace OpenSim.Region.Framework.Scenes
3310 } 3366 }
3311 } 3367 }
3312 3368
3369 public void TriggerThrottleUpdate(ScenePresence scenePresence)
3370 {
3371 ThrottleUpdate handler = OnThrottleUpdate;
3372 if (handler != null)
3373 {
3374 handler(scenePresence);
3375 }
3376 }
3377
3313// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids) 3378// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3314// { 3379// {
3315// GatherUuids handler = OnGatherUuids; 3380// GatherUuids handler = OnGatherUuids;
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index bbf3b51..cdd8d2d 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -292,14 +292,17 @@ namespace OpenSim.Region.Framework.Scenes
292 292
293 private void StartTimer() 293 private void StartTimer()
294 { 294 {
295 KeyframeTimer.Add(this); 295 lock (m_frames)
296 m_timerStopped = false; 296 {
297 KeyframeTimer.Add(this);
298 m_timerStopped = false;
299 }
297 } 300 }
298 301
299 private void StopTimer() 302 private void StopTimer()
300 { 303 {
301 m_timerStopped = true; 304 lock (m_frames)
302 KeyframeTimer.Remove(this); 305 m_timerStopped = true;
303 } 306 }
304 307
305 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 308 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
@@ -348,24 +351,26 @@ namespace OpenSim.Region.Framework.Scenes
348 m_group = grp; 351 m_group = grp;
349 m_scene = grp.Scene; 352 m_scene = grp.Scene;
350 353
351 Vector3 grppos = grp.AbsolutePosition;
352 Vector3 offset = grppos - m_serializedPosition;
353 // avoid doing it more than once
354 // current this will happen dragging a prim to other region
355 m_serializedPosition = grppos;
356 354
357 m_basePosition += offset; 355 lock (m_frames)
358 m_nextPosition += offset;
359
360 m_currentFrame.StartPosition += offset;
361 m_currentFrame.Position += offset;
362
363 for (int i = 0; i < m_frames.Count; i++)
364 { 356 {
365 Keyframe k = m_frames[i]; 357 Vector3 grppos = grp.AbsolutePosition;
366 k.StartPosition += offset; 358 Vector3 offset = grppos - m_serializedPosition;
367 k.Position += offset; 359 // avoid doing it more than once
368 m_frames[i]=k; 360 // current this will happen draging a prim to other region
361 m_serializedPosition = grppos;
362
363 m_basePosition += offset;
364 m_currentFrame.Position += offset;
365
366 m_nextPosition += offset;
367
368 for (int i = 0; i < m_frames.Count; i++)
369 {
370 Keyframe k = m_frames[i];
371 k.Position += offset;
372 m_frames[i] = k;
373 }
369 } 374 }
370 375
371 if (m_running) 376 if (m_running)
@@ -410,25 +415,28 @@ namespace OpenSim.Region.Framework.Scenes
410 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 415 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
411 } 416 }
412 417
413 newmotion.m_frames = new List<Keyframe>(m_frames); 418 lock (m_frames)
419 {
420 newmotion.m_frames = new List<Keyframe>(m_frames);
414 421
415 newmotion.m_basePosition = m_basePosition; 422 newmotion.m_basePosition = m_basePosition;
416 newmotion.m_baseRotation = m_baseRotation; 423 newmotion.m_baseRotation = m_baseRotation;
417 424
418 if (m_selected) 425 if (m_selected)
419 newmotion.m_serializedPosition = m_serializedPosition;
420 else
421 {
422 if (m_group != null)
423 newmotion.m_serializedPosition = m_group.AbsolutePosition;
424 else
425 newmotion.m_serializedPosition = m_serializedPosition; 426 newmotion.m_serializedPosition = m_serializedPosition;
426 } 427 else
428 {
429 if (m_group != null)
430 newmotion.m_serializedPosition = m_group.AbsolutePosition;
431 else
432 newmotion.m_serializedPosition = m_serializedPosition;
433 }
427 434
428 newmotion.m_currentFrame = m_currentFrame; 435 newmotion.m_currentFrame = m_currentFrame;
429 436
430 newmotion.m_iterations = m_iterations; 437 newmotion.m_iterations = m_iterations;
431 newmotion.m_running = m_running; 438 newmotion.m_running = m_running;
439 }
432 440
433 if (m_running && !m_waitingCrossing) 441 if (m_running && !m_waitingCrossing)
434 StartTimer(); 442 StartTimer();
@@ -458,19 +466,18 @@ namespace OpenSim.Region.Framework.Scenes
458 } 466 }
459 else 467 else
460 { 468 {
461 m_running = false;
462 StopTimer(); 469 StopTimer();
470 m_running = false;
463 } 471 }
464 } 472 }
465 473
466 public void Stop() 474 public void Stop()
467 { 475 {
476 StopTimer();
468 m_running = false; 477 m_running = false;
469 m_isCrossing = false; 478 m_isCrossing = false;
470 m_waitingCrossing = false; 479 m_waitingCrossing = false;
471 480
472 StopTimer();
473
474 m_basePosition = m_group.AbsolutePosition; 481 m_basePosition = m_group.AbsolutePosition;
475 m_baseRotation = m_group.GroupRotation; 482 m_baseRotation = m_group.GroupRotation;
476 483
@@ -483,14 +490,34 @@ namespace OpenSim.Region.Framework.Scenes
483 490
484 public void Pause() 491 public void Pause()
485 { 492 {
486 m_running = false;
487 StopTimer(); 493 StopTimer();
494 m_running = false;
488 495
489 m_group.RootPart.Velocity = Vector3.Zero; 496 m_group.RootPart.Velocity = Vector3.Zero;
490 m_group.RootPart.AngularVelocity = Vector3.Zero; 497 m_group.RootPart.AngularVelocity = Vector3.Zero;
491 m_group.SendGroupRootTerseUpdate(); 498 m_group.SendGroupRootTerseUpdate();
492// m_group.RootPart.ScheduleTerseUpdate(); 499// m_group.RootPart.ScheduleTerseUpdate();
500 }
493 501
502 public void Suspend()
503 {
504 lock (m_frames)
505 {
506 if (m_timerStopped)
507 return;
508 m_timerStopped = true;
509 }
510 }
511
512 public void Resume()
513 {
514 lock (m_frames)
515 {
516 if (!m_timerStopped)
517 return;
518 if (m_running && !m_waitingCrossing)
519 StartTimer();
520 }
494 } 521 }
495 522
496 private void GetNextList() 523 private void GetNextList()
@@ -581,6 +608,7 @@ namespace OpenSim.Region.Framework.Scenes
581 608
582 pos = (Vector3)k.Position; 609 pos = (Vector3)k.Position;
583 rot = (Quaternion)k.Rotation; 610 rot = (Quaternion)k.Rotation;
611
584 } 612 }
585 613
586 m_basePosition = pos; 614 m_basePosition = pos;
@@ -592,15 +620,41 @@ namespace OpenSim.Region.Framework.Scenes
592 620
593 public void OnTimer(double tickDuration) 621 public void OnTimer(double tickDuration)
594 { 622 {
623 if (!Monitor.TryEnter(m_frames))
624 return;
625 if (m_timerStopped)
626 KeyframeTimer.Remove(this);
627 else
628 DoOnTimer(tickDuration);
629 Monitor.Exit(m_frames);
630 }
631
632 private void Done()
633 {
634 KeyframeTimer.Remove(this);
635 m_timerStopped = true;
636 m_running = false;
637 m_isCrossing = false;
638 m_waitingCrossing = false;
639
640 m_basePosition = m_group.AbsolutePosition;
641 m_baseRotation = m_group.GroupRotation;
642
643 m_group.RootPart.Velocity = Vector3.Zero;
644 m_group.RootPart.AngularVelocity = Vector3.Zero;
645 m_group.SendGroupRootTerseUpdate();
646 // m_group.RootPart.ScheduleTerseUpdate();
647 m_frames.Clear();
648 }
649
650 private void DoOnTimer(double tickDuration)
651 {
595 if (m_skipLoops > 0) 652 if (m_skipLoops > 0)
596 { 653 {
597 m_skipLoops--; 654 m_skipLoops--;
598 return; 655 return;
599 } 656 }
600 657
601 if (m_timerStopped) // trap events still in air even after a timer.stop
602 return;
603
604 if (m_group == null) 658 if (m_group == null)
605 return; 659 return;
606 660
@@ -612,7 +666,6 @@ namespace OpenSim.Region.Framework.Scenes
612 { 666 {
613 m_group.RootPart.Velocity = Vector3.Zero; 667 m_group.RootPart.Velocity = Vector3.Zero;
614 m_group.SendGroupRootTerseUpdate(); 668 m_group.SendGroupRootTerseUpdate();
615
616 } 669 }
617 return; 670 return;
618 } 671 }
@@ -635,32 +688,22 @@ namespace OpenSim.Region.Framework.Scenes
635 688
636 if (m_frames.Count == 0) 689 if (m_frames.Count == 0)
637 { 690 {
638 if (!m_running) return; 691 lock (m_frames)
639
640 GetNextList();
641
642 if (m_frames.Count == 0)
643 { 692 {
644 Stop(); 693 GetNextList();
645// Scene scene = m_group.Scene;
646//
647// IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
648// foreach (IScriptModule m in scriptModules)
649// {
650// if (m == null)
651// continue;
652// m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
653// }
654
655 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
656
657 return;
658 }
659 694
660 m_currentFrame = m_frames[0]; 695 if (m_frames.Count == 0)
661 m_currentFrame.TimeMS += (int)tickDuration; 696 {
697 Done();
698 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
699 return;
700 }
662 701
702 m_currentFrame = m_frames[0];
703 m_currentFrame.TimeMS += (int)tickDuration;
704 }
663 //force a update on a keyframe transition 705 //force a update on a keyframe transition
706 m_nextPosition = m_group.AbsolutePosition;
664 update = true; 707 update = true;
665 } 708 }
666 709
@@ -681,9 +724,13 @@ namespace OpenSim.Region.Framework.Scenes
681 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); 724 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
682 725
683 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 726 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
684 m_frames.RemoveAt(0); 727
685 if (m_frames.Count > 0) 728 lock (m_frames)
686 m_currentFrame = m_frames[0]; 729 {
730 m_frames.RemoveAt(0);
731 if (m_frames.Count > 0)
732 m_currentFrame = m_frames[0];
733 }
687 734
688 update = true; 735 update = true;
689 } 736 }
@@ -692,17 +739,14 @@ namespace OpenSim.Region.Framework.Scenes
692 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; 739 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
693 bool lastStep = m_currentFrame.TimeMS <= tickDuration; 740 bool lastStep = m_currentFrame.TimeMS <= tickDuration;
694 741
695 Vector3 positionThisStep = m_currentFrame.StartPosition + (m_currentFrame.Position.Value - m_currentFrame.StartPosition) * completed; 742 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
696 Vector3 motionThisStep = positionThisStep - m_group.AbsolutePosition; 743 Vector3 motionThisFrame = v / (float)remainingSteps;
744 v = v * 1000 / m_currentFrame.TimeMS;
697 745
698 float mag = Vector3.Mag(motionThisStep); 746 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
699 747
700 if ((mag >= 0.02f) || lastStep) 748 if (Vector3.Mag(motionThisFrame) >= 0.05f)
701 {
702 m_nextPosition = m_group.AbsolutePosition + motionThisStep;
703 m_group.AbsolutePosition = m_nextPosition;
704 update = true; 749 update = true;
705 }
706 750
707 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration; 751 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration;
708 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})", 752 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})",
@@ -714,43 +758,41 @@ namespace OpenSim.Region.Framework.Scenes
714 758
715 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); 759 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed);
716 step.Normalize(); 760 step.Normalize();
717/* use simpler change detection 761 /* use simpler change detection
718* float angle = 0; 762 * float angle = 0;
719 763
720 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 764 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
721 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 765 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
722 float aa_bb = aa * bb; 766 float aa_bb = aa * bb;
723 767
724 if (aa_bb == 0) 768 if (aa_bb == 0)
725 { 769 {
726 angle = 0; 770 angle = 0;
727 } 771 }
728 else 772 else
729 { 773 {
730 float ab = current.X * step.X + 774 float ab = current.X * step.X +
731 current.Y * step.Y + 775 current.Y * step.Y +
732 current.Z * step.Z + 776 current.Z * step.Z +
733 current.W * step.W; 777 current.W * step.W;
734 float q = (ab * ab) / aa_bb; 778 float q = (ab * ab) / aa_bb;
735 779
736 if (q > 1.0f) 780 if (q > 1.0f)
737 { 781 {
738 angle = 0; 782 angle = 0;
739 } 783 }
740 else 784 else
741 { 785 {
742 angle = (float)Math.Acos(2 * q - 1); 786 angle = (float)Math.Acos(2 * q - 1);
743 } 787 }
744 } 788 }
745 789
746 if (angle > 0.01f) 790 if (angle > 0.01f)
747*/ 791 */
748 if(Math.Abs(step.X - current.X) > 0.001f 792 if (Math.Abs(step.X - current.X) > 0.001f
749 || Math.Abs(step.Y - current.Y) > 0.001f 793 || Math.Abs(step.Y - current.Y) > 0.001f
750 || Math.Abs(step.Z - current.Z) > 0.001f 794 || Math.Abs(step.Z - current.Z) > 0.001f)
751 || lastStep) 795 // assuming w is a dependente var
752 // assuming w is a dependente var
753
754 { 796 {
755// m_group.UpdateGroupRotationR(step); 797// m_group.UpdateGroupRotationR(step);
756 m_group.RootPart.RotationOffset = step; 798 m_group.RootPart.RotationOffset = step;
@@ -763,25 +805,31 @@ namespace OpenSim.Region.Framework.Scenes
763 805
764 if (update) 806 if (update)
765 { 807 {
808 m_group.AbsolutePosition = m_nextPosition;
766 m_group.SendGroupRootTerseUpdate(); 809 m_group.SendGroupRootTerseUpdate();
767 } 810 }
768 } 811 }
769 812
770 public Byte[] Serialize() 813 public Byte[] Serialize()
771 { 814 {
815 bool timerWasStopped;
816 lock (m_frames)
817 {
818 timerWasStopped = m_timerStopped;
819 }
772 StopTimer(); 820 StopTimer();
773 821
774 SceneObjectGroup tmp = m_group; 822 SceneObjectGroup tmp = m_group;
775 m_group = null; 823 m_group = null;
776 if (!m_selected && tmp != null) 824
777 m_serializedPosition = tmp.AbsolutePosition;
778
779 using (MemoryStream ms = new MemoryStream()) 825 using (MemoryStream ms = new MemoryStream())
780 { 826 {
781 BinaryFormatter fmt = new BinaryFormatter(); 827 BinaryFormatter fmt = new BinaryFormatter();
828 if (!m_selected && tmp != null)
829 m_serializedPosition = tmp.AbsolutePosition;
782 fmt.Serialize(ms, this); 830 fmt.Serialize(ms, this);
783 m_group = tmp; 831 m_group = tmp;
784 if (m_running && !m_waitingCrossing) 832 if (!timerWasStopped && m_running && !m_waitingCrossing)
785 StartTimer(); 833 StartTimer();
786 834
787 return ms.ToArray(); 835 return ms.ToArray();
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index ae85560..bd9d580 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,true); 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 }
@@ -212,25 +218,43 @@ namespace OpenSim.Region.Framework.Scenes
212 } 218 }
213 219
214 // Use the camera position for local agents and avatar position for remote agents 220 // Use the camera position for local agents and avatar position for remote agents
215 Vector3 presencePos = (presence.IsChildAgent) ? 221 // Why would I want that? They could be camming but I still see them at the
216 presence.AbsolutePosition : 222 // avatar position, so why should I update them as if they were at their
217 presence.CameraPosition; 223 // camera positions? Makes no sense!
224 // TODO: Fix this mess
225 //Vector3 presencePos = (presence.IsChildAgent) ?
226 // presence.AbsolutePosition :
227 // presence.CameraPosition;
228
229 Vector3 presencePos = presence.AbsolutePosition;
218 230
219 // Compute the distance... 231 // Compute the distance...
220 double distance = Vector3.Distance(presencePos, entityPos); 232 double distance = Vector3.Distance(presencePos, entityPos);
221 233
222 // 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
223 // at 10, 20, 40, 80, 160, 320, 640, and 1280m 235 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
224 uint pqueue = PriorityQueue.NumberOfImmediateQueues; 236 uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue
225 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; 237 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
226 238/*
227 for (int i = 0; i < queues - 1; i++) 239 for (int i = 0; i < queues - 1; i++)
228 { 240 {
229 if (distance < 10 * Math.Pow(2.0,i)) 241 if (distance < 30 * Math.Pow(2.0,i))
230 break; 242 break;
231 pqueue++; 243 pqueue++;
232 } 244 }
233 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
234 // If this is a root agent, then determine front & back 258 // If this is a root agent, then determine front & back
235 // 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
236 if (useFrontBack && ! presence.IsChildAgent) 260 if (useFrontBack && ! presence.IsChildAgent)
diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
new file mode 100644
index 0000000..10ac37c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 public static class SOPMaterialData
36 {
37 public enum SopMaterial : int // redundante and not in use for now
38 {
39 Stone = 0,
40 Metal = 1,
41 Glass = 2,
42 Wood = 3,
43 Flesh = 4,
44 Plastic = 5,
45 Rubber = 6,
46 light = 7 // compatibility with old viewers
47 }
48
49 private struct MaterialData
50 {
51 public float friction;
52 public float bounce;
53 public MaterialData(float f, float b)
54 {
55 friction = f;
56 bounce = b;
57 }
58 }
59
60 private static MaterialData[] m_materialdata = {
61 new MaterialData(0.8f,0.4f), // Stone
62 new MaterialData(0.3f,0.4f), // Metal
63 new MaterialData(0.2f,0.7f), // Glass
64 new MaterialData(0.6f,0.5f), // Wood
65 new MaterialData(0.9f,0.3f), // Flesh
66 new MaterialData(0.4f,0.7f), // Plastic
67 new MaterialData(0.9f,0.95f), // Rubber
68 new MaterialData(0.0f,0.0f) // light ??
69 };
70
71 public static Material MaxMaterial
72 {
73 get { return (Material)(m_materialdata.Length - 1); }
74 }
75
76 public static float friction(Material material)
77 {
78 int indx = (int)material;
79 if (indx < m_materialdata.Length)
80 return (m_materialdata[indx].friction);
81 else
82 return 0;
83 }
84
85 public static float bounce(Material material)
86 {
87 int indx = (int)material;
88 if (indx < m_materialdata.Length)
89 return (m_materialdata[indx].bounce);
90 else
91 return 0;
92 }
93
94 }
95} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
new file mode 100644
index 0000000..b617f52
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,792 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using System.Text;
34using System.IO;
35using System.Xml;
36using OpenSim.Framework.Serialization;
37using OpenSim.Framework.Serialization.External;
38using OpenSim.Region.Framework.Scenes.Serialization;
39
40namespace OpenSim.Region.Framework.Scenes
41{
42 public class SOPVehicle
43 {
44 public VehicleData vd;
45
46 public Vehicle Type
47 {
48 get { return vd.m_type; }
49 }
50
51 public SOPVehicle()
52 {
53 vd = new VehicleData();
54 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
55 }
56
57 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
58 {
59 float len;
60 float timestep = 0.01f;
61 switch (pParam)
62 {
63 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
64 if (pValue < 0f) pValue = 0f;
65 if (pValue > 1f) pValue = 1f;
66 vd.m_angularDeflectionEfficiency = pValue;
67 break;
68 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
69 if (pValue < timestep) pValue = timestep;
70 vd.m_angularDeflectionTimescale = pValue;
71 break;
72 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
73 if (pValue < timestep) pValue = timestep;
74 else if (pValue > 120) pValue = 120;
75 vd.m_angularMotorDecayTimescale = pValue;
76 break;
77 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
78 if (pValue < timestep) pValue = timestep;
79 vd.m_angularMotorTimescale = pValue;
80 break;
81 case Vehicle.BANKING_EFFICIENCY:
82 if (pValue < -1f) pValue = -1f;
83 if (pValue > 1f) pValue = 1f;
84 vd.m_bankingEfficiency = pValue;
85 break;
86 case Vehicle.BANKING_MIX:
87 if (pValue < 0f) pValue = 0f;
88 if (pValue > 1f) pValue = 1f;
89 vd.m_bankingMix = pValue;
90 break;
91 case Vehicle.BANKING_TIMESCALE:
92 if (pValue < timestep) pValue = timestep;
93 vd.m_bankingTimescale = pValue;
94 break;
95 case Vehicle.BUOYANCY:
96 if (pValue < -1f) pValue = -1f;
97 if (pValue > 1f) pValue = 1f;
98 vd.m_VehicleBuoyancy = pValue;
99 break;
100 case Vehicle.HOVER_EFFICIENCY:
101 if (pValue < 0f) pValue = 0f;
102 if (pValue > 1f) pValue = 1f;
103 vd.m_VhoverEfficiency = pValue;
104 break;
105 case Vehicle.HOVER_HEIGHT:
106 vd.m_VhoverHeight = pValue;
107 break;
108 case Vehicle.HOVER_TIMESCALE:
109 if (pValue < timestep) pValue = timestep;
110 vd.m_VhoverTimescale = pValue;
111 break;
112 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
113 if (pValue < 0f) pValue = 0f;
114 if (pValue > 1f) pValue = 1f;
115 vd.m_linearDeflectionEfficiency = pValue;
116 break;
117 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
118 if (pValue < timestep) pValue = timestep;
119 vd.m_linearDeflectionTimescale = pValue;
120 break;
121 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
122 if (pValue < timestep) pValue = timestep;
123 else if (pValue > 120) pValue = 120;
124 vd.m_linearMotorDecayTimescale = pValue;
125 break;
126 case Vehicle.LINEAR_MOTOR_TIMESCALE:
127 if (pValue < timestep) pValue = timestep;
128 vd.m_linearMotorTimescale = pValue;
129 break;
130 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
131 if (pValue < 0f) pValue = 0f;
132 if (pValue > 1f) pValue = 1f;
133 vd.m_verticalAttractionEfficiency = pValue;
134 break;
135 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
136 if (pValue < timestep) pValue = timestep;
137 vd.m_verticalAttractionTimescale = pValue;
138 break;
139
140 // These are vector properties but the engine lets you use a single float value to
141 // set all of the components to the same value
142 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
143 if (pValue < timestep) pValue = timestep;
144 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
145 break;
146 case Vehicle.ANGULAR_MOTOR_DIRECTION:
147 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
148 len = vd.m_angularMotorDirection.Length();
149 if (len > 12.566f)
150 vd.m_angularMotorDirection *= (12.566f / len);
151 break;
152 case Vehicle.LINEAR_FRICTION_TIMESCALE:
153 if (pValue < timestep) pValue = timestep;
154 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
155 break;
156 case Vehicle.LINEAR_MOTOR_DIRECTION:
157 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
158 len = vd.m_linearMotorDirection.Length();
159 if (len > 30.0f)
160 vd.m_linearMotorDirection *= (30.0f / len);
161 break;
162 case Vehicle.LINEAR_MOTOR_OFFSET:
163 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
164 len = vd.m_linearMotorOffset.Length();
165 if (len > 100.0f)
166 vd.m_linearMotorOffset *= (100.0f / len);
167 break;
168 }
169 }//end ProcessFloatVehicleParam
170
171 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
172 {
173 float len;
174 float timestep = 0.01f;
175 switch (pParam)
176 {
177 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
178 if (pValue.X < timestep) pValue.X = timestep;
179 if (pValue.Y < timestep) pValue.Y = timestep;
180 if (pValue.Z < timestep) pValue.Z = timestep;
181
182 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
183 break;
184 case Vehicle.ANGULAR_MOTOR_DIRECTION:
185 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
186 // Limit requested angular speed to 2 rps= 4 pi rads/sec
187 len = vd.m_angularMotorDirection.Length();
188 if (len > 12.566f)
189 vd.m_angularMotorDirection *= (12.566f / len);
190 break;
191 case Vehicle.LINEAR_FRICTION_TIMESCALE:
192 if (pValue.X < timestep) pValue.X = timestep;
193 if (pValue.Y < timestep) pValue.Y = timestep;
194 if (pValue.Z < timestep) pValue.Z = timestep;
195 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
196 break;
197 case Vehicle.LINEAR_MOTOR_DIRECTION:
198 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
199 len = vd.m_linearMotorDirection.Length();
200 if (len > 30.0f)
201 vd.m_linearMotorDirection *= (30.0f / len);
202 break;
203 case Vehicle.LINEAR_MOTOR_OFFSET:
204 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
205 len = vd.m_linearMotorOffset.Length();
206 if (len > 100.0f)
207 vd.m_linearMotorOffset *= (100.0f / len);
208 break;
209 }
210 }//end ProcessVectorVehicleParam
211
212 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
213 {
214 switch (pParam)
215 {
216 case Vehicle.REFERENCE_FRAME:
217 vd.m_referenceFrame = pValue;
218 break;
219 }
220 }//end ProcessRotationVehicleParam
221
222 public void ProcessVehicleFlags(int pParam, bool remove)
223 {
224 if (remove)
225 {
226 vd.m_flags &= ~((VehicleFlag)pParam);
227 }
228 else
229 {
230 vd.m_flags |= (VehicleFlag)pParam;
231 }
232 }//end ProcessVehicleFlags
233
234 public void ProcessTypeChange(Vehicle pType)
235 {
236 vd.m_linearMotorDirection = Vector3.Zero;
237 vd.m_angularMotorDirection = Vector3.Zero;
238 vd.m_linearMotorOffset = Vector3.Zero;
239 vd.m_referenceFrame = Quaternion.Identity;
240
241 // Set Defaults For Type
242 vd.m_type = pType;
243 switch (pType)
244 {
245 case Vehicle.TYPE_NONE:
246 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
248 vd.m_linearMotorTimescale = 1000;
249 vd.m_linearMotorDecayTimescale = 120;
250 vd.m_angularMotorTimescale = 1000;
251 vd.m_angularMotorDecayTimescale = 1000;
252 vd.m_VhoverHeight = 0;
253 vd.m_VhoverEfficiency = 1;
254 vd.m_VhoverTimescale = 1000;
255 vd.m_VehicleBuoyancy = 0;
256 vd.m_linearDeflectionEfficiency = 0;
257 vd.m_linearDeflectionTimescale = 1000;
258 vd.m_angularDeflectionEfficiency = 0;
259 vd.m_angularDeflectionTimescale = 1000;
260 vd.m_bankingEfficiency = 0;
261 vd.m_bankingMix = 1;
262 vd.m_bankingTimescale = 1000;
263 vd.m_verticalAttractionEfficiency = 0;
264 vd.m_verticalAttractionTimescale = 1000;
265
266 vd.m_flags = (VehicleFlag)0;
267 break;
268
269 case Vehicle.TYPE_SLED:
270 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
271 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
272 vd.m_linearMotorTimescale = 1000;
273 vd.m_linearMotorDecayTimescale = 120;
274 vd.m_angularMotorTimescale = 1000;
275 vd.m_angularMotorDecayTimescale = 120;
276 vd.m_VhoverHeight = 0;
277 vd.m_VhoverEfficiency = 1;
278 vd.m_VhoverTimescale = 10;
279 vd.m_VehicleBuoyancy = 0;
280 vd.m_linearDeflectionEfficiency = 1;
281 vd.m_linearDeflectionTimescale = 1;
282 vd.m_angularDeflectionEfficiency = 0;
283 vd.m_angularDeflectionTimescale = 1000;
284 vd.m_bankingEfficiency = 0;
285 vd.m_bankingMix = 1;
286 vd.m_bankingTimescale = 10;
287 vd.m_flags &=
288 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
289 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
290 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
291 break;
292 case Vehicle.TYPE_CAR:
293 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
294 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
295 vd.m_linearMotorTimescale = 1;
296 vd.m_linearMotorDecayTimescale = 60;
297 vd.m_angularMotorTimescale = 1;
298 vd.m_angularMotorDecayTimescale = 0.8f;
299 vd.m_VhoverHeight = 0;
300 vd.m_VhoverEfficiency = 0;
301 vd.m_VhoverTimescale = 1000;
302 vd.m_VehicleBuoyancy = 0;
303 vd.m_linearDeflectionEfficiency = 1;
304 vd.m_linearDeflectionTimescale = 2;
305 vd.m_angularDeflectionEfficiency = 0;
306 vd.m_angularDeflectionTimescale = 10;
307 vd.m_verticalAttractionEfficiency = 1f;
308 vd.m_verticalAttractionTimescale = 10f;
309 vd.m_bankingEfficiency = -0.2f;
310 vd.m_bankingMix = 1;
311 vd.m_bankingTimescale = 1;
312 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
313 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
314 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
315 break;
316 case Vehicle.TYPE_BOAT:
317 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
318 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
319 vd.m_linearMotorTimescale = 5;
320 vd.m_linearMotorDecayTimescale = 60;
321 vd.m_angularMotorTimescale = 4;
322 vd.m_angularMotorDecayTimescale = 4;
323 vd.m_VhoverHeight = 0;
324 vd.m_VhoverEfficiency = 0.5f;
325 vd.m_VhoverTimescale = 2;
326 vd.m_VehicleBuoyancy = 1;
327 vd.m_linearDeflectionEfficiency = 0.5f;
328 vd.m_linearDeflectionTimescale = 3;
329 vd.m_angularDeflectionEfficiency = 0.5f;
330 vd.m_angularDeflectionTimescale = 5;
331 vd.m_verticalAttractionEfficiency = 0.5f;
332 vd.m_verticalAttractionTimescale = 5f;
333 vd.m_bankingEfficiency = -0.3f;
334 vd.m_bankingMix = 0.8f;
335 vd.m_bankingTimescale = 1;
336 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
337 VehicleFlag.HOVER_GLOBAL_HEIGHT |
338 VehicleFlag.HOVER_UP_ONLY |
339 VehicleFlag.LIMIT_ROLL_ONLY);
340 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
341 VehicleFlag.LIMIT_MOTOR_UP |
342 VehicleFlag.HOVER_WATER_ONLY);
343 break;
344 case Vehicle.TYPE_AIRPLANE:
345 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
346 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
347 vd.m_linearMotorTimescale = 2;
348 vd.m_linearMotorDecayTimescale = 60;
349 vd.m_angularMotorTimescale = 4;
350 vd.m_angularMotorDecayTimescale = 8;
351 vd.m_VhoverHeight = 0;
352 vd.m_VhoverEfficiency = 0.5f;
353 vd.m_VhoverTimescale = 1000;
354 vd.m_VehicleBuoyancy = 0;
355 vd.m_linearDeflectionEfficiency = 0.5f;
356 vd.m_linearDeflectionTimescale = 0.5f;
357 vd.m_angularDeflectionEfficiency = 1;
358 vd.m_angularDeflectionTimescale = 2;
359 vd.m_verticalAttractionEfficiency = 0.9f;
360 vd.m_verticalAttractionTimescale = 2f;
361 vd.m_bankingEfficiency = 1;
362 vd.m_bankingMix = 0.7f;
363 vd.m_bankingTimescale = 2;
364 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
365 VehicleFlag.HOVER_TERRAIN_ONLY |
366 VehicleFlag.HOVER_GLOBAL_HEIGHT |
367 VehicleFlag.HOVER_UP_ONLY |
368 VehicleFlag.NO_DEFLECTION_UP |
369 VehicleFlag.LIMIT_MOTOR_UP);
370 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
371 break;
372 case Vehicle.TYPE_BALLOON:
373 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
374 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
375 vd.m_linearMotorTimescale = 5;
376 vd.m_linearMotorDecayTimescale = 60;
377 vd.m_angularMotorTimescale = 6;
378 vd.m_angularMotorDecayTimescale = 10;
379 vd.m_VhoverHeight = 5;
380 vd.m_VhoverEfficiency = 0.8f;
381 vd.m_VhoverTimescale = 10;
382 vd.m_VehicleBuoyancy = 1;
383 vd.m_linearDeflectionEfficiency = 0;
384 vd.m_linearDeflectionTimescale = 5;
385 vd.m_angularDeflectionEfficiency = 0;
386 vd.m_angularDeflectionTimescale = 5;
387 vd.m_verticalAttractionEfficiency = 0f;
388 vd.m_verticalAttractionTimescale = 1000f;
389 vd.m_bankingEfficiency = 0;
390 vd.m_bankingMix = 0.7f;
391 vd.m_bankingTimescale = 5;
392 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
393 VehicleFlag.HOVER_TERRAIN_ONLY |
394 VehicleFlag.HOVER_UP_ONLY |
395 VehicleFlag.NO_DEFLECTION_UP |
396 VehicleFlag.LIMIT_MOTOR_UP);
397 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
398 VehicleFlag.HOVER_GLOBAL_HEIGHT);
399 break;
400 }
401 }
402 public void SetVehicle(PhysicsActor ph)
403 {
404 if (ph == null)
405 return;
406 ph.SetVehicle(vd);
407 }
408
409 private XmlTextWriter writer;
410
411 private void XWint(string name, int i)
412 {
413 writer.WriteElementString(name, i.ToString());
414 }
415
416 private void XWfloat(string name, float f)
417 {
418 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
419 }
420
421 private void XWVector(string name, Vector3 vec)
422 {
423 writer.WriteStartElement(name);
424 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
426 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
427 writer.WriteEndElement();
428 }
429
430 private void XWQuat(string name, Quaternion quat)
431 {
432 writer.WriteStartElement(name);
433 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
436 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
437 writer.WriteEndElement();
438 }
439
440 public void ToXml2(XmlTextWriter twriter)
441 {
442 writer = twriter;
443 writer.WriteStartElement("Vehicle");
444
445 XWint("TYPE", (int)vd.m_type);
446 XWint("FLAGS", (int)vd.m_flags);
447
448 // Linear properties
449 XWVector("LMDIR", vd.m_linearMotorDirection);
450 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
451 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
452 XWfloat("LMTIME", vd.m_linearMotorTimescale);
453 XWVector("LMOFF", vd.m_linearMotorOffset);
454
455 //Angular properties
456 XWVector("AMDIR", vd.m_angularMotorDirection);
457 XWfloat("AMTIME", vd.m_angularMotorTimescale);
458 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
459 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
460
461 //Deflection properties
462 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
463 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
464 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
465 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
466
467 //Banking properties
468 XWfloat("BEFF", vd.m_bankingEfficiency);
469 XWfloat("BMIX", vd.m_bankingMix);
470 XWfloat("BTIME", vd.m_bankingTimescale);
471
472 //Hover and Buoyancy properties
473 XWfloat("HHEI", vd.m_VhoverHeight);
474 XWfloat("HEFF", vd.m_VhoverEfficiency);
475 XWfloat("HTIME", vd.m_VhoverTimescale);
476 XWfloat("VBUO", vd.m_VehicleBuoyancy);
477
478 //Attractor properties
479 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
480 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
481
482 XWQuat("REF_FRAME", vd.m_referenceFrame);
483
484 writer.WriteEndElement();
485 writer = null;
486 }
487
488
489
490 XmlReader reader;
491
492 private int XRint()
493 {
494 return reader.ReadElementContentAsInt();
495 }
496
497 private float XRfloat()
498 {
499 return reader.ReadElementContentAsFloat();
500 }
501
502 public Vector3 XRvector()
503 {
504 Vector3 vec;
505 reader.ReadStartElement();
506 vec.X = reader.ReadElementContentAsFloat();
507 vec.Y = reader.ReadElementContentAsFloat();
508 vec.Z = reader.ReadElementContentAsFloat();
509 reader.ReadEndElement();
510 return vec;
511 }
512
513 public Quaternion XRquat()
514 {
515 Quaternion q;
516 reader.ReadStartElement();
517 q.X = reader.ReadElementContentAsFloat();
518 q.Y = reader.ReadElementContentAsFloat();
519 q.Z = reader.ReadElementContentAsFloat();
520 q.W = reader.ReadElementContentAsFloat();
521 reader.ReadEndElement();
522 return q;
523 }
524
525 public static bool EReadProcessors(
526 Dictionary<string, Action> processors,
527 XmlReader xtr)
528 {
529 bool errors = false;
530
531 string nodeName = string.Empty;
532 while (xtr.NodeType != XmlNodeType.EndElement)
533 {
534 nodeName = xtr.Name;
535
536 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
537
538 Action p = null;
539 if (processors.TryGetValue(xtr.Name, out p))
540 {
541 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
542
543 try
544 {
545 p();
546 }
547 catch (Exception e)
548 {
549 errors = true;
550 if (xtr.NodeType == XmlNodeType.EndElement)
551 xtr.Read();
552 }
553 }
554 else
555 {
556 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
557 xtr.ReadOuterXml(); // ignore
558 }
559 }
560
561 return errors;
562 }
563
564
565 public string ToXml2()
566 {
567 using (StringWriter sw = new StringWriter())
568 {
569 using (XmlTextWriter xwriter = new XmlTextWriter(sw))
570 {
571 ToXml2(xwriter);
572 }
573
574 return sw.ToString();
575 }
576 }
577
578 public static SOPVehicle FromXml2(string text)
579 {
580 if (text == String.Empty)
581 return null;
582
583 UTF8Encoding enc = new UTF8Encoding();
584 MemoryStream ms = new MemoryStream(enc.GetBytes(text));
585 XmlTextReader xreader = new XmlTextReader(ms);
586
587 SOPVehicle v = new SOPVehicle();
588 bool error;
589
590 v.FromXml2(xreader, out error);
591
592 xreader.Close();
593
594 if (error)
595 {
596 v = null;
597 return null;
598 }
599 return v;
600 }
601
602 public static SOPVehicle FromXml2(XmlReader reader)
603 {
604 SOPVehicle vehicle = new SOPVehicle();
605
606 bool errors = false;
607
608 vehicle.FromXml2(reader, out errors);
609 if (errors)
610 return null;
611
612 return vehicle;
613 }
614
615 private void FromXml2(XmlReader _reader, out bool errors)
616 {
617 errors = false;
618 reader = _reader;
619
620 Dictionary<string, Action> m_VehicleXmlProcessors
621 = new Dictionary<string, Action>();
622
623 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
624 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
625
626 // Linear properties
627 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
628 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
629 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
630 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
631 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
632
633 //Angular properties
634 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
635 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
636 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
637 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
638
639 //Deflection properties
640 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
641 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
642 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
643 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
644
645 //Banking properties
646 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
647 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
648 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
649
650 //Hover and Buoyancy properties
651 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
652 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
653 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
654
655 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
656
657 //Attractor properties
658 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
659 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
660
661 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
662
663 vd = new VehicleData();
664
665 reader.ReadStartElement("Vehicle", String.Empty);
666
667 errors = EReadProcessors(
668 m_VehicleXmlProcessors,
669 reader);
670
671 reader.ReadEndElement();
672 reader = null;
673 }
674
675 private void ProcessXR_type()
676 {
677 vd.m_type = (Vehicle)XRint();
678 }
679 private void ProcessXR_flags()
680 {
681 vd.m_flags = (VehicleFlag)XRint();
682 }
683 // Linear properties
684 private void ProcessXR_linearMotorDirection()
685 {
686 vd.m_linearMotorDirection = XRvector();
687 }
688
689 private void ProcessXR_linearFrictionTimescale()
690 {
691 vd.m_linearFrictionTimescale = XRvector();
692 }
693
694 private void ProcessXR_linearMotorDecayTimescale()
695 {
696 vd.m_linearMotorDecayTimescale = XRfloat();
697 }
698 private void ProcessXR_linearMotorTimescale()
699 {
700 vd.m_linearMotorTimescale = XRfloat();
701 }
702 private void ProcessXR_linearMotorOffset()
703 {
704 vd.m_linearMotorOffset = XRvector();
705 }
706
707
708 //Angular properties
709 private void ProcessXR_angularMotorDirection()
710 {
711 vd.m_angularMotorDirection = XRvector();
712 }
713 private void ProcessXR_angularMotorTimescale()
714 {
715 vd.m_angularMotorTimescale = XRfloat();
716 }
717 private void ProcessXR_angularMotorDecayTimescale()
718 {
719 vd.m_angularMotorDecayTimescale = XRfloat();
720 }
721 private void ProcessXR_angularFrictionTimescale()
722 {
723 vd.m_angularFrictionTimescale = XRvector();
724 }
725
726 //Deflection properties
727 private void ProcessXR_angularDeflectionEfficiency()
728 {
729 vd.m_angularDeflectionEfficiency = XRfloat();
730 }
731 private void ProcessXR_angularDeflectionTimescale()
732 {
733 vd.m_angularDeflectionTimescale = XRfloat();
734 }
735 private void ProcessXR_linearDeflectionEfficiency()
736 {
737 vd.m_linearDeflectionEfficiency = XRfloat();
738 }
739 private void ProcessXR_linearDeflectionTimescale()
740 {
741 vd.m_linearDeflectionTimescale = XRfloat();
742 }
743
744 //Banking properties
745 private void ProcessXR_bankingEfficiency()
746 {
747 vd.m_bankingEfficiency = XRfloat();
748 }
749 private void ProcessXR_bankingMix()
750 {
751 vd.m_bankingMix = XRfloat();
752 }
753 private void ProcessXR_bankingTimescale()
754 {
755 vd.m_bankingTimescale = XRfloat();
756 }
757
758 //Hover and Buoyancy properties
759 private void ProcessXR_VhoverHeight()
760 {
761 vd.m_VhoverHeight = XRfloat();
762 }
763 private void ProcessXR_VhoverEfficiency()
764 {
765 vd.m_VhoverEfficiency = XRfloat();
766 }
767 private void ProcessXR_VhoverTimescale()
768 {
769 vd.m_VhoverTimescale = XRfloat();
770 }
771
772 private void ProcessXR_VehicleBuoyancy()
773 {
774 vd.m_VehicleBuoyancy = XRfloat();
775 }
776
777 //Attractor properties
778 private void ProcessXR_verticalAttractionEfficiency()
779 {
780 vd.m_verticalAttractionEfficiency = XRfloat();
781 }
782 private void ProcessXR_verticalAttractionTimescale()
783 {
784 vd.m_verticalAttractionTimescale = XRfloat();
785 }
786
787 private void ProcessXR_referenceFrame()
788 {
789 vd.m_referenceFrame = XRquat();
790 }
791 }
792}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index b838177..edb881f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -106,12 +106,12 @@ namespace OpenSim.Region.Framework.Scenes
106 engine.StartProcessing(); 106 engine.StartProcessing();
107 } 107 }
108 108
109 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) 109 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item, uint cost)
110 { 110 {
111 IMoneyModule money = RequestModuleInterface<IMoneyModule>(); 111 IMoneyModule money = RequestModuleInterface<IMoneyModule>();
112 if (money != null) 112 if (money != null)
113 { 113 {
114 money.ApplyUploadCharge(agentID, money.UploadCharge, "Asset upload"); 114 money.ApplyUploadCharge(agentID, (int)cost, "Asset upload");
115 } 115 }
116 116
117 AddInventoryItem(item); 117 AddInventoryItem(item);
@@ -182,7 +182,7 @@ namespace OpenSim.Region.Framework.Scenes
182 return false; 182 return false;
183 } 183 }
184 } 184 }
185 185
186 if (InventoryService.AddItem(item)) 186 if (InventoryService.AddItem(item))
187 { 187 {
188 int userlevel = 0; 188 int userlevel = 0;
@@ -338,8 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
338 338
339 // Update item with new asset 339 // Update item with new asset
340 item.AssetID = asset.FullID; 340 item.AssetID = asset.FullID;
341 if (group.UpdateInventoryItem(item)) 341 group.UpdateInventoryItem(item);
342 remoteClient.SendAlertMessage("Script saved");
343 342
344 part.SendPropertiesToClient(remoteClient); 343 part.SendPropertiesToClient(remoteClient);
345 344
@@ -350,12 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
350 { 349 {
351 // Needs to determine which engine was running it and use that 350 // Needs to determine which engine was running it and use that
352 // 351 //
353 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 352 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1);
354 errors = part.Inventory.GetScriptErrors(item.ItemID);
355 }
356 else
357 {
358 remoteClient.SendAlertMessage("Script saved");
359 } 353 }
360 354
361 // Tell anyone managing scripts that a script has been reloaded/changed 355 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -421,6 +415,7 @@ namespace OpenSim.Region.Framework.Scenes
421 if (item.Owner != remoteClient.AgentId) 415 if (item.Owner != remoteClient.AgentId)
422 return; 416 return;
423 417
418 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
424 item.Name = itemUpd.Name; 419 item.Name = itemUpd.Name;
425 item.Description = itemUpd.Description; 420 item.Description = itemUpd.Description;
426 421
@@ -889,6 +884,20 @@ namespace OpenSim.Region.Framework.Scenes
889 if (newName == String.Empty) 884 if (newName == String.Empty)
890 newName = item.Name; 885 newName = item.Name;
891 886
887 AssetBase asset = AssetService.Get(item.AssetID.ToString());
888
889 if (asset != null)
890 {
891 if (newName != String.Empty)
892 {
893 asset.Name = newName;
894 }
895 else
896 {
897 newName = item.Name;
898 }
899
900
892 if (remoteClient.AgentId == oldAgentID 901 if (remoteClient.AgentId == oldAgentID
893 || (LibraryService != null 902 || (LibraryService != null
894 && LibraryService.LibraryRootFolder != null 903 && LibraryService.LibraryRootFolder != null
@@ -915,6 +924,13 @@ namespace OpenSim.Region.Framework.Scenes
915 } 924 }
916 } 925 }
917 } 926 }
927 else
928 {
929 m_log.ErrorFormat(
930 "[AGENT INVENTORY]: Could not copy item {0} since asset {1} could not be found",
931 item.Name, item.AssetID);
932 }
933 }
918 934
919 /// <summary> 935 /// <summary>
920 /// Create a new asset data structure. 936 /// Create a new asset data structure.
@@ -929,6 +945,24 @@ namespace OpenSim.Region.Framework.Scenes
929 } 945 }
930 946
931 /// <summary> 947 /// <summary>
948 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
949 /// </summary>
950 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
951 {
952 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
953 foreach (InventoryItemBase b in items)
954 {
955 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
956 InventoryItemBase n = InventoryService.GetItem(b);
957 n.Folder = destfolder;
958 moveitems.Add(n);
959 remoteClient.SendInventoryItemCreateUpdate(n, 0);
960 }
961
962 MoveInventoryItem(remoteClient, moveitems);
963 }
964
965 /// <summary>
932 /// Move an item within the agent's inventory. 966 /// Move an item within the agent's inventory.
933 /// </summary> 967 /// </summary>
934 /// <param name="remoteClient"></param> 968 /// <param name="remoteClient"></param>
@@ -1015,7 +1049,11 @@ namespace OpenSim.Region.Framework.Scenes
1015 item.BasePermissions = baseMask; 1049 item.BasePermissions = baseMask;
1016 item.CreationDate = creationDate; 1050 item.CreationDate = creationDate;
1017 1051
1018 if (AddInventoryItem(item, assetUpload)) 1052 // special AnimationSet case
1053 if (item.InvType == (int)CustomInventoryType.AnimationSet)
1054 AnimationSet.enforceItemPermitions(item,true);
1055
1056 if (AddInventoryItem(item))
1019 { 1057 {
1020 remoteClient.SendInventoryItemCreateUpdate(item, callbackID); 1058 remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
1021 } 1059 }
@@ -1327,6 +1365,10 @@ namespace OpenSim.Region.Framework.Scenes
1327 { 1365 {
1328 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1366 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1329 1367
1368 // Can't move a null item
1369 if (itemId == UUID.Zero)
1370 return;
1371
1330 if (null == part) 1372 if (null == part)
1331 { 1373 {
1332 m_log.WarnFormat( 1374 m_log.WarnFormat(
@@ -1437,21 +1479,28 @@ namespace OpenSim.Region.Framework.Scenes
1437 return; 1479 return;
1438 } 1480 }
1439 1481
1440 if (part.OwnerID != destPart.OwnerID) 1482 // Can't transfer this
1483 //
1484 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1485 return;
1486
1487 bool overrideNoMod = false;
1488 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1489 overrideNoMod = true;
1490
1491 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1441 { 1492 {
1442 // Source must have transfer permissions 1493 // object cannot copy items to an object owned by a different owner
1443 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1494 // unless llAllowInventoryDrop has been called
1444 return;
1445 1495
1446 // Object cannot copy items to an object owned by a different owner 1496 return;
1447 // unless llAllowInventoryDrop has been called on the destination
1448 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1449 return;
1450 } 1497 }
1451 1498
1452 // must have both move and modify permission to put an item in an object 1499 // must have both move and modify permission to put an item in an object
1453 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1500 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1501 {
1454 return; 1502 return;
1503 }
1455 1504
1456 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1505 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1457 1506
@@ -1507,10 +1556,20 @@ namespace OpenSim.Region.Framework.Scenes
1507 1556
1508 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1557 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1509 { 1558 {
1559
1510 ScenePresence avatar; 1560 ScenePresence avatar;
1511 IClientAPI remoteClient = null; 1561 IClientAPI remoteClient = null;
1512 if (TryGetScenePresence(destID, out avatar)) 1562 if (TryGetScenePresence(destID, out avatar))
1513 remoteClient = avatar.ControllingClient; 1563 remoteClient = avatar.ControllingClient;
1564// ????
1565 SceneObjectPart destPart = GetSceneObjectPart(destID);
1566 if (destPart != null) // Move into a prim
1567 {
1568 foreach(UUID itemID in items)
1569 MoveTaskInventoryItem(destID, host, itemID);
1570 return destID; // Prim folder ID == prim ID
1571 }
1572// /????
1514 1573
1515 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1574 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1516 1575
@@ -1696,12 +1755,12 @@ namespace OpenSim.Region.Framework.Scenes
1696 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( 1755 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1697 remoteClient, part, transactionID, currentItem); 1756 remoteClient, part, transactionID, currentItem);
1698 1757
1699 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1758// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1700 remoteClient.SendAlertMessage("Notecard saved"); 1759// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1701 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1760// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1702 remoteClient.SendAlertMessage("Script saved"); 1761// remoteClient.SendAgentAlertMessage("Script saved", false);
1703 else 1762// else
1704 remoteClient.SendAlertMessage("Item saved"); 1763// remoteClient.SendAgentAlertMessage("Item saved", false);
1705 } 1764 }
1706 1765
1707 // Base ALWAYS has move 1766 // Base ALWAYS has move
@@ -2075,7 +2134,8 @@ namespace OpenSim.Region.Framework.Scenes
2075 // build a list of eligible objects 2134 // build a list of eligible objects
2076 List<uint> deleteIDs = new List<uint>(); 2135 List<uint> deleteIDs = new List<uint>();
2077 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 2136 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
2078 2137 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
2138
2079 // Start with true for both, then remove the flags if objects 2139 // Start with true for both, then remove the flags if objects
2080 // that we can't derez are part of the selection 2140 // that we can't derez are part of the selection
2081 bool permissionToTake = true; 2141 bool permissionToTake = true;
@@ -2084,14 +2144,24 @@ namespace OpenSim.Region.Framework.Scenes
2084 2144
2085 foreach (uint localID in localIDs) 2145 foreach (uint localID in localIDs)
2086 { 2146 {
2147
2148
2087 // Invalid id 2149 // Invalid id
2088 SceneObjectPart part = GetSceneObjectPart(localID); 2150 SceneObjectPart part = GetSceneObjectPart(localID);
2089 if (part == null) 2151 if (part == null)
2152 {
2153 //Client still thinks the object exists, kill it
2154 deleteIDs.Add(localID);
2090 continue; 2155 continue;
2156 }
2091 2157
2092 // Already deleted by someone else 2158 // Already deleted by someone else
2093 if (part.ParentGroup.IsDeleted) 2159 if (part.ParentGroup.IsDeleted)
2160 {
2161 //Client still thinks the object exists, kill it
2162 deleteIDs.Add(localID);
2094 continue; 2163 continue;
2164 }
2095 2165
2096 // Can't delete child prims 2166 // Can't delete child prims
2097 if (part != part.ParentGroup.RootPart) 2167 if (part != part.ParentGroup.RootPart)
@@ -2099,9 +2169,6 @@ namespace OpenSim.Region.Framework.Scenes
2099 2169
2100 SceneObjectGroup grp = part.ParentGroup; 2170 SceneObjectGroup grp = part.ParentGroup;
2101 2171
2102 deleteIDs.Add(localID);
2103 deleteGroups.Add(grp);
2104
2105 // If child prims have invalid perms, fix them 2172 // If child prims have invalid perms, fix them
2106 grp.AdjustChildPrimPermissions(false); 2173 grp.AdjustChildPrimPermissions(false);
2107 2174
@@ -2121,87 +2188,191 @@ namespace OpenSim.Region.Framework.Scenes
2121 } 2188 }
2122 else 2189 else
2123 { 2190 {
2124 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 2191 if (action == DeRezAction.TakeCopy)
2192 {
2193 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
2194 permissionToTakeCopy = false;
2195 }
2196 else
2197 {
2125 permissionToTakeCopy = false; 2198 permissionToTakeCopy = false;
2126 2199 }
2127 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 2200 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
2128 permissionToTake = false; 2201 permissionToTake = false;
2129 2202
2130 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 2203 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
2131 permissionToDelete = false; 2204 permissionToDelete = false;
2132 } 2205 }
2133 }
2134 2206
2135 // Handle god perms 2207 // Handle god perms
2136 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 2208 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
2137 {
2138 permissionToTake = true;
2139 permissionToTakeCopy = true;
2140 permissionToDelete = true;
2141 }
2142
2143 // If we're re-saving, we don't even want to delete
2144 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2145 permissionToDelete = false;
2146
2147 // if we want to take a copy, we also don't want to delete
2148 // Note: after this point, the permissionToTakeCopy flag
2149 // becomes irrelevant. It already includes the permissionToTake
2150 // permission and after excluding no copy items here, we can
2151 // just use that.
2152 if (action == DeRezAction.TakeCopy)
2153 {
2154 // If we don't have permission, stop right here
2155 if (!permissionToTakeCopy)
2156 { 2209 {
2157 remoteClient.SendAlertMessage("You don't have permission to take the object"); 2210 permissionToTake = true;
2158 return; 2211 permissionToTakeCopy = true;
2212 permissionToDelete = true;
2159 } 2213 }
2160 2214
2161 permissionToTake = true; 2215 // If we're re-saving, we don't even want to delete
2162 // Don't delete 2216 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2163 permissionToDelete = false; 2217 permissionToDelete = false;
2164 }
2165 2218
2166 if (action == DeRezAction.Return) 2219 // if we want to take a copy, we also don't want to delete
2167 { 2220 // Note: after this point, the permissionToTakeCopy flag
2168 if (remoteClient != null) 2221 // becomes irrelevant. It already includes the permissionToTake
2222 // permission and after excluding no copy items here, we can
2223 // just use that.
2224 if (action == DeRezAction.TakeCopy)
2169 { 2225 {
2170 if (Permissions.CanReturnObjects( 2226 // If we don't have permission, stop right here
2171 null, 2227 if (!permissionToTakeCopy)
2172 remoteClient.AgentId,
2173 deleteGroups))
2174 { 2228 {
2175 permissionToTake = true; 2229 remoteClient.SendAlertMessage("You don't have permission to take the object");
2176 permissionToDelete = true; 2230 return;
2231 }
2177 2232
2178 foreach (SceneObjectGroup g in deleteGroups) 2233 permissionToTake = true;
2234 // Don't delete
2235 permissionToDelete = false;
2236 }
2237
2238 if (action == DeRezAction.Return)
2239 {
2240 if (remoteClient != null)
2241 {
2242 if (Permissions.CanReturnObjects(
2243 null,
2244 remoteClient.AgentId,
2245 new List<SceneObjectGroup>() {grp}))
2179 { 2246 {
2180 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2247 permissionToTake = true;
2248 permissionToDelete = true;
2249
2250 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
2181 } 2251 }
2182 } 2252 }
2253 else // Auto return passes through here with null agent
2254 {
2255 permissionToTake = true;
2256 permissionToDelete = true;
2257 }
2183 } 2258 }
2184 else // Auto return passes through here with null agent 2259
2260 if (permissionToTake && (!permissionToDelete))
2261 takeGroups.Add(grp);
2262
2263 if (permissionToDelete)
2185 { 2264 {
2186 permissionToTake = true; 2265 if (permissionToTake)
2187 permissionToDelete = true; 2266 deleteGroups.Add(grp);
2267 deleteIDs.Add(grp.LocalId);
2188 } 2268 }
2189 } 2269 }
2190 2270
2191 // OK, we're done with permissions. Let's check if any part of the code prevents the objects from being deleted 2271 SendKillObject(deleteIDs);
2192 bool canDelete = EventManager.TriggerDeRezRequested(remoteClient, deleteGroups, action);
2193 2272
2194 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) 2273 if (deleteGroups.Count > 0)
2195 { 2274 {
2275 foreach (SceneObjectGroup g in deleteGroups)
2276 deleteIDs.Remove(g.LocalId);
2277
2196 m_asyncSceneObjectDeleter.DeleteToInventory( 2278 m_asyncSceneObjectDeleter.DeleteToInventory(
2197 action, destinationID, deleteGroups, remoteClient, 2279 action, destinationID, deleteGroups, remoteClient,
2198 permissionToDelete && canDelete); 2280 true);
2199 } 2281 }
2200 else if (permissionToDelete && canDelete) 2282 if (takeGroups.Count > 0)
2283 {
2284 m_asyncSceneObjectDeleter.DeleteToInventory(
2285 action, destinationID, takeGroups, remoteClient,
2286 false);
2287 }
2288 if (deleteIDs.Count > 0)
2201 { 2289 {
2202 foreach (SceneObjectGroup g in deleteGroups) 2290 foreach (SceneObjectGroup g in deleteGroups)
2203 DeleteSceneObject(g, false); 2291 DeleteSceneObject(g, true);
2292 }
2293 }
2294
2295 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2296 {
2297 itemID = UUID.Zero;
2298 if (grp != null)
2299 {
2300 Vector3 inventoryStoredPosition = new Vector3(
2301 Math.Min(grp.AbsolutePosition.X, RegionInfo.RegionSizeX - 6),
2302 Math.Min(grp.AbsolutePosition.Y, RegionInfo.RegionSizeY - 6),
2303 grp.AbsolutePosition.Z);
2304
2305 Vector3 originalPosition = grp.AbsolutePosition;
2306
2307 grp.AbsolutePosition = inventoryStoredPosition;
2308
2309 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2310
2311 grp.AbsolutePosition = originalPosition;
2312
2313 AssetBase asset = CreateAsset(
2314 grp.GetPartName(grp.LocalId),
2315 grp.GetPartDescription(grp.LocalId),
2316 (sbyte)AssetType.Object,
2317 Utils.StringToBytes(sceneObjectXml),
2318 remoteClient.AgentId);
2319 AssetService.Store(asset);
2320
2321 InventoryItemBase item = new InventoryItemBase();
2322 item.CreatorId = grp.RootPart.CreatorID.ToString();
2323 item.CreatorData = grp.RootPart.CreatorData;
2324 item.Owner = remoteClient.AgentId;
2325 item.ID = UUID.Random();
2326 item.AssetID = asset.FullID;
2327 item.Description = asset.Description;
2328 item.Name = asset.Name;
2329 item.AssetType = asset.Type;
2330 item.InvType = (int)InventoryType.Object;
2331
2332 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, FolderType.Object);
2333 if (folder != null)
2334 item.Folder = folder.ID;
2335 else // oopsies
2336 item.Folder = UUID.Zero;
2337
2338 // Set up base perms properly
2339 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2340 permsBase &= grp.RootPart.BaseMask;
2341 permsBase |= (uint)PermissionMask.Move;
2342
2343 // Make sure we don't lock it
2344 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2345
2346 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2347 {
2348 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2349 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2350 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2351 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2352 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2353 }
2354 else
2355 {
2356 item.BasePermissions = permsBase;
2357 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2358 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2359 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2360 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2361 }
2362 item.CreationDate = Util.UnixTimeSinceEpoch();
2363
2364 // sets itemID so client can show item as 'attached' in inventory
2365 grp.FromItemID = item.ID;
2366
2367 if (AddInventoryItem(item))
2368 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2369 else
2370 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2371
2372 itemID = item.ID;
2373 return item.AssetID;
2204 } 2374 }
2375 return UUID.Zero;
2205 } 2376 }
2206 2377
2207 /// <summary> 2378 /// <summary>
@@ -2254,7 +2425,7 @@ namespace OpenSim.Region.Framework.Scenes
2254 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); 2425 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData);
2255 g = null; 2426 g = null;
2256 } 2427 }
2257 2428
2258 if (g != null) 2429 if (g != null)
2259 { 2430 {
2260 objlist.Add(g); 2431 objlist.Add(g);
@@ -2265,7 +2436,7 @@ namespace OpenSim.Region.Framework.Scenes
2265 return true; 2436 return true;
2266 } 2437 }
2267 else 2438 else
2268 { 2439 {
2269 XmlDocument doc = new XmlDocument(); 2440 XmlDocument doc = new XmlDocument();
2270 doc.LoadXml(xmlData); 2441 doc.LoadXml(xmlData);
2271 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); 2442 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
@@ -2371,7 +2542,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 2542 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2372 BypassRayCast, bRayEndIsIntersection, true, scale, false); 2543 BypassRayCast, bRayEndIsIntersection, true, scale, false);
2373 2544
2374 RezObject(part, item, pos, null, Vector3.Zero, 0); 2545 RezObject(part, item, pos, null, Vector3.Zero, 0, false);
2375 } 2546 }
2376 } 2547 }
2377 2548
@@ -2387,15 +2558,18 @@ namespace OpenSim.Region.Framework.Scenes
2387 /// <param name="param"></param> 2558 /// <param name="param"></param>
2388 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns> 2559 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2389 public virtual List<SceneObjectGroup> RezObject( 2560 public virtual List<SceneObjectGroup> RezObject(
2390 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2561 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param, bool atRoot)
2391 { 2562 {
2392 if (null == item) 2563 if (null == item)
2393 return null; 2564 return null;
2394 2565
2395 List<SceneObjectGroup> objlist; 2566 List<SceneObjectGroup> objlist;
2396 List<Vector3> veclist; 2567 List<Vector3> veclist;
2397 2568 Vector3 bbox;
2398 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); 2569 float offsetHeight;
2570
2571 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist,out bbox, out offsetHeight);
2572
2399 if (!success) 2573 if (!success)
2400 return null; 2574 return null;
2401 2575
@@ -2412,10 +2586,69 @@ namespace OpenSim.Region.Framework.Scenes
2412 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2586 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2413 } 2587 }
2414 2588
2589 SceneObjectGroup sog;
2590
2591 bool fixrot = false;
2592 Quaternion netRot = Quaternion.Identity;
2593
2594 // position adjust
2595 if (totalPrims > 1) // nothing to do on a single prim
2596 {
2597 if (objlist.Count == 1)
2598 {
2599 // current object position is root position
2600 if(!atRoot)
2601 {
2602 sog = objlist[0];
2603 Quaternion orot;
2604 if (rot == null)
2605 orot = sog.RootPart.GetWorldRotation();
2606 else
2607 orot = rot.Value;
2608 // possible should be bbox, but geometric center looks better
2609 Vector3 off = sog.GetGeometricCenter();
2610// Vector3 off = bbox * 0.5f;
2611 off *= orot;
2612 pos -= off;
2613 }
2614 }
2615 else
2616 {
2617 //veclist[] are relative to bbox corner with min X,Y and Z
2618 // rez at root, and rot will be referenced to first object in list
2619 if (rot == null)
2620 {
2621 // use original rotations
2622 if (atRoot)
2623 pos -= veclist[0];
2624 else
2625 pos -= bbox / 2;
2626 }
2627 else
2628 {
2629 fixrot = true;
2630 sog = objlist[0];
2631 netRot = Quaternion.Conjugate(sog.RootPart.GetWorldRotation());
2632 netRot = netRot * rot.Value;
2633 Vector3 off;
2634 if (atRoot)
2635 off = veclist[0];
2636 else
2637 off = bbox / 2;
2638 off *= netRot;
2639 pos -= off;
2640 }
2641 }
2642 }
2643
2415 for (int i = 0; i < objlist.Count; i++) 2644 for (int i = 0; i < objlist.Count; i++)
2416 { 2645 {
2417 SceneObjectGroup group = objlist[i]; 2646 SceneObjectGroup group = objlist[i];
2418 Vector3 curpos = pos + veclist[i]; 2647 Vector3 curpos;
2648 if(fixrot)
2649 curpos = pos + veclist[i] * netRot;
2650 else
2651 curpos = pos + veclist[i];
2419 2652
2420 if (group.IsAttachment == false && group.RootPart.Shape.State != 0) 2653 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2421 { 2654 {
@@ -2424,7 +2657,17 @@ namespace OpenSim.Region.Framework.Scenes
2424 } 2657 }
2425 2658
2426 group.FromPartID = sourcePart.UUID; 2659 group.FromPartID = sourcePart.UUID;
2427 AddNewSceneObject(group, true, curpos, rot, vel); 2660 if( i == 0)
2661 AddNewSceneObject(group, true, curpos, rot, vel);
2662 else
2663 {
2664 Quaternion crot = objlist[i].RootPart.GetWorldRotation();
2665 if (fixrot)
2666 {
2667 crot *= netRot;
2668 }
2669 AddNewSceneObject(group, true, curpos, crot, vel);
2670 }
2428 2671
2429 // We can only call this after adding the scene object, since the scene object references the scene 2672 // We can only call this after adding the scene object, since the scene object references the scene
2430 // to find out if scripts should be activated at all. 2673 // to find out if scripts should be activated at all.
@@ -2455,6 +2698,9 @@ namespace OpenSim.Region.Framework.Scenes
2455 2698
2456 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2699 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2457 { 2700 {
2701 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2702 return;
2703
2458 SceneObjectPart part = GetSceneObjectPart(objectID); 2704 SceneObjectPart part = GetSceneObjectPart(objectID);
2459 if (part == null) 2705 if (part == null)
2460 return; 2706 return;
@@ -2511,7 +2757,10 @@ namespace OpenSim.Region.Framework.Scenes
2511 } 2757 }
2512 else 2758 else
2513 { 2759 {
2514 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) 2760 if (!Permissions.IsGod(remoteClient.AgentId) && sog.OwnerID != remoteClient.AgentId)
2761 continue;
2762
2763 if (!Permissions.CanTransferObject(sog.UUID, groupID))
2515 continue; 2764 continue;
2516 2765
2517 if (sog.GroupID != groupID) 2766 if (sog.GroupID != groupID)
@@ -2622,7 +2871,18 @@ namespace OpenSim.Region.Framework.Scenes
2622 return; 2871 return;
2623 } 2872 }
2624 2873
2874 bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0;
2625 m_sceneGraph.LinkObjects(root, children); 2875 m_sceneGraph.LinkObjects(root, children);
2876
2877 ScenePresence sp;
2878 if (TryGetScenePresence(agentId, out sp))
2879 {
2880 root.SendPropertiesToClient(sp.ControllingClient);
2881 if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0)
2882 {
2883 sp.ControllingClient.SendAlertMessage("Object physics canceled");
2884 }
2885 }
2626 } 2886 }
2627 2887
2628 private string PermissionString(uint permissions) 2888 private string PermissionString(uint permissions)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 8ebcd92..0b0e458 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 /// <param name='targetID'></param> 49 /// <param name='targetID'></param>
50 /// <param name='fromAgent'></param> 50 /// <param name='fromAgent'></param>
51 /// <param name='broadcast'></param> 51 /// <param name='broadcast'></param>
52 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 52 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
53 UUID fromID, UUID targetID, bool fromAgent, bool broadcast) 53 UUID fromID, UUID targetID, bool fromAgent, bool broadcast)
54 { 54 {
55 OSChatMessage args = new OSChatMessage(); 55 OSChatMessage args = new OSChatMessage();
@@ -60,6 +60,7 @@ namespace OpenSim.Region.Framework.Scenes
60 args.Position = fromPos; 60 args.Position = fromPos;
61 args.SenderUUID = fromID; 61 args.SenderUUID = fromID;
62 args.Scene = this; 62 args.Scene = this;
63 args.Destination = targetID;
63 64
64 if (fromAgent) 65 if (fromAgent)
65 { 66 {
@@ -74,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
74 } 75 }
75 76
76 args.From = fromName; 77 args.From = fromName;
77 args.TargetUUID = targetID; 78 //args.
78 79
79// m_log.DebugFormat( 80// m_log.DebugFormat(
80// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", 81// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}",
@@ -85,7 +86,7 @@ namespace OpenSim.Region.Framework.Scenes
85 else 86 else
86 EventManager.TriggerOnChatFromWorld(this, args); 87 EventManager.TriggerOnChatFromWorld(this, args);
87 } 88 }
88 89
89 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 90 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
90 UUID fromID, bool fromAgent, bool broadcast) 91 UUID fromID, bool fromAgent, bool broadcast)
91 { 92 {
@@ -129,19 +130,6 @@ namespace OpenSim.Region.Framework.Scenes
129 { 130 {
130 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true); 131 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true);
131 } 132 }
132 /// <summary>
133 ///
134 /// </summary>
135 /// <param name="message"></param>
136 /// <param name="type"></param>
137 /// <param name="fromPos"></param>
138 /// <param name="fromName"></param>
139 /// <param name="fromAgentID"></param>
140 /// <param name="targetID"></param>
141 public void SimChatToAgent(UUID targetID, byte[] message, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent)
142 {
143 SimChat(message, ChatTypeEnum.Say, 0, fromPos, fromName, fromID, targetID, fromAgent, false);
144 }
145 133
146 /// <summary> 134 /// <summary>
147 /// 135 ///
@@ -178,27 +166,47 @@ namespace OpenSim.Region.Framework.Scenes
178 /// <param name="remoteClient"></param> 166 /// <param name="remoteClient"></param>
179 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 167 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
180 { 168 {
169 /*
170 SceneObjectPart part = GetSceneObjectPart(primLocalID);
171
172 if (null == part)
173 return;
174
175 if (part.IsRoot)
176 {
177 SceneObjectGroup sog = part.ParentGroup;
178 sog.SendPropertiesToClient(remoteClient);
179
180 // A prim is only tainted if it's allowed to be edited by the person clicking it.
181 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
182 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
183 {
184 sog.IsSelected = true;
185 EventManager.TriggerParcelPrimCountTainted();
186 }
187 }
188 else
189 {
190 part.SendPropertiesToClient(remoteClient);
191 }
192 */
181 SceneObjectPart part = GetSceneObjectPart(primLocalID); 193 SceneObjectPart part = GetSceneObjectPart(primLocalID);
182 194
183 if (null == part) 195 if (null == part)
184 return; 196 return;
185 197
186 if (part.IsRoot) 198 SceneObjectGroup sog = part.ParentGroup;
187 { 199 if (sog == null)
188 SceneObjectGroup sog = part.ParentGroup; 200 return;
189 sog.SendPropertiesToClient(remoteClient);
190 sog.IsSelected = true;
191 201
192 // A prim is only tainted if it's allowed to be edited by the person clicking it. 202 part.SendPropertiesToClient(remoteClient);
193 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 203
194 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 204 // A prim is only tainted if it's allowed to be edited by the person clicking it.
195 { 205 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
196 EventManager.TriggerParcelPrimCountTainted(); 206 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
197 }
198 }
199 else
200 { 207 {
201 part.SendPropertiesToClient(remoteClient); 208 part.IsSelected = true;
209 EventManager.TriggerParcelPrimCountTainted();
202 } 210 }
203 } 211 }
204 212
@@ -251,7 +259,7 @@ namespace OpenSim.Region.Framework.Scenes
251 SceneObjectPart part = GetSceneObjectPart(primLocalID); 259 SceneObjectPart part = GetSceneObjectPart(primLocalID);
252 if (part == null) 260 if (part == null)
253 return; 261 return;
254 262 /*
255 // A deselect packet contains all the local prims being deselected. However, since selection is still 263 // A deselect packet contains all the local prims being deselected. However, since selection is still
256 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims 264 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
257 // we end up sending many duplicate ObjectUpdates 265 // we end up sending many duplicate ObjectUpdates
@@ -262,7 +270,9 @@ namespace OpenSim.Region.Framework.Scenes
262 // handled by group, but by prim. Legacy cruft. 270 // handled by group, but by prim. Legacy cruft.
263 // TODO: Make selection flagging per prim! 271 // TODO: Make selection flagging per prim!
264 // 272 //
265 part.ParentGroup.IsSelected = false; 273 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
274 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
275 part.ParentGroup.IsSelected = false;
266 276
267 part.ParentGroup.ScheduleGroupForFullUpdate(); 277 part.ParentGroup.ScheduleGroupForFullUpdate();
268 278
@@ -279,6 +289,26 @@ namespace OpenSim.Region.Framework.Scenes
279 part.UUID, remoteClient.AgentId)) 289 part.UUID, remoteClient.AgentId))
280 EventManager.TriggerParcelPrimCountTainted(); 290 EventManager.TriggerParcelPrimCountTainted();
281 } 291 }
292 */
293
294 bool oldgprSelect = part.ParentGroup.IsSelected;
295
296 // This is wrong, wrong, wrong. Selection should not be
297 // handled by group, but by prim. Legacy cruft.
298 // TODO: Make selection flagging per prim!
299 //
300 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
301 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
302 {
303 part.IsSelected = false;
304 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
305 EventManager.TriggerParcelPrimCountTainted();
306 }
307
308 // restore targetOmega
309 if (part.AngularVelocity != Vector3.Zero)
310 part.ScheduleTerseUpdate();
311
282 } 312 }
283 313
284 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 314 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
@@ -433,12 +463,26 @@ namespace OpenSim.Region.Framework.Scenes
433 } 463 }
434 }); 464 });
435 } 465 }
436 466
437 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other) 467 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
438 { 468 {
439 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; 469 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
440 } 470 }
441 471
472 private class DescendentsRequestData
473 {
474 public IClientAPI RemoteClient;
475 public UUID FolderID;
476 public UUID OwnerID;
477 public bool FetchFolders;
478 public bool FetchItems;
479 public int SortOrder;
480 }
481
482 private Queue<DescendentsRequestData> m_descendentsRequestQueue = new Queue<DescendentsRequestData>();
483 private Object m_descendentsRequestLock = new Object();
484 private bool m_descendentsRequestProcessing = false;
485
442 /// <summary> 486 /// <summary>
443 /// Tell the client about the various child items and folders contained in the requested folder. 487 /// Tell the client about the various child items and folders contained in the requested folder.
444 /// </summary> 488 /// </summary>
@@ -475,11 +519,31 @@ namespace OpenSim.Region.Framework.Scenes
475 } 519 }
476 } 520 }
477 521
478 // We're going to send the reply async, because there may be 522 lock (m_descendentsRequestLock)
479 // an enormous quantity of packets -- basically the entire inventory! 523 {
480 // We don't want to block the client thread while all that is happening. 524 if (!m_descendentsRequestProcessing)
481 SendInventoryDelegate d = SendInventoryAsync; 525 {
482 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); 526 m_descendentsRequestProcessing = true;
527
528 // We're going to send the reply async, because there may be
529 // an enormous quantity of packets -- basically the entire inventory!
530 // We don't want to block the client thread while all that is happening.
531 SendInventoryDelegate d = SendInventoryAsync;
532 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d);
533
534 return;
535 }
536
537 DescendentsRequestData req = new DescendentsRequestData();
538 req.RemoteClient = remoteClient;
539 req.FolderID = folderID;
540 req.OwnerID = ownerID;
541 req.FetchFolders = fetchFolders;
542 req.FetchItems = fetchItems;
543 req.SortOrder = sortOrder;
544
545 m_descendentsRequestQueue.Enqueue(req);
546 }
483 } 547 }
484 548
485 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); 549 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
@@ -496,12 +560,28 @@ namespace OpenSim.Region.Framework.Scenes
496 string.Format( 560 string.Format(
497 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e)); 561 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e));
498 } 562 }
563 Thread.Sleep(20);
499 } 564 }
500 565
501 void SendInventoryComplete(IAsyncResult iar) 566 void SendInventoryComplete(IAsyncResult iar)
502 { 567 {
503 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; 568 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState;
504 d.EndInvoke(iar); 569 d.EndInvoke(iar);
570
571 lock (m_descendentsRequestLock)
572 {
573 if (m_descendentsRequestQueue.Count > 0)
574 {
575 DescendentsRequestData req = m_descendentsRequestQueue.Dequeue();
576
577 d = SendInventoryAsync;
578 d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d);
579
580 return;
581 }
582
583 m_descendentsRequestProcessing = false;
584 }
505 } 585 }
506 586
507 /// <summary> 587 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index 535d87a..4d90726 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene); 70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene);
71 public delegate bool IsAdministratorHandler(UUID user); 71 public delegate bool IsAdministratorHandler(UUID user);
72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); 72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene);
73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene); 73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager);
74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene); 74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene);
75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); 75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene);
76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene); 76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene);
@@ -763,7 +763,7 @@ namespace OpenSim.Region.Framework.Scenes
763 763
764 #region EDIT PARCEL 764 #region EDIT PARCEL
765 765
766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p) 766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, bool allowManager)
767 { 767 {
768 EditParcelPropertiesHandler handler = OnEditParcelProperties; 768 EditParcelPropertiesHandler handler = OnEditParcelProperties;
769 if (handler != null) 769 if (handler != null)
@@ -771,7 +771,7 @@ namespace OpenSim.Region.Framework.Scenes
771 Delegate[] list = handler.GetInvocationList(); 771 Delegate[] list = handler.GetInvocationList();
772 foreach (EditParcelPropertiesHandler h in list) 772 foreach (EditParcelPropertiesHandler h in list)
773 { 773 {
774 if (h(user, parcel, p, m_scene) == false) 774 if (h(user, parcel, p, m_scene, allowManager) == false)
775 return false; 775 return false;
776 } 776 }
777 } 777 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index dce2247..05edd20 100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -60,8 +60,7 @@ namespace OpenSim.Region.Framework.Scenes
60 { 60 {
61 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; 61 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
62 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; 62 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
63 63
64 public const int m_defaultNumberFramesStored = 10;
65 64
66 public delegate void SynchronizeSceneHandler(Scene scene); 65 public delegate void SynchronizeSceneHandler(Scene scene);
67 66
@@ -104,9 +103,10 @@ namespace OpenSim.Region.Framework.Scenes
104 /// <summary> 103 /// <summary>
105 /// If false then physical objects are disabled, though collisions will continue as normal. 104 /// If false then physical objects are disabled, though collisions will continue as normal.
106 /// </summary> 105 /// </summary>
107 public bool PhysicsEnabled 106
108 { 107 public bool PhysicsEnabled
109 get 108 {
109 get
110 { 110 {
111 return m_physicsEnabled; 111 return m_physicsEnabled;
112 } 112 }
@@ -215,7 +215,7 @@ namespace OpenSim.Region.Framework.Scenes
215 /// <summary> 215 /// <summary>
216 /// Maximum value of the size of a physical prim in each axis 216 /// Maximum value of the size of a physical prim in each axis
217 /// </summary> 217 /// </summary>
218 public float m_maxPhys = 64; 218 public float m_maxPhys = 10;
219 219
220 /// <summary> 220 /// <summary>
221 /// Max prims an object will hold 221 /// Max prims an object will hold
@@ -227,10 +227,16 @@ namespace OpenSim.Region.Framework.Scenes
227 public bool m_allowScriptCrossings = true; 227 public bool m_allowScriptCrossings = true;
228 228
229 /// <summary> 229 /// <summary>
230
230 /// Can avatars cross from and to this region? 231 /// Can avatars cross from and to this region?
231 /// </summary> 232 /// </summary>
232 public bool AllowAvatarCrossing { get; set; } 233 public bool AllowAvatarCrossing { get; set; }
233 234
235 /// Max prims an Physical object will hold
236 /// </summary>
237 ///
238 public int m_linksetPhysCapacity = 0;
239
234 public bool m_useFlySlow; 240 public bool m_useFlySlow;
235 public bool m_useTrashOnDelete = true; 241 public bool m_useTrashOnDelete = true;
236 242
@@ -264,20 +270,17 @@ namespace OpenSim.Region.Framework.Scenes
264 /// </summary> 270 /// </summary>
265 public int ChildTerseUpdatePeriod { get; set; } 271 public int ChildTerseUpdatePeriod { get; set; }
266 272
267 protected float m_defaultDrawDistance = 255.0f; 273 protected float m_defaultDrawDistance = 255f;
268 public float DefaultDrawDistance 274 public float DefaultDrawDistance
269 { 275 {
270 // get { return m_defaultDrawDistance; } 276 get { return m_defaultDrawDistance; }
271 get 277 }
272 {
273 if (RegionInfo != null)
274 {
275 float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
276 m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension);
277 278
278 } 279 protected float m_maxDrawDistance = 512.0f;
279 return m_defaultDrawDistance; 280// protected float m_maxDrawDistance = 256.0f;
280 } 281 public float MaxDrawDistance
282 {
283 get { return m_maxDrawDistance; }
281 } 284 }
282 285
283 private List<string> m_AllowedViewers = new List<string>(); 286 private List<string> m_AllowedViewers = new List<string>();
@@ -286,8 +289,8 @@ namespace OpenSim.Region.Framework.Scenes
286 // TODO: need to figure out how allow client agents but deny 289 // TODO: need to figure out how allow client agents but deny
287 // root agents when ACL denies access to root agent 290 // root agents when ACL denies access to root agent
288 public bool m_strictAccessControl = true; 291 public bool m_strictAccessControl = true;
289 292 public bool m_seeIntoBannedRegion = false;
290 public int MaxUndoCount { get; set; } 293 public int MaxUndoCount = 5;
291 294
292 public bool SeeIntoRegion { get; set; } 295 public bool SeeIntoRegion { get; set; }
293 296
@@ -305,11 +308,13 @@ namespace OpenSim.Region.Framework.Scenes
305 308
306 protected int m_splitRegionID; 309 protected int m_splitRegionID;
307 protected Timer m_restartWaitTimer = new Timer(); 310 protected Timer m_restartWaitTimer = new Timer();
311 protected Timer m_timerWatchdog = new Timer();
308 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 312 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
309 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 313 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
310 protected string m_simulatorVersion = "OpenSimulator Server"; 314 protected string m_simulatorVersion = "OpenSimulator Server";
311 protected AgentCircuitManager m_authenticateHandler; 315 protected AgentCircuitManager m_authenticateHandler;
312 protected SceneCommunicationService m_sceneGridService; 316 protected SceneCommunicationService m_sceneGridService;
317 protected ISnmpModule m_snmpService = null;
313 318
314 protected ISimulationDataService m_SimulationDataService; 319 protected ISimulationDataService m_SimulationDataService;
315 protected IEstateDataService m_EstateDataService; 320 protected IEstateDataService m_EstateDataService;
@@ -338,17 +343,6 @@ namespace OpenSim.Region.Framework.Scenes
338 private Dictionary<string, string> m_extraSettings; 343 private Dictionary<string, string> m_extraSettings;
339 344
340 /// <summary> 345 /// <summary>
341 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
342 /// rather than on a single thread that sleeps.
343 /// </summary>
344 public bool UpdateOnTimer { get; set; }
345
346 /// <summary>
347 /// Only used if we are updating scene on a timer rather than sleeping a thread.
348 /// </summary>
349 private Timer m_sceneUpdateTimer;
350
351 /// <summary>
352 /// Current scene frame number 346 /// Current scene frame number
353 /// </summary> 347 /// </summary>
354 public uint Frame 348 public uint Frame
@@ -363,23 +357,14 @@ namespace OpenSim.Region.Framework.Scenes
363 public uint MaintenanceRun { get; private set; } 357 public uint MaintenanceRun { get; private set; }
364 358
365 /// <summary> 359 /// <summary>
366 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we 360 /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we
367 /// will sleep for the remaining period. 361 /// will sleep for the remaining period.
368 /// </summary> 362 /// </summary>
369 /// <remarks> 363 /// <remarks>
370 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations 364 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
371 /// occur too quickly (viewer 1) or with even more slide (viewer 2). 365 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
372 /// </remarks> 366 /// </remarks>
373 public int MinFrameTicks 367 public float MinFrameTime { get; private set; }
374 {
375 get { return m_minFrameTicks; }
376 private set
377 {
378 m_minFrameTicks = value;
379 MinFrameSeconds = (float)m_minFrameTicks / 1000;
380 }
381 }
382 private int m_minFrameTicks;
383 368
384 /// <summary> 369 /// <summary>
385 /// The minimum length of time in seconds that will be taken for a scene frame. 370 /// The minimum length of time in seconds that will be taken for a scene frame.
@@ -387,17 +372,7 @@ namespace OpenSim.Region.Framework.Scenes
387 /// <remarks> 372 /// <remarks>
388 /// Always derived from MinFrameTicks. 373 /// Always derived from MinFrameTicks.
389 /// </remarks> 374 /// </remarks>
390 public float MinFrameSeconds { get; private set; } 375 public float MinMaintenanceTime { get; private set; }
391
392 /// <summary>
393 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
394 /// will sleep for the remaining period.
395 /// </summary>
396 /// <remarks>
397 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
398 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
399 /// </remarks>
400 public int MinMaintenanceTicks { get; set; }
401 376
402 private int m_update_physics = 1; 377 private int m_update_physics = 1;
403 private int m_update_entitymovement = 1; 378 private int m_update_entitymovement = 1;
@@ -405,22 +380,23 @@ namespace OpenSim.Region.Framework.Scenes
405 private int m_update_presences = 1; // Update scene presence movements 380 private int m_update_presences = 1; // Update scene presence movements
406 private int m_update_events = 1; 381 private int m_update_events = 1;
407 private int m_update_backup = 200; 382 private int m_update_backup = 200;
408 private int m_update_terrain = 50; 383
409 // private int m_update_land = 1; 384 private int m_update_terrain = 1000;
385 private int m_update_land = 10;
386
410 private int m_update_coarse_locations = 50; 387 private int m_update_coarse_locations = 50;
411 private int m_update_temp_cleaning = 180; 388 private int m_update_temp_cleaning = 180;
412 389
413 private int agentMS; 390 private float agentMS;
414 private int frameMS; 391 private float frameMS;
415 private int physicsMS2; 392 private float physicsMS2;
416 private int physicsMS; 393 private float physicsMS;
417 private int otherMS; 394 private float otherMS;
418 private int tempOnRezMS; 395 private float tempOnRezMS;
419 private int eventMS; 396 private float eventMS;
420 private int backupMS; 397 private float backupMS;
421 private int terrainMS; 398 private float terrainMS;
422 private int landMS; 399 private float landMS;
423 private int spareMS;
424 400
425 // A temporary configuration flag to enable using FireAndForget to process 401 // A temporary configuration flag to enable using FireAndForget to process
426 // collisions from the physics engine. There is a problem with collisions 402 // collisions from the physics engine. There is a problem with collisions
@@ -438,6 +414,7 @@ namespace OpenSim.Region.Framework.Scenes
438 /// </summary> 414 /// </summary>
439 private int m_lastFrameTick; 415 private int m_lastFrameTick;
440 416
417 public bool CombineRegions = false;
441 /// <summary> 418 /// <summary>
442 /// Tick at which the last maintenance run occurred. 419 /// Tick at which the last maintenance run occurred.
443 /// </summary> 420 /// </summary>
@@ -469,7 +446,7 @@ namespace OpenSim.Region.Framework.Scenes
469 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 446 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
470 private volatile bool m_backingup; 447 private volatile bool m_backingup;
471 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 448 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
472 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 449 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
473 450
474 private string m_defaultScriptEngine; 451 private string m_defaultScriptEngine;
475 452
@@ -484,6 +461,11 @@ namespace OpenSim.Region.Framework.Scenes
484 /// </summary> 461 /// </summary>
485 private int m_LastLogin; 462 private int m_LastLogin;
486 463
464 private int m_lastIncoming;
465 private int m_lastOutgoing;
466 private int m_hbRestarts = 0;
467
468
487 /// <summary> 469 /// <summary>
488 /// Thread that runs the scene loop. 470 /// Thread that runs the scene loop.
489 /// </summary> 471 /// </summary>
@@ -532,6 +514,16 @@ namespace OpenSim.Region.Framework.Scenes
532 public bool IsRunning { get { return m_isRunning; } } 514 public bool IsRunning { get { return m_isRunning; } }
533 private volatile bool m_isRunning; 515 private volatile bool m_isRunning;
534 516
517// private int m_lastUpdate;
518 private bool m_firstHeartbeat = true;
519
520 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
521 private bool m_reprioritizationEnabled = true;
522 private double m_reprioritizationInterval = 5000.0;
523 private double m_rootReprioritizationDistance = 10.0;
524 private double m_childReprioritizationDistance = 20.0;
525
526
535 private Timer m_mapGenerationTimer = new Timer(); 527 private Timer m_mapGenerationTimer = new Timer();
536 private bool m_generateMaptiles; 528 private bool m_generateMaptiles;
537 529
@@ -563,6 +555,19 @@ namespace OpenSim.Region.Framework.Scenes
563 get { return m_sceneGridService; } 555 get { return m_sceneGridService; }
564 } 556 }
565 557
558 public ISnmpModule SnmpService
559 {
560 get
561 {
562 if (m_snmpService == null)
563 {
564 m_snmpService = RequestModuleInterface<ISnmpModule>();
565 }
566
567 return m_snmpService;
568 }
569 }
570
566 public ISimulationDataService SimulationDataService 571 public ISimulationDataService SimulationDataService
567 { 572 {
568 get 573 get
@@ -769,15 +774,15 @@ namespace OpenSim.Region.Framework.Scenes
769 get { return m_capsModule; } 774 get { return m_capsModule; }
770 } 775 }
771 776
772 public int MonitorFrameTime { get { return frameMS; } } 777 public int MonitorFrameTime { get { return (int)frameMS; } }
773 public int MonitorPhysicsUpdateTime { get { return physicsMS; } } 778 public int MonitorPhysicsUpdateTime { get { return (int)physicsMS; } }
774 public int MonitorPhysicsSyncTime { get { return physicsMS2; } } 779 public int MonitorPhysicsSyncTime { get { return (int)physicsMS2; } }
775 public int MonitorOtherTime { get { return otherMS; } } 780 public int MonitorOtherTime { get { return (int)otherMS; } }
776 public int MonitorTempOnRezTime { get { return tempOnRezMS; } } 781 public int MonitorTempOnRezTime { get { return (int)tempOnRezMS; } }
777 public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? 782 public int MonitorEventTime { get { return (int)eventMS; } } // This may need to be divided into each event?
778 public int MonitorBackupTime { get { return backupMS; } } 783 public int MonitorBackupTime { get { return (int)backupMS; } }
779 public int MonitorTerrainTime { get { return terrainMS; } } 784 public int MonitorTerrainTime { get { return (int)terrainMS; } }
780 public int MonitorLandTime { get { return landMS; } } 785 public int MonitorLandTime { get { return (int)landMS; } }
781 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 786 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
782 787
783 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 788 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
@@ -855,8 +860,8 @@ namespace OpenSim.Region.Framework.Scenes
855 : this(regInfo) 860 : this(regInfo)
856 { 861 {
857 m_config = config; 862 m_config = config;
858 MinFrameTicks = 89; 863 MinFrameTime = 0.089f;
859 MinMaintenanceTicks = 1000; 864 MinMaintenanceTime = 1;
860 SeeIntoRegion = true; 865 SeeIntoRegion = true;
861 866
862 Random random = new Random(); 867 Random random = new Random();
@@ -867,6 +872,9 @@ namespace OpenSim.Region.Framework.Scenes
867 m_SimulationDataService = simDataService; 872 m_SimulationDataService = simDataService;
868 m_EstateDataService = estateDataService; 873 m_EstateDataService = estateDataService;
869 874
875 m_lastIncoming = 0;
876 m_lastOutgoing = 0;
877
870 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 878 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
871 m_asyncSceneObjectDeleter.Enabled = true; 879 m_asyncSceneObjectDeleter.Enabled = true;
872 880
@@ -924,6 +932,22 @@ namespace OpenSim.Region.Framework.Scenes
924 EventManager.OnLandObjectRemoved += 932 EventManager.OnLandObjectRemoved +=
925 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 933 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
926 934
935 m_sceneGraph = new SceneGraph(this);
936 m_sceneGraph.PhysicsScene = physicsScene;
937
938 // If the scene graph has an Unrecoverable error, restart this sim.
939 // Currently the only thing that causes it to happen is two kinds of specific
940 // Physics based crashes.
941 //
942 // Out of memory
943 // Operating system has killed the plugin
944 m_sceneGraph.UnRecoverableError
945 += () =>
946 {
947 m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name);
948 RestartNow();
949 };
950
927 RegisterDefaultSceneEvents(); 951 RegisterDefaultSceneEvents();
928 952
929 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 953 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
@@ -945,6 +969,11 @@ namespace OpenSim.Region.Framework.Scenes
945 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 969 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
946 970
947 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); 971 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
972 m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
973
974 if (m_defaultDrawDistance > m_maxDrawDistance)
975 m_defaultDrawDistance = m_maxDrawDistance;
976
948 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 977 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
949 if (!UseBackup) 978 if (!UseBackup)
950 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 979 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -956,9 +985,8 @@ namespace OpenSim.Region.Framework.Scenes
956 985
957 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 986 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
958 987
959 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 988 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
960 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 989 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
961
962 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 990 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
963 if (RegionInfo.NonphysPrimMin > 0) 991 if (RegionInfo.NonphysPrimMin > 0)
964 { 992 {
@@ -978,11 +1006,24 @@ namespace OpenSim.Region.Framework.Scenes
978 } 1006 }
979 1007
980 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 1008 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
1009
981 if (RegionInfo.PhysPrimMax > 0) 1010 if (RegionInfo.PhysPrimMax > 0)
982 { 1011 {
983 m_maxPhys = RegionInfo.PhysPrimMax; 1012 m_maxPhys = RegionInfo.PhysPrimMax;
984 } 1013 }
985 1014
1015 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
1016 if (RegionInfo.LinksetCapacity > 0)
1017 {
1018 m_linksetCapacity = RegionInfo.LinksetCapacity;
1019 }
1020
1021 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
1022
1023
1024 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1025 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1026
986 // Here, if clamping is requested in either global or 1027 // Here, if clamping is requested in either global or
987 // local config, it will be used 1028 // local config, it will be used
988 // 1029 //
@@ -992,13 +1033,7 @@ namespace OpenSim.Region.Framework.Scenes
992 m_clampPrimSize = true; 1033 m_clampPrimSize = true;
993 } 1034 }
994 1035
995 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 1036 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
996 if (RegionInfo.LinksetCapacity > 0)
997 {
998 m_linksetCapacity = RegionInfo.LinksetCapacity;
999 }
1000
1001 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete);
1002 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 1037 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
1003 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 1038 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
1004 m_dontPersistBefore = 1039 m_dontPersistBefore =
@@ -1009,11 +1044,11 @@ namespace OpenSim.Region.Framework.Scenes
1009 m_persistAfter *= 10000000; 1044 m_persistAfter *= 10000000;
1010 1045
1011 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1046 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
1012 1047 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
1013 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1014 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1015 1048
1016 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1049 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
1050 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
1051 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
1017 1052
1018 string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; 1053 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1019 1054
@@ -1059,7 +1094,7 @@ namespace OpenSim.Region.Framework.Scenes
1059 1094
1060 if (grant.Length > 0) 1095 if (grant.Length > 0)
1061 { 1096 {
1062 foreach (string viewer in grant.Split('|')) 1097 foreach (string viewer in grant.Split(','))
1063 { 1098 {
1064 m_AllowedViewers.Add(viewer.Trim().ToLower()); 1099 m_AllowedViewers.Add(viewer.Trim().ToLower());
1065 } 1100 }
@@ -1075,14 +1110,13 @@ namespace OpenSim.Region.Framework.Scenes
1075 1110
1076 if (grant.Length > 0) 1111 if (grant.Length > 0)
1077 { 1112 {
1078 foreach (string viewer in grant.Split('|')) 1113 foreach (string viewer in grant.Split(','))
1079 { 1114 {
1080 m_BannedViewers.Add(viewer.Trim().ToLower()); 1115 m_BannedViewers.Add(viewer.Trim().ToLower());
1081 } 1116 }
1082 } 1117 }
1083 1118
1084 if (startupConfig.Contains("MinFrameTime")) 1119 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
1085 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
1086 1120
1087 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); 1121 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
1088 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1122 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -1160,39 +1194,13 @@ namespace OpenSim.Region.Framework.Scenes
1160 1194
1161 #endregion Interest Management 1195 #endregion Interest Management
1162 1196
1163 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform
1164 // if the timer is based on a high-resolution performance counter or based on the system timer;
1165 // the performance counter will provide a more precise time than the system timer
1166 if (Stopwatch.IsHighResolution)
1167 m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics.");
1168 else
1169 m_log.InfoFormat("[SCENE]: Using system timer for statistics.");
1170 1197
1171 // Acquire the statistics section of the OpenSim.ini file located 1198 StatsReporter = new SimStatsReporter(this);
1172 // in the bin directory
1173 IConfig statisticsConfig = m_config.Configs["Statistics"];
1174
1175 // Confirm that the statistics section existed in the configuration
1176 // file
1177 if (statisticsConfig != null)
1178 {
1179 // Create the StatsReporter using the number of frames to store
1180 // for the frame time statistics, or 10 frames if the config
1181 // file doesn't contain a value
1182 StatsReporter = new SimStatsReporter(this,
1183 statisticsConfig.GetInt("NumberOfFrames",
1184 m_defaultNumberFramesStored));
1185 }
1186 else
1187 {
1188 // Create a StatsReporter with the current scene and a default
1189 // 10 frames stored for the frame time statistics
1190 StatsReporter = new SimStatsReporter(this);
1191 }
1192 1199
1193 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1200 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
1194 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1201 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1195 1202
1203 MainConsole.Instance.Commands.AddCommand("scene", false, "gc collect", "gc collect", "gc collect", "Cause the garbage collector to make a single pass", HandleGcCollect);
1196 } 1204 }
1197 1205
1198 public Scene(RegionInfo regInfo) 1206 public Scene(RegionInfo regInfo)
@@ -1215,13 +1223,36 @@ namespace OpenSim.Region.Framework.Scenes
1215 1223
1216 PhysicalPrims = true; 1224 PhysicalPrims = true;
1217 CollidablePrims = true; 1225 CollidablePrims = true;
1218 PhysicsEnabled = true; 1226 // this is done above acording to config
1227 // PhysicsEnabled = true;
1219 1228
1220 AllowAvatarCrossing = true; 1229 AllowAvatarCrossing = true;
1221 1230
1222 PeriodicBackup = true; 1231 PeriodicBackup = true;
1223 UseBackup = true; 1232 UseBackup = true;
1224 1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1225 IsReprioritizationEnabled = true; 1256 IsReprioritizationEnabled = true;
1226 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; 1257 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time;
1227 ReprioritizationInterval = 5000; 1258 ReprioritizationInterval = 5000;
@@ -1235,6 +1266,7 @@ namespace OpenSim.Region.Framework.Scenes
1235 m_eventManager = new EventManager(); 1266 m_eventManager = new EventManager();
1236 1267
1237 m_permissions = new ScenePermissions(this); 1268 m_permissions = new ScenePermissions(this);
1269
1238 } 1270 }
1239 1271
1240 #endregion 1272 #endregion
@@ -1280,20 +1312,8 @@ namespace OpenSim.Region.Framework.Scenes
1280 { 1312 {
1281 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1313 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1282 { 1314 {
1283 //// If these are cast to INT because long + negative values + abs returns invalid data
1284 //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
1285 //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
1286 //if (resultX <= 1 && resultY <= 1)
1287 float dist = (float)Math.Max(DefaultDrawDistance,
1288 (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY));
1289 uint newRegionX, newRegionY, thisRegionX, thisRegionY;
1290 Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY);
1291 Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY);
1292 1315
1293 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1316 if (isNeighborRegion(otherRegion))
1294 // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY);
1295
1296 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY))
1297 { 1317 {
1298 // Let the grid service module know, so this can be cached 1318 // Let the grid service module know, so this can be cached
1299 m_eventManager.TriggerOnRegionUp(otherRegion); 1319 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1328,6 +1348,21 @@ namespace OpenSim.Region.Framework.Scenes
1328 } 1348 }
1329 } 1349 }
1330 1350
1351 public bool isNeighborRegion(GridRegion otherRegion)
1352 {
1353 int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ;
1354
1355 if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX)
1356 return false;
1357
1358 tmp = otherRegion.RegionLocY - (int)RegionInfo.WorldLocY;
1359
1360 if (tmp < -otherRegion.RegionSizeY && tmp > RegionInfo.RegionSizeY)
1361 return false;
1362
1363 return true;
1364 }
1365
1331 public void AddNeighborRegion(RegionInfo region) 1366 public void AddNeighborRegion(RegionInfo region)
1332 { 1367 {
1333 lock (m_neighbours) 1368 lock (m_neighbours)
@@ -1459,8 +1494,11 @@ namespace OpenSim.Region.Framework.Scenes
1459 // Stop all client threads. 1494 // Stop all client threads.
1460 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); 1495 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1461 1496
1462 m_log.Debug("[SCENE]: Persisting changed objects"); 1497 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1463 EventManager.TriggerSceneShuttingDown(this); 1498 EventManager.TriggerSceneShuttingDown(this);
1499
1500 m_log.Debug("[SCENE]: Persisting changed objects");
1501
1464 Backup(false); 1502 Backup(false);
1465 m_sceneGraph.Close(); 1503 m_sceneGraph.Close();
1466 1504
@@ -1474,6 +1512,7 @@ namespace OpenSim.Region.Framework.Scenes
1474 // attempt to reference a null or disposed physics scene. 1512 // attempt to reference a null or disposed physics scene.
1475 if (PhysicsScene != null) 1513 if (PhysicsScene != null)
1476 { 1514 {
1515 m_log.Debug("[SCENE]: Dispose Physics");
1477 PhysicsScene phys = PhysicsScene; 1516 PhysicsScene phys = PhysicsScene;
1478 // remove the physics engine from both Scene and SceneGraph 1517 // remove the physics engine from both Scene and SceneGraph
1479 PhysicsScene = null; 1518 PhysicsScene = null;
@@ -1505,10 +1544,28 @@ namespace OpenSim.Region.Framework.Scenes
1505// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1544// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1506 if (m_heartbeatThread != null) 1545 if (m_heartbeatThread != null)
1507 { 1546 {
1547 m_hbRestarts++;
1548 if(m_hbRestarts > 10)
1549 Environment.Exit(1);
1550 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1551
1552//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1553//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1554//proc.EnableRaisingEvents=false;
1555//proc.StartInfo.FileName = "/bin/kill";
1556//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1557//proc.Start();
1558//proc.WaitForExit();
1559//Thread.Sleep(1000);
1560//Environment.Exit(1);
1508 m_heartbeatThread.Abort(); 1561 m_heartbeatThread.Abort();
1562 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1509 m_heartbeatThread = null; 1563 m_heartbeatThread = null;
1510 } 1564 }
1511 1565
1566// m_sceneGraph.PreparePhysicsSimulation();
1567
1568
1512 m_heartbeatThread 1569 m_heartbeatThread
1513 = WorkManager.StartThread( 1570 = WorkManager.StartThread(
1514 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); 1571 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
@@ -1556,45 +1613,8 @@ namespace OpenSim.Region.Framework.Scenes
1556 1613
1557 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1614 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1558 m_lastFrameTick = Util.EnvironmentTickCount(); 1615 m_lastFrameTick = Util.EnvironmentTickCount();
1559 1616 Update(-1);
1560 if (UpdateOnTimer) 1617 }
1561 {
1562 m_sceneUpdateTimer = new Timer(MinFrameTicks);
1563 m_sceneUpdateTimer.AutoReset = true;
1564 m_sceneUpdateTimer.Elapsed += Update;
1565 m_sceneUpdateTimer.Start();
1566 }
1567 else
1568 {
1569 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1570 Update(-1);
1571 Watchdog.RemoveThread();
1572 m_isRunning = false;
1573 }
1574 }
1575
1576 private volatile bool m_isTimerUpdateRunning;
1577
1578 private void Update(object sender, ElapsedEventArgs e)
1579 {
1580 if (m_isTimerUpdateRunning)
1581 return;
1582
1583 m_isTimerUpdateRunning = true;
1584
1585 // If the last frame did not complete on time, then immediately start the next update on the same thread
1586 // and ignore further timed updates until we have a frame that had spare time.
1587 while (!Update(1) && Active) { }
1588
1589 if (!Active || m_shuttingDown)
1590 {
1591 m_sceneUpdateTimer.Stop();
1592 m_sceneUpdateTimer = null;
1593 m_isRunning = false;
1594 }
1595
1596 m_isTimerUpdateRunning = false;
1597 }
1598 1618
1599 private void Maintenance() 1619 private void Maintenance()
1600 { 1620 {
@@ -1663,24 +1683,24 @@ namespace OpenSim.Region.Framework.Scenes
1663 previousMaintenanceTick = m_lastMaintenanceTick; 1683 previousMaintenanceTick = m_lastMaintenanceTick;
1664 m_lastMaintenanceTick = Util.EnvironmentTickCount(); 1684 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1665 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); 1685 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1666 runtc = MinMaintenanceTicks - runtc; 1686 runtc = (int)(MinMaintenanceTime * 1000) - runtc;
1667 1687
1668 if (runtc > 0) 1688 if (runtc > 0)
1669 m_maintenanceWaitEvent.WaitOne(runtc); 1689 m_maintenanceWaitEvent.WaitOne(runtc);
1670 1690
1671 // Optionally warn if a frame takes double the amount of time that it should. 1691 // Optionally warn if a frame takes double the amount of time that it should.
1672 if (DebugUpdates 1692 if (DebugUpdates
1673 && Util.EnvironmentTickCountSubtract( 1693 && Util.EnvironmentTickCountSubtract(
1674 m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) 1694 m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2))
1675 m_log.WarnFormat( 1695 m_log.WarnFormat(
1676 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", 1696 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1677 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), 1697 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1678 MinMaintenanceTicks, 1698 MinMaintenanceTime * 1000,
1679 RegionInfo.RegionName); 1699 RegionInfo.RegionName);
1680 } 1700 }
1681 } 1701 }
1682 1702
1683 public override bool Update(int frames) 1703 public override void Update(int frames)
1684 { 1704 {
1685 long? endFrame = null; 1705 long? endFrame = null;
1686 1706
@@ -1688,119 +1708,76 @@ namespace OpenSim.Region.Framework.Scenes
1688 endFrame = Frame + frames; 1708 endFrame = Frame + frames;
1689 1709
1690 float physicsFPS = 0f; 1710 float physicsFPS = 0f;
1691 int previousFrameTick, tmpMS; 1711
1692 1712 int previousFrameTick;
1693 // These variables will be used to save the precise frame time using the 1713
1694 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1714 double tmpMS;
1695 // and end of a particular section of code, and then used to calculate 1715 double tmpMS2;
1696 // the frame times, which are the sums of the sections for each given name 1716 double framestart;
1697 double preciseTotalFrameTime = 0.0; 1717 float sleepMS;
1698 double preciseSimFrameTime = 0.0;
1699 double precisePhysicsFrameTime = 0.0;
1700 Stopwatch totalFrameStopwatch = new Stopwatch();
1701 Stopwatch simFrameStopwatch = new Stopwatch();
1702 Stopwatch physicsFrameStopwatch = new Stopwatch();
1703
1704 // Begin the stopwatch to keep track of the time that the frame
1705 // started running to determine how long the frame took to complete
1706 totalFrameStopwatch.Start();
1707 1718
1708 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1719 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1709 { 1720 {
1721 framestart = Util.GetTimeStampMS();
1710 ++Frame; 1722 ++Frame;
1711 1723
1712 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1724 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1713 1725
1714 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1726 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0f;
1715 1727
1716 try 1728 try
1717 { 1729 {
1718 EventManager.TriggerRegionHeartbeatStart(this); 1730 EventManager.TriggerRegionHeartbeatStart(this);
1719 1731
1720 // Apply taints in terrain module to terrain in physics scene 1732 // Apply taints in terrain module to terrain in physics scene
1733
1734 tmpMS = Util.GetTimeStampMS();
1735
1736 if (Frame % 4 == 0)
1737 {
1738 CheckTerrainUpdates();
1739 }
1740
1721 if (Frame % m_update_terrain == 0) 1741 if (Frame % m_update_terrain == 0)
1722 { 1742 {
1723 // At several points inside the code there was a need to
1724 // create a more precise measurement of time elapsed.
1725 // This led to the addition of variables that have a
1726 // similar function and thus remain tightly connected to
1727 // their original counterparts. However, the original
1728 // code is not receiving comments from our group because
1729 // we don't feel right modifying the code to that degree
1730 // at this point in time, the precise values all begin
1731 // with the keyword precise
1732 tmpMS = Util.EnvironmentTickCount();
1733 simFrameStopwatch.Start();
1734 UpdateTerrain(); 1743 UpdateTerrain();
1735
1736 // Get the simulation frame time that the avatar force
1737 // input took
1738 simFrameStopwatch.Stop();
1739 preciseSimFrameTime =
1740 simFrameStopwatch.Elapsed.TotalMilliseconds;
1741 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1742 } 1744 }
1743 1745
1744 // At several points inside the code there was a need to 1746 tmpMS2 = Util.GetTimeStampMS();
1745 // create a more precise measurement of time elapsed. This 1747 terrainMS = (float)(tmpMS2 - tmpMS);
1746 // led to the addition of variables that have a similar 1748 tmpMS = tmpMS2;
1747 // function and thus remain tightly connected to their
1748 // original counterparts. However, the original code is
1749 // not receiving comments from our group because we don't
1750 // feel right modifying the code to that degree at this
1751 // point in time, the precise values all begin with the
1752 // keyword precise
1753 1749
1754 tmpMS = Util.EnvironmentTickCount();
1755
1756 // Begin the stopwatch to track the time to prepare physics
1757 physicsFrameStopwatch.Start();
1758 if (PhysicsEnabled && Frame % m_update_physics == 0) 1750 if (PhysicsEnabled && Frame % m_update_physics == 0)
1759 m_sceneGraph.UpdatePreparePhysics(); 1751 m_sceneGraph.UpdatePreparePhysics();
1760 1752
1761 // Get the time it took to prepare the physics, this 1753 tmpMS2 = Util.GetTimeStampMS();
1762 // would report the most precise time that physics was 1754 physicsMS2 = (float)(tmpMS2 - tmpMS);
1763 // running on the machine and should the physics not be 1755 tmpMS = tmpMS2;
1764 // enabled will report the time it took to check if physics
1765 // was enabled
1766 physicsFrameStopwatch.Stop();
1767 precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1768 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1769 1756
1770 // Apply any pending avatar force input to the avatar's velocity 1757 // Apply any pending avatar force input to the avatar's velocity
1771 tmpMS = Util.EnvironmentTickCount();
1772 simFrameStopwatch.Restart();
1773 if (Frame % m_update_entitymovement == 0) 1758 if (Frame % m_update_entitymovement == 0)
1774 m_sceneGraph.UpdateScenePresenceMovement(); 1759 m_sceneGraph.UpdateScenePresenceMovement();
1775 1760
1776 // Get the simulation frame time that the avatar force input 1761 // Get the simulation frame time that the avatar force input
1777 // took 1762 // took
1778 simFrameStopwatch.Stop(); 1763 tmpMS2 = Util.GetTimeStampMS();
1779 preciseSimFrameTime += 1764 agentMS = (float)(tmpMS2 - tmpMS);
1780 simFrameStopwatch.Elapsed.TotalMilliseconds; 1765 tmpMS = tmpMS2;
1781 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1782 1766
1783 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1767 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1784 // velocity 1768 // velocity
1785 tmpMS = Util.EnvironmentTickCount();
1786 physicsFrameStopwatch.Restart();
1787 if (Frame % m_update_physics == 0) 1769 if (Frame % m_update_physics == 0)
1788 { 1770 {
1789 if (PhysicsEnabled) 1771 if (PhysicsEnabled)
1790 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); 1772 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime);
1791 1773
1792 if (SynchronizeScene != null) 1774 if (SynchronizeScene != null)
1793 SynchronizeScene(this); 1775 SynchronizeScene(this);
1794 } 1776 }
1795 1777
1796 // Add the main physics update time to the prepare physics time 1778 tmpMS2 = Util.GetTimeStampMS();
1797 physicsFrameStopwatch.Stop(); 1779 physicsMS = (float)(tmpMS2 - tmpMS);
1798 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; 1780 tmpMS = tmpMS2;
1799 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1800
1801 // Start the stopwatch for the remainder of the simulation
1802 simFrameStopwatch.Restart();
1803 tmpMS = Util.EnvironmentTickCount();
1804 1781
1805 // Check if any objects have reached their targets 1782 // Check if any objects have reached their targets
1806 CheckAtTargets(); 1783 CheckAtTargets();
@@ -1815,20 +1792,37 @@ namespace OpenSim.Region.Framework.Scenes
1815 if (Frame % m_update_presences == 0) 1792 if (Frame % m_update_presences == 0)
1816 m_sceneGraph.UpdatePresences(); 1793 m_sceneGraph.UpdatePresences();
1817 1794
1818 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1795 tmpMS2 = Util.GetTimeStampMS();
1819 1796 agentMS += (float)(tmpMS2 - tmpMS);
1797 tmpMS = tmpMS2;
1798
1799 // Delete temp-on-rez stuff
1800 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1801 {
1802
1803 m_cleaningTemps = true;
1804 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1805 tmpMS2 = Util.GetTimeStampMS();
1806 tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
1807 tmpMS = tmpMS2;
1808 }
1809
1820 if (Frame % m_update_events == 0) 1810 if (Frame % m_update_events == 0)
1821 { 1811 {
1822 tmpMS = Util.EnvironmentTickCount();
1823 UpdateEvents(); 1812 UpdateEvents();
1824 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1813
1814 tmpMS2 = Util.GetTimeStampMS();
1815 eventMS = (float)(tmpMS2 - tmpMS);
1816 tmpMS = tmpMS2;
1825 } 1817 }
1826 1818
1827 if (PeriodicBackup && Frame % m_update_backup == 0) 1819 if (PeriodicBackup && Frame % m_update_backup == 0)
1828 { 1820 {
1829 tmpMS = Util.EnvironmentTickCount();
1830 UpdateStorageBackup(); 1821 UpdateStorageBackup();
1831 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1822
1823 tmpMS2 = Util.GetTimeStampMS();
1824 backupMS = (float)(tmpMS2 - tmpMS);
1825 tmpMS = tmpMS2;
1832 } 1826 }
1833 1827
1834 //if (Frame % m_update_land == 0) 1828 //if (Frame % m_update_land == 0)
@@ -1885,79 +1879,58 @@ namespace OpenSim.Region.Framework.Scenes
1885 } 1879 }
1886 1880
1887 EventManager.TriggerRegionHeartbeatEnd(this); 1881 EventManager.TriggerRegionHeartbeatEnd(this);
1888 otherMS = eventMS + backupMS + terrainMS + landMS;
1889 1882
1890 // Get the elapsed time for the simulation frame 1883 Watchdog.UpdateThread();
1891 simFrameStopwatch.Stop();
1892 preciseSimFrameTime +=
1893 simFrameStopwatch.Elapsed.TotalMilliseconds;
1894
1895 if (!UpdateOnTimer)
1896 {
1897 Watchdog.UpdateThread();
1898
1899 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1900
1901 if (spareMS > 0)
1902 m_updateWaitEvent.WaitOne(spareMS);
1903 else
1904 spareMS = 0;
1905 }
1906 else
1907 {
1908 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS);
1909 }
1910
1911 // Get the total frame time
1912 totalFrameStopwatch.Stop();
1913 preciseTotalFrameTime =
1914 totalFrameStopwatch.Elapsed.TotalMilliseconds;
1915 1884
1916 // Restart the stopwatch for the total time of the next frame 1885 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1917 totalFrameStopwatch.Restart();
1918 1886
1919 previousFrameTick = m_lastFrameTick;
1920 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1921 m_lastFrameTick = Util.EnvironmentTickCount();
1922
1923 // if (Frame%m_update_avatars == 0)
1924 // UpdateInWorldTime();
1925 StatsReporter.AddPhysicsFPS(physicsFPS); 1887 StatsReporter.AddPhysicsFPS(physicsFPS);
1926 StatsReporter.AddTimeDilation(TimeDilation); 1888 StatsReporter.AddTimeDilation(TimeDilation);
1927 StatsReporter.AddFPS(1); 1889 StatsReporter.AddFPS(1);
1928 1890
1929 StatsReporter.addFrameMS(frameMS);
1930 StatsReporter.addAgentMS(agentMS); 1891 StatsReporter.addAgentMS(agentMS);
1931 StatsReporter.addPhysicsMS(physicsMS + physicsMS2); 1892 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1932 StatsReporter.addOtherMS(otherMS); 1893 StatsReporter.addOtherMS(otherMS);
1933 StatsReporter.AddSpareMS(spareMS);
1934 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); 1894 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1935 StatsReporter.AddScriptMS((int) GetAndResetScriptExecutionTime());
1936 1895
1937 // Send the correct time values to the stats reporter for the 1896
1938 // frame times 1897 tmpMS = Util.GetTimeStampMS();
1939 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime,
1940 preciseSimFrameTime, precisePhysicsFrameTime, 0.0);
1941 1898
1942 // Send the correct number of frames that the physics library 1899 previousFrameTick = m_lastFrameTick;
1943 // has processed to the stats reporter 1900 m_lastFrameTick = (int)(tmpMS + 0.5);
1944 StatsReporter.addPhysicsFrame(1);
1945 1901
1946 // Optionally warn if a frame takes double the amount of time that it should. 1902 // estimate sleep time
1903 tmpMS2 = tmpMS - framestart;
1904 tmpMS2 = (double)MinFrameTime * 1000.0D - tmpMS2;
1905
1906 m_firstHeartbeat = false;
1907
1908 // sleep if we can
1909 if (tmpMS2 > 0)
1910 Thread.Sleep((int)(tmpMS2 +0.5));
1911
1912 tmpMS2 = Util.GetTimeStampMS();
1913
1914 sleepMS = (float)(tmpMS2 - tmpMS);
1915 frameMS = (float)(tmpMS2 - framestart);
1916 StatsReporter.addSleepMS(sleepMS);
1917 StatsReporter.addFrameMS(frameMS);
1918
1919 // if (Frame%m_update_avatars == 0)
1920 // UpdateInWorldTime();
1921
1922 // Optionally warn if a frame takes double the amount of time that it should.
1947 if (DebugUpdates 1923 if (DebugUpdates
1948 && Util.EnvironmentTickCountSubtract( 1924 && Util.EnvironmentTickCountSubtract(
1949 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) 1925 m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2))
1926
1950 m_log.WarnFormat( 1927 m_log.WarnFormat(
1951 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1928 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1952 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1929 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1953 MinFrameTicks, 1930 MinFrameTime * 1000,
1931
1954 RegionInfo.RegionName); 1932 RegionInfo.RegionName);
1955 } 1933 }
1956
1957 // Finished updating scene frame, so stop the total frame's Stopwatch
1958 totalFrameStopwatch.Stop();
1959
1960 return spareMS >= 0;
1961 } 1934 }
1962 1935
1963 /// <summary> 1936 /// <summary>
@@ -1983,7 +1956,7 @@ namespace OpenSim.Region.Framework.Scenes
1983 public void AddGroupTarget(SceneObjectGroup grp) 1956 public void AddGroupTarget(SceneObjectGroup grp)
1984 { 1957 {
1985 lock (m_groupsWithTargets) 1958 lock (m_groupsWithTargets)
1986 m_groupsWithTargets[grp.UUID] = grp; 1959 m_groupsWithTargets[grp.UUID] = 0;
1987 } 1960 }
1988 1961
1989 public void RemoveGroupTarget(SceneObjectGroup grp) 1962 public void RemoveGroupTarget(SceneObjectGroup grp)
@@ -1994,18 +1967,24 @@ namespace OpenSim.Region.Framework.Scenes
1994 1967
1995 private void CheckAtTargets() 1968 private void CheckAtTargets()
1996 { 1969 {
1997 List<SceneObjectGroup> objs = null; 1970 List<UUID> objs = null;
1998 1971
1999 lock (m_groupsWithTargets) 1972 lock (m_groupsWithTargets)
2000 { 1973 {
2001 if (m_groupsWithTargets.Count != 0) 1974 if (m_groupsWithTargets.Count != 0)
2002 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1975 objs = new List<UUID>(m_groupsWithTargets.Keys);
2003 } 1976 }
2004 1977
2005 if (objs != null) 1978 if (objs != null)
2006 { 1979 {
2007 foreach (SceneObjectGroup entry in objs) 1980 foreach (UUID entry in objs)
2008 entry.checkAtTargets(); 1981 {
1982 SceneObjectGroup grp = GetSceneObjectGroup(entry);
1983 if (grp == null)
1984 m_groupsWithTargets.Remove(entry);
1985 else
1986 grp.checkAtTargets();
1987 }
2009 } 1988 }
2010 } 1989 }
2011 1990
@@ -2029,6 +2008,11 @@ namespace OpenSim.Region.Framework.Scenes
2029 EventManager.TriggerTerrainTick(); 2008 EventManager.TriggerTerrainTick();
2030 } 2009 }
2031 2010
2011 private void CheckTerrainUpdates()
2012 {
2013 EventManager.TriggerTerrainCheckUpdates();
2014 }
2015
2032 /// <summary> 2016 /// <summary>
2033 /// Back up queued up changes 2017 /// Back up queued up changes
2034 /// </summary> 2018 /// </summary>
@@ -2080,7 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes
2080 msg.fromAgentName = "Server"; 2064 msg.fromAgentName = "Server";
2081 msg.dialog = (byte)19; // Object msg 2065 msg.dialog = (byte)19; // Object msg
2082 msg.fromGroup = false; 2066 msg.fromGroup = false;
2083 msg.offline = (byte)0; 2067 msg.offline = (byte)1;
2084 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 2068 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
2085 msg.Position = Vector3.Zero; 2069 msg.Position = Vector3.Zero;
2086 msg.RegionID = RegionInfo.RegionID.Guid; 2070 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -2316,7 +2300,7 @@ namespace OpenSim.Region.Framework.Scenes
2316 return PhysicsScene.SupportsRaycastWorldFiltered(); 2300 return PhysicsScene.SupportsRaycastWorldFiltered();
2317 } 2301 }
2318 2302
2319 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) 2303 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2320 { 2304 {
2321 if (PhysicsScene == null) 2305 if (PhysicsScene == null)
2322 return null; 2306 return null;
@@ -2338,14 +2322,24 @@ namespace OpenSim.Region.Framework.Scenes
2338 /// <returns></returns> 2322 /// <returns></returns>
2339 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 2323 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
2340 { 2324 {
2325
2326 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
2327 Vector3 wpos = Vector3.Zero;
2328 // Check for water surface intersection from above
2329 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
2330 {
2331 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
2332 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
2333 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
2334 wpos.Z = wheight;
2335 }
2336
2341 Vector3 pos = Vector3.Zero; 2337 Vector3 pos = Vector3.Zero;
2342 if (RayEndIsIntersection == (byte)1) 2338 if (RayEndIsIntersection == (byte)1)
2343 { 2339 {
2344 pos = RayEnd; 2340 pos = RayEnd;
2345 return pos;
2346 } 2341 }
2347 2342 else if (RayTargetID != UUID.Zero)
2348 if (RayTargetID != UUID.Zero)
2349 { 2343 {
2350 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2344 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2351 2345
@@ -2390,13 +2384,10 @@ namespace OpenSim.Region.Framework.Scenes
2390 //pos.Z -= 0.25F; 2384 //pos.Z -= 0.25F;
2391 2385
2392 } 2386 }
2393
2394 return pos;
2395 } 2387 }
2396 else 2388 else
2397 { 2389 {
2398 // We don't have a target here, so we're going to raytrace all the objects in the scene. 2390 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2399
2400 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2391 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
2401 2392
2402 // Un-comment the following line to print the raytrace results to the console. 2393 // Un-comment the following line to print the raytrace results to the console.
@@ -2404,15 +2395,13 @@ namespace OpenSim.Region.Framework.Scenes
2404 2395
2405 if (ei.HitTF) 2396 if (ei.HitTF)
2406 { 2397 {
2407 pos = ei.ipoint; 2398 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2408 } 2399 }
2409 else 2400 else
2410 { 2401 {
2411 // fall back to our stupid functionality 2402 // fall back to our stupid functionality
2412 pos = RayEnd; 2403 pos = RayEnd;
2413 } 2404 }
2414
2415 return pos;
2416 } 2405 }
2417 } 2406 }
2418 else 2407 else
@@ -2423,8 +2412,12 @@ namespace OpenSim.Region.Framework.Scenes
2423 //increase height so its above the ground. 2412 //increase height so its above the ground.
2424 //should be getting the normal of the ground at the rez point and using that? 2413 //should be getting the normal of the ground at the rez point and using that?
2425 pos.Z += scale.Z / 2f; 2414 pos.Z += scale.Z / 2f;
2426 return pos; 2415// return pos;
2427 } 2416 }
2417
2418 // check against posible water intercept
2419 if (wpos.Z > pos.Z) pos = wpos;
2420 return pos;
2428 } 2421 }
2429 2422
2430 2423
@@ -2515,12 +2508,12 @@ namespace OpenSim.Region.Framework.Scenes
2515 { 2508 {
2516 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2509 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2517 { 2510 {
2511 sceneObject.IsDeleted = false;
2518 EventManager.TriggerObjectAddedToScene(sceneObject); 2512 EventManager.TriggerObjectAddedToScene(sceneObject);
2519 return true; 2513 return true;
2520 } 2514 }
2521 2515
2522 return false; 2516 return false;
2523
2524 } 2517 }
2525 2518
2526 /// <summary> 2519 /// <summary>
@@ -2612,6 +2605,15 @@ namespace OpenSim.Region.Framework.Scenes
2612 /// </summary> 2605 /// </summary>
2613 public void DeleteAllSceneObjects() 2606 public void DeleteAllSceneObjects()
2614 { 2607 {
2608 DeleteAllSceneObjects(false);
2609 }
2610
2611 /// <summary>
2612 /// Delete every object from the scene. This does not include attachments worn by avatars.
2613 /// </summary>
2614 public void DeleteAllSceneObjects(bool exceptNoCopy)
2615 {
2616 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2615 lock (Entities) 2617 lock (Entities)
2616 { 2618 {
2617 EntityBase[] entities = Entities.GetEntities(); 2619 EntityBase[] entities = Entities.GetEntities();
@@ -2620,11 +2622,24 @@ namespace OpenSim.Region.Framework.Scenes
2620 if (e is SceneObjectGroup) 2622 if (e is SceneObjectGroup)
2621 { 2623 {
2622 SceneObjectGroup sog = (SceneObjectGroup)e; 2624 SceneObjectGroup sog = (SceneObjectGroup)e;
2623 if (!sog.IsAttachment) 2625 if (sog != null && !sog.IsAttachment)
2624 DeleteSceneObject((SceneObjectGroup)e, false); 2626 {
2627 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2628 {
2629 DeleteSceneObject((SceneObjectGroup)e, false);
2630 }
2631 else
2632 {
2633 toReturn.Add((SceneObjectGroup)e);
2634 }
2635 }
2625 } 2636 }
2626 } 2637 }
2627 } 2638 }
2639 if (toReturn.Count > 0)
2640 {
2641 returnObjects(toReturn.ToArray(), UUID.Zero);
2642 }
2628 } 2643 }
2629 2644
2630 /// <summary> 2645 /// <summary>
@@ -2655,6 +2670,14 @@ namespace OpenSim.Region.Framework.Scenes
2655 else 2670 else
2656 group.StopScriptInstances(); 2671 group.StopScriptInstances();
2657 2672
2673 List<UUID> avatars = group.GetSittingAvatars();
2674 foreach (UUID av in avatars)
2675 {
2676 ScenePresence p = GetScenePresence(av);
2677 if (p != null && p.ParentUUID == UUID.Zero)
2678 p.StandUp();
2679 }
2680
2658 SceneObjectPart[] partList = group.Parts; 2681 SceneObjectPart[] partList = group.Parts;
2659 2682
2660 foreach (SceneObjectPart part in partList) 2683 foreach (SceneObjectPart part in partList)
@@ -2682,6 +2705,8 @@ namespace OpenSim.Region.Framework.Scenes
2682 } 2705 }
2683 2706
2684 group.DeleteGroupFromScene(silent); 2707 group.DeleteGroupFromScene(silent);
2708 if (!silent)
2709 SendKillObject(new List<uint>() { group.LocalId });
2685 2710
2686 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2711 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2687 } 2712 }
@@ -2718,6 +2743,11 @@ namespace OpenSim.Region.Framework.Scenes
2718 return false; 2743 return false;
2719 } 2744 }
2720 2745
2746
2747 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2748 {
2749 m_sceneGraph.updateScenePartGroup(part, grp);
2750 }
2721 /// <summary> 2751 /// <summary>
2722 /// Move the given scene object into a new region depending on which region its absolute position has moved 2752 /// Move the given scene object into a new region depending on which region its absolute position has moved
2723 /// into. 2753 /// into.
@@ -2783,17 +2813,11 @@ namespace OpenSim.Region.Framework.Scenes
2783 if (regionCombinerModule == null) 2813 if (regionCombinerModule == null)
2784 { 2814 {
2785 // Regular region. Just check for region size 2815 // Regular region. Just check for region size
2786 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY) 2816 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
2787 ret = true; 2817 ret = true;
2788 } 2818 }
2789 else
2790 {
2791 // We're in a mega-region so see if we are still in that larger region
2792 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2793 }
2794 2819
2795 return ret; 2820 return ret;
2796
2797 } 2821 }
2798 2822
2799 /// <summary> 2823 /// <summary>
@@ -2817,8 +2841,50 @@ namespace OpenSim.Region.Framework.Scenes
2817 return false; 2841 return false;
2818 } 2842 }
2819 2843
2820 if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) 2844 // If the user is banned, we won't let any of their objects
2845 // enter. Period.
2846 //
2847 if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID, 36))
2848 {
2849 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID);
2850 return false;
2851 }
2852
2853 if (newPosition != Vector3.Zero)
2854 newObject.RootPart.GroupPosition = newPosition;
2855
2856 if (!AddSceneObject(newObject))
2857 {
2858 m_log.DebugFormat(
2859 "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName);
2821 return false; 2860 return false;
2861 }
2862
2863 if (!newObject.IsAttachment)
2864 {
2865 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2866 // it
2867 if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition))
2868 {
2869 // Deny non attachments based on parcel settings
2870 //
2871 m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
2872
2873 DeleteSceneObject(newObject, false);
2874
2875 return false;
2876 }
2877
2878 // For attachments, we need to wait until the agent is root
2879 // before we restart the scripts, or else some functions won't work.
2880 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
2881 newObject.ResumeScripts();
2882
2883 // AddSceneObject already does this and doing it again messes
2884 // up region crossings, so don't.
2885 //if (newObject.RootPart.KeyframeMotion != null)
2886 // newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2887 }
2822 2888
2823 // Do this as late as possible so that listeners have full access to the incoming object 2889 // Do this as late as possible so that listeners have full access to the incoming object
2824 EventManager.TriggerOnIncomingSceneObject(newObject); 2890 EventManager.TriggerOnIncomingSceneObject(newObject);
@@ -2835,6 +2901,23 @@ namespace OpenSim.Region.Framework.Scenes
2835 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2901 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2836 public bool AddSceneObject(SceneObjectGroup sceneObject) 2902 public bool AddSceneObject(SceneObjectGroup sceneObject)
2837 { 2903 {
2904 if (sceneObject.OwnerID == UUID.Zero)
2905 {
2906 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2907 return false;
2908 }
2909
2910 // If the user is banned, we won't let any of their objects
2911 // enter. Period.
2912 //
2913 int flags = GetUserFlags(sceneObject.OwnerID);
2914 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2915 {
2916 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2917
2918 return false;
2919 }
2920
2838 // Force allocation of new LocalId 2921 // Force allocation of new LocalId
2839 // 2922 //
2840 SceneObjectPart[] parts = sceneObject.Parts; 2923 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2871,22 +2954,62 @@ namespace OpenSim.Region.Framework.Scenes
2871 // information that this is due to a teleport/border cross rather than an ordinary attachment. 2954 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2872 // We currently do this in Scene.MakeRootAgent() instead. 2955 // We currently do this in Scene.MakeRootAgent() instead.
2873 if (AttachmentsModule != null) 2956 if (AttachmentsModule != null)
2874 AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); 2957 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
2875 } 2958 }
2876 else 2959 else
2877 { 2960 {
2961 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2878 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2962 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2879 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2963 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2880 } 2964 }
2965 if (sceneObject.OwnerID == UUID.Zero)
2966 {
2967 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2968 return false;
2969 }
2881 } 2970 }
2882 else 2971 else
2883 { 2972 {
2973 if (sceneObject.OwnerID == UUID.Zero)
2974 {
2975 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2976 return false;
2977 }
2884 AddRestoredSceneObject(sceneObject, true, false); 2978 AddRestoredSceneObject(sceneObject, true, false);
2885 } 2979 }
2886 2980
2887 return true; 2981 return true;
2888 } 2982 }
2889 2983
2984 private int GetStateSource(SceneObjectGroup sog)
2985 {
2986 ScenePresence sp = GetScenePresence(sog.OwnerID);
2987
2988 if (sp != null)
2989 return sp.GetStateSource();
2990
2991 return 2; // StateSource.PrimCrossing
2992 }
2993
2994 public int GetUserFlags(UUID user)
2995 {
2996 //Unfortunately the SP approach means that the value is cached until region is restarted
2997 /*
2998 ScenePresence sp;
2999 if (TryGetScenePresence(user, out sp))
3000 {
3001 return sp.UserFlags;
3002 }
3003 else
3004 {
3005 */
3006 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
3007 if (uac == null)
3008 return 0;
3009 return uac.UserFlags;
3010 //}
3011 }
3012
2890 #endregion 3013 #endregion
2891 3014
2892 #region Add/Remove Avatar Methods 3015 #region Add/Remove Avatar Methods
@@ -2922,8 +3045,9 @@ namespace OpenSim.Region.Framework.Scenes
2922 vialogin 3045 vialogin
2923 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 3046 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2924 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 3047 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2925 3048
2926 // CheckHeartbeat(); 3049 CheckHeartbeat();
3050
2927 3051
2928 sp = GetScenePresence(client.AgentId); 3052 sp = GetScenePresence(client.AgentId);
2929 3053
@@ -2934,27 +3058,27 @@ namespace OpenSim.Region.Framework.Scenes
2934 if (sp == null) 3058 if (sp == null)
2935 { 3059 {
2936 m_log.DebugFormat( 3060 m_log.DebugFormat(
2937 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3061 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}",
2938 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 3062 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
2939 3063 ((TPFlags)aCircuit.teleportFlags).ToString());
2940 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 3064
2941
2942 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2943 // client is for a root or child agent.
2944 // We must also set this before adding the client to the client manager so that an exception later on
2945 // does not leave a client manager entry without the scene agent set, which will cause other code
2946 // to fail since any entry in the client manager should have a ScenePresence
2947 //
2948 // XXX: This may be better set for a new client before that client is added to the client manager.
2949 // But need to know what happens in the case where a ScenePresence is already present (and if this
2950 // actually occurs).
2951 client.SceneAgent = sp;
2952
2953 m_clientManager.Add(client); 3065 m_clientManager.Add(client);
2954 SubscribeToClientEvents(client); 3066 SubscribeToClientEvents(client);
2955 m_eventManager.TriggerOnNewPresence(sp); 3067
3068 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2956 3069
2957 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3070 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3071
3072/* done in completMovement
3073 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
3074 if (cof == null)
3075 sp.COF = UUID.Zero;
3076 else
3077 sp.COF = cof.ID;
3078
3079 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
3080 */
3081 m_eventManager.TriggerOnNewPresence(sp);
2958 } 3082 }
2959 else 3083 else
2960 { 3084 {
@@ -2963,7 +3087,7 @@ namespace OpenSim.Region.Framework.Scenes
2963 // XXX: This may be better set for a new client before that client is added to the client manager. 3087 // XXX: This may be better set for a new client before that client is added to the client manager.
2964 // But need to know what happens in the case where a ScenePresence is already present (and if this 3088 // But need to know what happens in the case where a ScenePresence is already present (and if this
2965 // actually occurs). 3089 // actually occurs).
2966 client.SceneAgent = sp; 3090
2967 3091
2968 m_log.WarnFormat( 3092 m_log.WarnFormat(
2969 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3093 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
@@ -2971,6 +3095,7 @@ namespace OpenSim.Region.Framework.Scenes
2971 3095
2972 reallyNew = false; 3096 reallyNew = false;
2973 } 3097 }
3098 client.SceneAgent = sp;
2974 3099
2975 // This is currently also being done earlier in NewUserConnection for real users to see if this 3100 // This is currently also being done earlier in NewUserConnection for real users to see if this
2976 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other 3101 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
@@ -3089,19 +3214,15 @@ namespace OpenSim.Region.Framework.Scenes
3089 // and the scene presence and the client, if they exist 3214 // and the scene presence and the client, if they exist
3090 try 3215 try
3091 { 3216 {
3092 // We need to wait for the client to make UDP contact first.
3093 // It's the UDP contact that creates the scene presence
3094 ScenePresence sp = WaitGetScenePresence(agentID); 3217 ScenePresence sp = WaitGetScenePresence(agentID);
3218
3095 if (sp != null) 3219 if (sp != null)
3096 { 3220 {
3097 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3221 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3098 3222
3099 CloseAgent(sp.UUID, false); 3223 CloseAgent(sp.UUID, false);
3100 } 3224 }
3101 else 3225
3102 {
3103 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
3104 }
3105 // BANG! SLASH! 3226 // BANG! SLASH!
3106 m_authenticateHandler.RemoveCircuit(agentID); 3227 m_authenticateHandler.RemoveCircuit(agentID);
3107 3228
@@ -3138,7 +3259,7 @@ namespace OpenSim.Region.Framework.Scenes
3138 3259
3139 public virtual void SubscribeToClientTerrainEvents(IClientAPI client) 3260 public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
3140 { 3261 {
3141 client.OnRegionHandShakeReply += SendLayerData; 3262// client.OnRegionHandShakeReply += SendLayerData;
3142 } 3263 }
3143 3264
3144 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3265 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
@@ -3146,6 +3267,8 @@ namespace OpenSim.Region.Framework.Scenes
3146 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3267 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
3147 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 3268 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
3148 3269
3270 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
3271
3149 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 3272 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
3150 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3273 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
3151 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3274 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -3202,6 +3325,7 @@ namespace OpenSim.Region.Framework.Scenes
3202 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3325 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
3203 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3326 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
3204 client.OnCopyInventoryItem += CopyInventoryItem; 3327 client.OnCopyInventoryItem += CopyInventoryItem;
3328 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
3205 client.OnMoveInventoryItem += MoveInventoryItem; 3329 client.OnMoveInventoryItem += MoveInventoryItem;
3206 client.OnRemoveInventoryItem += RemoveInventoryItem; 3330 client.OnRemoveInventoryItem += RemoveInventoryItem;
3207 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3331 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3263,7 +3387,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 3387
3264 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) 3388 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
3265 { 3389 {
3266 client.OnRegionHandShakeReply -= SendLayerData; 3390// client.OnRegionHandShakeReply -= SendLayerData;
3267 } 3391 }
3268 3392
3269 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 3393 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
@@ -3271,6 +3395,8 @@ namespace OpenSim.Region.Framework.Scenes
3271 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3395 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
3272 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3396 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
3273 3397
3398 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3399
3274 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3400 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3275 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3401 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3276 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3402 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3428,16 +3554,14 @@ namespace OpenSim.Region.Framework.Scenes
3428 if (target != null && target2 != null) 3554 if (target != null && target2 != null)
3429 { 3555 {
3430 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3556 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3431 Vector3 AXOrigin = RayStart; 3557
3432 Vector3 AXdirection = direction;
3433
3434 pos = target2.AbsolutePosition; 3558 pos = target2.AbsolutePosition;
3435 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); 3559 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
3436 3560
3437 // TODO: Raytrace better here 3561 // TODO: Raytrace better here
3438 3562
3439 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 3563 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
3440 Ray NewRay = new Ray(AXOrigin, AXdirection); 3564 Ray NewRay = new Ray(RayStart,direction);
3441 3565
3442 // Ray Trace against target here 3566 // Ray Trace against target here
3443 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); 3567 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
@@ -3519,6 +3643,10 @@ namespace OpenSim.Region.Framework.Scenes
3519 /// <param name='closeChildAgents'> 3643 /// <param name='closeChildAgents'>
3520 /// Close the neighbour child agents associated with this client. 3644 /// Close the neighbour child agents associated with this client.
3521 /// </param> 3645 /// </param>
3646 ///
3647
3648 private object m_removeClientPrivLock = new Object();
3649
3522 public void RemoveClient(UUID agentID, bool closeChildAgents) 3650 public void RemoveClient(UUID agentID, bool closeChildAgents)
3523 { 3651 {
3524 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3652 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
@@ -3535,8 +3663,8 @@ namespace OpenSim.Region.Framework.Scenes
3535 } 3663 }
3536 3664
3537 // TODO: Can we now remove this lock? 3665 // TODO: Can we now remove this lock?
3538 lock (acd) 3666 lock (m_removeClientPrivLock)
3539 { 3667 {
3540 bool isChildAgent = false; 3668 bool isChildAgent = false;
3541 3669
3542 ScenePresence avatar = GetScenePresence(agentID); 3670 ScenePresence avatar = GetScenePresence(agentID);
@@ -3580,8 +3708,8 @@ namespace OpenSim.Region.Framework.Scenes
3580 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3708 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3581 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3709 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3582 if (closeChildAgents && CapsModule != null) 3710 if (closeChildAgents && CapsModule != null)
3583 CapsModule.RemoveCaps(agentID); 3711 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3584 3712
3585 if (closeChildAgents && !isChildAgent) 3713 if (closeChildAgents && !isChildAgent)
3586 { 3714 {
3587 List<ulong> regions = avatar.KnownRegionHandles; 3715 List<ulong> regions = avatar.KnownRegionHandles;
@@ -3592,13 +3720,17 @@ namespace OpenSim.Region.Framework.Scenes
3592 } 3720 }
3593 3721
3594 m_eventManager.TriggerClientClosed(agentID, this); 3722 m_eventManager.TriggerClientClosed(agentID, this);
3723// m_log.Debug("[Scene]TriggerClientClosed done");
3595 m_eventManager.TriggerOnRemovePresence(agentID); 3724 m_eventManager.TriggerOnRemovePresence(agentID);
3596 3725// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3726
3597 if (!isChildAgent) 3727 if (!isChildAgent)
3598 { 3728 {
3599 if (AttachmentsModule != null) 3729 if (AttachmentsModule != null)
3600 { 3730 {
3731// m_log.Debug("[Scene]DeRezAttachments");
3601 AttachmentsModule.DeRezAttachments(avatar); 3732 AttachmentsModule.DeRezAttachments(avatar);
3733// m_log.Debug("[Scene]DeRezAttachments done");
3602 } 3734 }
3603 3735
3604 ForEachClient( 3736 ForEachClient(
@@ -3612,7 +3744,11 @@ namespace OpenSim.Region.Framework.Scenes
3612 3744
3613 // It's possible for child agents to have transactions if changes are being made cross-border. 3745 // It's possible for child agents to have transactions if changes are being made cross-border.
3614 if (AgentTransactionsModule != null) 3746 if (AgentTransactionsModule != null)
3747 {
3748// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3615 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3749 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3750 }
3751 m_log.Debug("[Scene] The avatar has left the building");
3616 } 3752 }
3617 catch (Exception e) 3753 catch (Exception e)
3618 { 3754 {
@@ -3731,6 +3867,9 @@ namespace OpenSim.Region.Framework.Scenes
3731 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3867 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3732 /// <returns>True if the region accepts this agent. False if it does not. False will 3868 /// <returns>True if the region accepts this agent. False if it does not. False will
3733 /// also return a reason.</returns> 3869 /// also return a reason.</returns>
3870 ///
3871 private object m_newUserConnLock = new object();
3872
3734 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) 3873 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3735 { 3874 {
3736 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3875 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
@@ -3764,6 +3903,8 @@ namespace OpenSim.Region.Framework.Scenes
3764 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) 3903 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3765 ); 3904 );
3766 3905
3906// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3907
3767 if (!LoginsEnabled) 3908 if (!LoginsEnabled)
3768 { 3909 {
3769 reason = "Logins Disabled"; 3910 reason = "Logins Disabled";
@@ -3891,7 +4032,7 @@ namespace OpenSim.Region.Framework.Scenes
3891 } 4032 }
3892 4033
3893 // TODO: can we remove this lock? 4034 // TODO: can we remove this lock?
3894 lock (acd) 4035 lock (m_newUserConnLock)
3895 { 4036 {
3896 if (sp != null && !sp.IsChildAgent) 4037 if (sp != null && !sp.IsChildAgent)
3897 { 4038 {
@@ -3918,6 +4059,12 @@ namespace OpenSim.Region.Framework.Scenes
3918 // We need the circuit data here for some of the subsequent checks. (groups, for example) 4059 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3919 // If the checks fail, we remove the circuit. 4060 // If the checks fail, we remove the circuit.
3920 acd.teleportFlags = teleportFlags; 4061 acd.teleportFlags = teleportFlags;
4062
4063 // Remove any preexisting circuit - we don't want duplicates
4064 // This is a stab at preventing avatar "ghosting"
4065 if (vialogin)
4066 m_authenticateHandler.RemoveCircuit(acd.AgentID);
4067
3921 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); 4068 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3922 4069
3923 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); 4070 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
@@ -3925,6 +4072,9 @@ namespace OpenSim.Region.Framework.Scenes
3925 // On login test land permisions 4072 // On login test land permisions
3926 if (vialogin) 4073 if (vialogin)
3927 { 4074 {
4075 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
4076 if (cache != null)
4077 cache.Remove(acd.firstname + " " + acd.lastname);
3928 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) 4078 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3929 { 4079 {
3930 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4080 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
@@ -3979,7 +4129,7 @@ namespace OpenSim.Region.Framework.Scenes
3979 if (CapsModule != null) 4129 if (CapsModule != null)
3980 { 4130 {
3981 CapsModule.SetAgentCapsSeeds(acd); 4131 CapsModule.SetAgentCapsSeeds(acd);
3982 CapsModule.CreateCaps(acd.AgentID); 4132 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
3983 } 4133 }
3984 } 4134 }
3985 else 4135 else
@@ -3992,15 +4142,15 @@ namespace OpenSim.Region.Framework.Scenes
3992 { 4142 {
3993 m_log.DebugFormat( 4143 m_log.DebugFormat(
3994 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4144 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3995 acd.AgentID, RegionInfo.RegionName); 4145 acd.AgentID, RegionInfo.RegionName);
3996
3997 sp.AdjustKnownSeeds();
3998 4146
3999 if (CapsModule != null) 4147 if (CapsModule != null)
4000 { 4148 {
4001 CapsModule.SetAgentCapsSeeds(acd); 4149 CapsModule.SetAgentCapsSeeds(acd);
4002 CapsModule.CreateCaps(acd.AgentID); 4150 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4003 } 4151 }
4152
4153 sp.AdjustKnownSeeds();
4004 } 4154 }
4005 } 4155 }
4006 4156
@@ -4010,6 +4160,11 @@ namespace OpenSim.Region.Framework.Scenes
4010 CacheUserName(null, acd); 4160 CacheUserName(null, acd);
4011 } 4161 }
4012 4162
4163 if (CapsModule != null)
4164 {
4165 CapsModule.ActivateCaps(acd.circuitcode);
4166 }
4167
4013 if (vialogin) 4168 if (vialogin)
4014 { 4169 {
4015// CleanDroppedAttachments(); 4170// CleanDroppedAttachments();
@@ -4079,6 +4234,8 @@ namespace OpenSim.Region.Framework.Scenes
4079 } 4234 }
4080 4235
4081 // Honor parcel landing type and position. 4236 // Honor parcel landing type and position.
4237 /*
4238 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
4082 if (land != null) 4239 if (land != null)
4083 { 4240 {
4084 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4241 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -4093,6 +4250,7 @@ namespace OpenSim.Region.Framework.Scenes
4093 } 4250 }
4094 } 4251 }
4095 } 4252 }
4253 */// This is now handled properly in ScenePresence.MakeRootAgent
4096 } 4254 }
4097 4255
4098 return true; 4256 return true;
@@ -4117,12 +4275,13 @@ namespace OpenSim.Region.Framework.Scenes
4117 { 4275 {
4118 if (posX < 0) 4276 if (posX < 0)
4119 posX = 0; 4277 posX = 0;
4120 else if (posX >= (float)RegionInfo.RegionSizeX) 4278
4121 posX = (float)RegionInfo.RegionSizeX - 0.001f; 4279 else if (posX >= RegionInfo.RegionSizeX)
4280 posX = RegionInfo.RegionSizeX - 0.5f;
4122 if (posY < 0) 4281 if (posY < 0)
4123 posY = 0; 4282 posY = 0;
4124 else if (posY >= (float)RegionInfo.RegionSizeY) 4283 else if (posY >= RegionInfo.RegionSizeY)
4125 posY = (float)RegionInfo.RegionSizeY - 0.001f; 4284 posY = RegionInfo.RegionSizeY - 0.5f;
4126 4285
4127 reason = String.Empty; 4286 reason = String.Empty;
4128 if (Permissions.IsGod(agentID)) 4287 if (Permissions.IsGod(agentID))
@@ -4226,7 +4385,8 @@ namespace OpenSim.Region.Framework.Scenes
4226 { 4385 {
4227 if (RegionInfo.EstateSettings != null) 4386 if (RegionInfo.EstateSettings != null)
4228 { 4387 {
4229 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 4388 int flags = GetUserFlags(agent.AgentID);
4389 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4230 { 4390 {
4231 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4391 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4232 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4392 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -4415,6 +4575,22 @@ namespace OpenSim.Region.Framework.Scenes
4415 m_log.DebugFormat( 4575 m_log.DebugFormat(
4416 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4576 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4417 4577
4578 if (!LoginsEnabled)
4579 {
4580// reason = "Logins Disabled";
4581 m_log.DebugFormat(
4582 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4583 return false;
4584 }
4585 // We have to wait until the viewer contacts this region after receiving EAC.
4586 // That calls AddNewClient, which finally creates the ScenePresence
4587 int flags = GetUserFlags(cAgentData.AgentID);
4588 if (RegionInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4589 {
4590 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4591 return false;
4592 }
4593
4418 // TODO: This check should probably be in QueryAccess(). 4594 // TODO: This check should probably be in QueryAccess().
4419 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); 4595 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4420 if (nearestParcel == null) 4596 if (nearestParcel == null)
@@ -4432,8 +4608,14 @@ namespace OpenSim.Region.Framework.Scenes
4432 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. 4608 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4433 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4609 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4434 4610
4435 if (sp != null) 4611 if (sp != null)
4436 { 4612 {
4613 if (!sp.IsChildAgent)
4614 {
4615 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4616 sp.Name, sp.UUID, Name);
4617 return false;
4618 }
4437 if (cAgentData.SessionID != sp.ControllingClient.SessionId) 4619 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4438 { 4620 {
4439 m_log.WarnFormat( 4621 m_log.WarnFormat(
@@ -4518,7 +4700,7 @@ namespace OpenSim.Region.Framework.Scenes
4518 /// <param name='agentID'></param> 4700 /// <param name='agentID'></param>
4519 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4701 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4520 { 4702 {
4521 int ntimes = 20; 4703 int ntimes = 30;
4522 ScenePresence sp = null; 4704 ScenePresence sp = null;
4523 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4705 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4524 Thread.Sleep(1000); 4706 Thread.Sleep(1000);
@@ -4568,6 +4750,16 @@ namespace OpenSim.Region.Framework.Scenes
4568 return false; 4750 return false;
4569 } 4751 }
4570 4752
4753// public bool IncomingCloseAgent(UUID agentID)
4754// {
4755// return IncomingCloseAgent(agentID, false);
4756// }
4757
4758// public bool IncomingCloseChildAgent(UUID agentID)
4759// {
4760// return IncomingCloseAgent(agentID, true);
4761// }
4762
4571 /// <summary> 4763 /// <summary>
4572 /// Tell a single client to prepare to close. 4764 /// Tell a single client to prepare to close.
4573 /// </summary> 4765 /// </summary>
@@ -4630,6 +4822,20 @@ namespace OpenSim.Region.Framework.Scenes
4630 4822
4631 if (sp == null) 4823 if (sp == null)
4632 { 4824 {
4825 // If there is no scene presence, we may be handling a dead
4826 // client. These can keep an avatar from reentering a region
4827 // and since they don't get cleaned up they will stick
4828 // around until region restart. So, if there is no SP,
4829 // remove the client as well.
4830 IClientAPI client = null;
4831 if (m_clientManager.TryGetValue(agentID, out client))
4832 {
4833 m_clientManager.Remove(agentID);
4834 if (CapsModule != null)
4835 CapsModule.RemoveCaps(agentID, 0);
4836 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4837 return true;
4838 }
4633 m_log.DebugFormat( 4839 m_log.DebugFormat(
4634 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", 4840 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4635 agentID, Name); 4841 agentID, Name);
@@ -4664,7 +4870,11 @@ namespace OpenSim.Region.Framework.Scenes
4664 sp.LifecycleState = ScenePresenceState.Removing; 4870 sp.LifecycleState = ScenePresenceState.Removing;
4665 } 4871 }
4666 4872
4667 sp.ControllingClient.Close(force); 4873 if (sp != null)
4874 {
4875 sp.ControllingClient.Close(force, force);
4876 return true;
4877 }
4668 4878
4669 return true; 4879 return true;
4670 } 4880 }
@@ -4826,7 +5036,10 @@ namespace OpenSim.Region.Framework.Scenes
4826 5036
4827 public LandData GetLandData(float x, float y) 5037 public LandData GetLandData(float x, float y)
4828 { 5038 {
4829 return LandChannel.GetLandObject(x, y).LandData; 5039 ILandObject parcel = LandChannel.GetLandObject(x, y);
5040 if (parcel == null)
5041 return null;
5042 return parcel.LandData;
4830 } 5043 }
4831 5044
4832 /// <summary> 5045 /// <summary>
@@ -4842,7 +5055,10 @@ namespace OpenSim.Region.Framework.Scenes
4842 public LandData GetLandData(uint x, uint y) 5055 public LandData GetLandData(uint x, uint y)
4843 { 5056 {
4844 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5057 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4845 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5058 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5059 if (parcel == null)
5060 return null;
5061 return parcel.LandData;
4846 } 5062 }
4847 5063
4848 #endregion 5064 #endregion
@@ -5230,7 +5446,7 @@ namespace OpenSim.Region.Framework.Scenes
5230 { 5446 {
5231 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5447 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5232 { 5448 {
5233 if (grp.RootPart.Expires <= DateTime.Now) 5449 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= DateTime.Now)
5234 DeleteSceneObject(grp, false); 5450 DeleteSceneObject(grp, false);
5235 } 5451 }
5236 } 5452 }
@@ -5244,35 +5460,80 @@ namespace OpenSim.Region.Framework.Scenes
5244 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 5460 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
5245 } 5461 }
5246 5462
5247 public int GetHealth() 5463 public int GetHealth(out int flags, out string message)
5248 { 5464 {
5249 // Returns: 5465 // Returns:
5250 // 1 = sim is up and accepting http requests. The heartbeat has 5466 // 1 = sim is up and accepting http requests. The heartbeat has
5251 // stopped and the sim is probably locked up, but a remote 5467 // stopped and the sim is probably locked up, but a remote
5252 // admin restart may succeed 5468 // admin restart may succeed
5253 // 5469 //
5254 // 2 = Sim is up and the heartbeat is running. The sim is likely 5470 // 2 = Sim is up and the heartbeat is running. The sim is likely
5255 // usable for people within and logins _may_ work 5471 // usable for people within
5256 // 5472 //
5257 // 3 = We have seen a new user enter within the past 4 minutes 5473 // 3 = Sim is up and one packet thread is running. Sim is
5474 // unstable and will not accept new logins
5475 //
5476 // 4 = Sim is up and both packet threads are running. Sim is
5477 // likely usable
5478 //
5479 // 5 = We have seen a new user enter within the past 4 minutes
5258 // which can be seen as positive confirmation of sim health 5480 // which can be seen as positive confirmation of sim health
5259 // 5481 //
5260 int health = 1; // Start at 1, means we're up 5482 int health = 1; // Start at 1, means we're up
5261 5483
5484 flags = 0;
5485 message = String.Empty;
5486
5487 CheckHeartbeat();
5488
5489 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
5490 {
5491 // We're still starting
5492 // 0 means "in startup", it can't happen another way, since
5493 // to get here, we must be able to accept http connections
5494 return 0;
5495 }
5496
5262 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5497 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
5263 health += 1; 5498 {
5499 health+=1;
5500 flags |= 1;
5501 }
5502
5503 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
5504 {
5505 health+=1;
5506 flags |= 2;
5507 }
5508
5509 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
5510 {
5511 health+=1;
5512 flags |= 4;
5513 }
5264 else 5514 else
5515 {
5516int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
5517System.Diagnostics.Process proc = new System.Diagnostics.Process();
5518proc.EnableRaisingEvents=false;
5519proc.StartInfo.FileName = "/bin/kill";
5520proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
5521proc.Start();
5522proc.WaitForExit();
5523Thread.Sleep(1000);
5524Environment.Exit(1);
5525 }
5526
5527 if (flags != 7)
5265 return health; 5528 return health;
5266 5529
5267 // A login in the last 4 mins? We can't be doing too badly 5530 // A login in the last 4 mins? We can't be doing too badly
5268 // 5531 //
5269 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 5532 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
5270 health++; 5533 health++;
5271 else 5534 else
5272 return health; 5535 return health;
5273 5536
5274// CheckHeartbeat();
5275
5276 return health; 5537 return health;
5277 } 5538 }
5278 5539
@@ -5360,7 +5621,7 @@ namespace OpenSim.Region.Framework.Scenes
5360 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 5621 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
5361 if (wasUsingPhysics) 5622 if (wasUsingPhysics)
5362 { 5623 {
5363 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 5624 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
5364 } 5625 }
5365 } 5626 }
5366 5627
@@ -5463,14 +5724,14 @@ namespace OpenSim.Region.Framework.Scenes
5463 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5724 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
5464 } 5725 }
5465 5726
5466// private void CheckHeartbeat() 5727 private void CheckHeartbeat()
5467// { 5728 {
5468// if (m_firstHeartbeat) 5729 if (m_firstHeartbeat)
5469// return; 5730 return;
5470// 5731
5471// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5732 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
5472// StartTimer(); 5733 Start();
5473// } 5734 }
5474 5735
5475 public override ISceneObject DeserializeObject(string representation) 5736 public override ISceneObject DeserializeObject(string representation)
5476 { 5737 {
@@ -5527,8 +5788,7 @@ namespace OpenSim.Region.Framework.Scenes
5527 //Go to the edge, this happens in teleporting to a region with no available parcels 5788 //Go to the edge, this happens in teleporting to a region with no available parcels
5528 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5789 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5529 5790
5530 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5791 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5531
5532 return nearestRegionEdgePoint; 5792 return nearestRegionEdgePoint;
5533 } 5793 }
5534 5794
@@ -5784,7 +6044,55 @@ namespace OpenSim.Region.Framework.Scenes
5784 mapModule.GenerateMaptile(); 6044 mapModule.GenerateMaptile();
5785 } 6045 }
5786 6046
5787 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 6047// public void CleanDroppedAttachments()
6048// {
6049// List<SceneObjectGroup> objectsToDelete =
6050// new List<SceneObjectGroup>();
6051//
6052// lock (m_cleaningAttachments)
6053// {
6054// ForEachSOG(delegate (SceneObjectGroup grp)
6055// {
6056// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
6057// {
6058// UUID agentID = grp.OwnerID;
6059// if (agentID == UUID.Zero)
6060// {
6061// objectsToDelete.Add(grp);
6062// return;
6063// }
6064//
6065// ScenePresence sp = GetScenePresence(agentID);
6066// if (sp == null)
6067// {
6068// objectsToDelete.Add(grp);
6069// return;
6070// }
6071// }
6072// });
6073// }
6074//
6075// foreach (SceneObjectGroup grp in objectsToDelete)
6076// {
6077// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
6078// DeleteSceneObject(grp, true);
6079// }
6080// }
6081
6082 public void ThreadAlive(int threadCode)
6083 {
6084 switch(threadCode)
6085 {
6086 case 1: // Incoming
6087 m_lastIncoming = Util.EnvironmentTickCount();
6088 break;
6089 case 2: // Incoming
6090 m_lastOutgoing = Util.EnvironmentTickCount();
6091 break;
6092 }
6093 }
6094
6095 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5788 { 6096 {
5789 RegenerateMaptile(); 6097 RegenerateMaptile();
5790 6098
@@ -5950,7 +6258,19 @@ namespace OpenSim.Region.Framework.Scenes
5950 return true; 6258 return true;
5951 } 6259 }
5952 6260
5953 /// <summary> 6261 public void StartTimerWatchdog()
6262 {
6263 m_timerWatchdog.Interval = 1000;
6264 m_timerWatchdog.Elapsed += TimerWatchdog;
6265 m_timerWatchdog.AutoReset = true;
6266 m_timerWatchdog.Start();
6267 }
6268
6269 public void TimerWatchdog(object sender, ElapsedEventArgs e)
6270 {
6271 CheckHeartbeat();
6272 }
6273
5954 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 6274 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5955 /// autopilot that moves an avatar to a sit target!. 6275 /// autopilot that moves an avatar to a sit target!.
5956 /// </summary> 6276 /// </summary>
@@ -6029,6 +6349,11 @@ namespace OpenSim.Region.Framework.Scenes
6029 return m_SpawnPoint - 1; 6349 return m_SpawnPoint - 1;
6030 } 6350 }
6031 6351
6352 private void HandleGcCollect(string module, string[] args)
6353 {
6354 GC.Collect();
6355 }
6356
6032 /// <summary> 6357 /// <summary>
6033 /// Wrappers to get physics modules retrieve assets. 6358 /// Wrappers to get physics modules retrieve assets.
6034 /// </summary> 6359 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 7ff3d40..f420f69 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// If -1 then updates until shutdown. 200 /// If -1 then updates until shutdown.
201 /// </param> 201 /// </param>
202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns> 202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns>
203 public abstract bool Update(int frames); 203 public abstract void Update(int frames);
204 204
205 #endregion 205 #endregion
206 206
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b9526da..28df1c1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -218,8 +218,11 @@ namespace OpenSim.Region.Framework.Scenes
218 } 218 }
219 } 219 }
220 220
221 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
222
221 /// <summary> 223 /// <summary>
222 /// Closes a child agent on a given region 224 /// This Closes child agents on neighboring regions
225 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
223 /// </summary> 226 /// </summary>
224 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token) 227 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
225 { 228 {
@@ -247,7 +250,7 @@ namespace OpenSim.Region.Framework.Scenes
247 { 250 {
248 foreach (ulong handle in regionslst) 251 foreach (ulong handle in regionslst)
249 { 252 {
250 // We must take a copy here since handle is acts like a reference when used in an iterator. 253 // We must take a copy here since handle acts like a reference when used in an iterator.
251 // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region. 254 // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region.
252 ulong handleCopy = handle; 255 ulong handleCopy = handle;
253 Util.FireAndForget( 256 Util.FireAndForget(
@@ -256,10 +259,10 @@ namespace OpenSim.Region.Framework.Scenes
256 "SceneCommunicationService.SendCloseChildAgentConnections"); 259 "SceneCommunicationService.SendCloseChildAgentConnections");
257 } 260 }
258 } 261 }
259 262
260 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 263 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
261 { 264 {
262 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 265 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
263 } 266 }
264 } 267 }
265} \ No newline at end of file 268}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e0080f2..0a22bb3 100755
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -134,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
134 144
135 protected internal void Close() 145 protected internal void Close()
136 { 146 {
137 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
138 { 149 {
139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
140 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
141 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
142 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
143 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
144 159
145 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
146 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -261,13 +276,54 @@ namespace OpenSim.Region.Framework.Scenes
261 protected internal bool AddRestoredSceneObject( 276 protected internal bool AddRestoredSceneObject(
262 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 277 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
263 { 278 {
279 if (!m_parentScene.CombineRegions)
280 {
281 // temporary checks to remove after varsize suport
282 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
283 if (regionSizeX == 0)
284 regionSizeX = Constants.RegionSize;
285 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
286 if (regionSizeY == 0)
287 regionSizeY = Constants.RegionSize;
288
289 // KF: Check for out-of-region, move inside and make static.
290 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
291 sceneObject.RootPart.GroupPosition.Y,
292 sceneObject.RootPart.GroupPosition.Z);
293 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 ||
294 npos.X > regionSizeX ||
295 npos.Y > regionSizeY))
296 {
297 if (npos.X < 0.0) npos.X = 1.0f;
298 if (npos.Y < 0.0) npos.Y = 1.0f;
299 if (npos.Z < 0.0) npos.Z = 0.0f;
300 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
301 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
302
303 SceneObjectPart rootpart = sceneObject.RootPart;
304 rootpart.GroupPosition = npos;
305
306 foreach (SceneObjectPart part in sceneObject.Parts)
307 {
308 if (part == rootpart)
309 continue;
310 part.GroupPosition = npos;
311 }
312 rootpart.Velocity = Vector3.Zero;
313 rootpart.AngularVelocity = Vector3.Zero;
314 rootpart.Acceleration = Vector3.Zero;
315 }
316 }
317
318 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
319
264 if (attachToBackup && (!alreadyPersisted)) 320 if (attachToBackup && (!alreadyPersisted))
265 { 321 {
266 sceneObject.ForceInventoryPersistence(); 322 sceneObject.ForceInventoryPersistence();
267 sceneObject.HasGroupChanged = true; 323 sceneObject.HasGroupChanged = true;
268 } 324 }
269 325
270 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 326 return ret;
271 } 327 }
272 328
273 /// <summary> 329 /// <summary>
@@ -284,12 +340,16 @@ namespace OpenSim.Region.Framework.Scenes
284 /// </returns> 340 /// </returns>
285 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 341 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
286 { 342 {
287 // Ensure that we persist this new scene object if it's not an 343
344 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
345
346 // Ensure that we persist this new scene object if it's not an
288 // attachment 347 // attachment
348
289 if (attachToBackup) 349 if (attachToBackup)
290 sceneObject.HasGroupChanged = true; 350 sceneObject.HasGroupChanged = true;
291 351
292 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 352 return ret;
293 } 353 }
294 354
295 /// <summary> 355 /// <summary>
@@ -324,9 +384,8 @@ namespace OpenSim.Region.Framework.Scenes
324 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 384 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
325 { 385 {
326 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 386 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
327 sceneObject.Velocity = vel;
328 } 387 }
329 388
330 return true; 389 return true;
331 } 390 }
332 391
@@ -351,6 +410,11 @@ namespace OpenSim.Region.Framework.Scenes
351 /// </returns> 410 /// </returns>
352 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 411 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
353 { 412 {
413 if (sceneObject == null)
414 {
415 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
416 return false;
417 }
354 if (sceneObject.UUID == UUID.Zero) 418 if (sceneObject.UUID == UUID.Zero)
355 { 419 {
356 m_log.ErrorFormat( 420 m_log.ErrorFormat(
@@ -383,9 +447,9 @@ namespace OpenSim.Region.Framework.Scenes
383 { 447 {
384 Vector3 scale = part.Shape.Scale; 448 Vector3 scale = part.Shape.Scale;
385 449
386 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 450 scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
387 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 451 scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
388 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 452 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
389 453
390 part.Shape.Scale = scale; 454 part.Shape.Scale = scale;
391 } 455 }
@@ -406,36 +470,39 @@ namespace OpenSim.Region.Framework.Scenes
406 470
407 sceneObject.AttachToScene(m_parentScene); 471 sceneObject.AttachToScene(m_parentScene);
408 472
409 if (sendClientUpdates)
410 sceneObject.ScheduleGroupForFullUpdate();
411
412 Entities.Add(sceneObject); 473 Entities.Add(sceneObject);
413 474
414 if (attachToBackup)
415 sceneObject.AttachToBackup();
416
417 lock (SceneObjectGroupsByFullID) 475 lock (SceneObjectGroupsByFullID)
418 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 476 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
419 477
420 lock (SceneObjectGroupsByFullPartID) 478 foreach (SceneObjectPart part in parts)
421 { 479 {
422 foreach (SceneObjectPart part in parts) 480 lock (SceneObjectGroupsByFullPartID)
423 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 481 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
424 }
425 482
426 lock (SceneObjectGroupsByLocalPartID) 483 lock (SceneObjectGroupsByLocalPartID)
427 {
428// m_log.DebugFormat(
429// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
430// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
431
432 foreach (SceneObjectPart part in parts)
433 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 484 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
434 } 485 }
435 486
487 if (sendClientUpdates)
488 sceneObject.ScheduleGroupForFullUpdate();
489
490 if (attachToBackup)
491 sceneObject.AttachToBackup();
492
436 return true; 493 return true;
437 } 494 }
438 495
496 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
497 {
498 // no tests, caller has responsability...
499 lock (SceneObjectGroupsByFullPartID)
500 SceneObjectGroupsByFullPartID[part.UUID] = grp;
501
502 lock (SceneObjectGroupsByLocalPartID)
503 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
504 }
505
439 /// <summary> 506 /// <summary>
440 /// Delete an object from the scene 507 /// Delete an object from the scene
441 /// </summary> 508 /// </summary>
@@ -476,25 +543,23 @@ namespace OpenSim.Region.Framework.Scenes
476 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 543 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
477 RemovePhysicalPrim(grp.PrimCount); 544 RemovePhysicalPrim(grp.PrimCount);
478 } 545 }
479 546
547 bool ret = Entities.Remove(uuid);
548
480 lock (SceneObjectGroupsByFullID) 549 lock (SceneObjectGroupsByFullID)
481 SceneObjectGroupsByFullID.Remove(grp.UUID); 550 SceneObjectGroupsByFullID.Remove(grp.UUID);
482 551
483 lock (SceneObjectGroupsByFullPartID) 552 SceneObjectPart[] parts = grp.Parts;
553 for (int i = 0; i < parts.Length; i++)
484 { 554 {
485 SceneObjectPart[] parts = grp.Parts; 555 lock (SceneObjectGroupsByFullPartID)
486 for (int i = 0; i < parts.Length; i++)
487 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 556 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
488 }
489 557
490 lock (SceneObjectGroupsByLocalPartID) 558 lock (SceneObjectGroupsByLocalPartID)
491 {
492 SceneObjectPart[] parts = grp.Parts;
493 for (int i = 0; i < parts.Length; i++)
494 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 559 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
495 } 560 }
496 561
497 return Entities.Remove(uuid); 562 return ret;
498 } 563 }
499 564
500 /// <summary> 565 /// <summary>
@@ -509,6 +574,30 @@ namespace OpenSim.Region.Framework.Scenes
509 m_updateList[obj.UUID] = obj; 574 m_updateList[obj.UUID] = obj;
510 } 575 }
511 576
577 public void FireAttachToBackup(SceneObjectGroup obj)
578 {
579 if (OnAttachToBackup != null)
580 {
581 OnAttachToBackup(obj);
582 }
583 }
584
585 public void FireDetachFromBackup(SceneObjectGroup obj)
586 {
587 if (OnDetachFromBackup != null)
588 {
589 OnDetachFromBackup(obj);
590 }
591 }
592
593 public void FireChangeBackup(SceneObjectGroup obj)
594 {
595 if (OnChangeBackup != null)
596 {
597 OnChangeBackup(obj);
598 }
599 }
600
512 /// <summary> 601 /// <summary>
513 /// Process all pending updates 602 /// Process all pending updates
514 /// </summary> 603 /// </summary>
@@ -600,7 +689,8 @@ namespace OpenSim.Region.Framework.Scenes
600 689
601 Entities[presence.UUID] = presence; 690 Entities[presence.UUID] = presence;
602 691
603 lock (m_presenceLock) 692 m_scenePresencesLock.EnterWriteLock();
693 try
604 { 694 {
605 m_numChildAgents++; 695 m_numChildAgents++;
606 696
@@ -626,6 +716,10 @@ namespace OpenSim.Region.Framework.Scenes
626 m_scenePresenceMap = newmap; 716 m_scenePresenceMap = newmap;
627 m_scenePresenceArray = newlist; 717 m_scenePresenceArray = newlist;
628 } 718 }
719 finally
720 {
721 m_scenePresencesLock.ExitWriteLock();
722 }
629 723
630 return presence; 724 return presence;
631 } 725 }
@@ -642,7 +736,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 736 agentID);
643 } 737 }
644 738
645 lock (m_presenceLock) 739 m_scenePresencesLock.EnterWriteLock();
740 try
646 { 741 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 742 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 743 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +759,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 759 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 760 }
666 } 761 }
762 finally
763 {
764 m_scenePresencesLock.ExitWriteLock();
765 }
667 } 766 }
668 767
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 768 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -892,7 +991,7 @@ namespace OpenSim.Region.Framework.Scenes
892 m_log.WarnFormat( 991 m_log.WarnFormat(
893 "[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}.", 992 "[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}.",
894 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); 993 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
895 994 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
896 SceneObjectGroupsByLocalPartID.Remove(localID); 995 SceneObjectGroupsByLocalPartID.Remove(localID);
897 } 996 }
898 } 997 }
@@ -1228,6 +1327,52 @@ namespace OpenSim.Region.Framework.Scenes
1228 1327
1229 #region Client Event handlers 1328 #region Client Event handlers
1230 1329
1330 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1331 {
1332 SceneObjectPart part = GetSceneObjectPart(localID);
1333 ObjectChangeData data = (ObjectChangeData)odata;
1334
1335 if (part != null)
1336 {
1337 SceneObjectGroup grp = part.ParentGroup;
1338 if (grp != null)
1339 {
1340 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1341 {
1342 // These two are exceptions SL makes in the interpretation
1343 // of the change flags. Must check them here because otherwise
1344 // the group flag (see below) would be lost
1345 if (data.change == ObjectChangeType.groupS)
1346 data.change = ObjectChangeType.primS;
1347 if (data.change == ObjectChangeType.groupPS)
1348 data.change = ObjectChangeType.primPS;
1349 part.StoreUndoState(data.change); // lets test only saving what we changed
1350 grp.doChangeObject(part, (ObjectChangeData)data);
1351 }
1352 else
1353 {
1354 // Is this any kind of group operation?
1355 if ((data.change & ObjectChangeType.Group) != 0)
1356 {
1357 // Is a move and/or rotation requested?
1358 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1359 {
1360 // Are we allowed to move it?
1361 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1362 {
1363 // Strip all but move and rotation from request
1364 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1365
1366 part.StoreUndoState(data.change);
1367 grp.doChangeObject(part, (ObjectChangeData)data);
1368 }
1369 }
1370 }
1371 }
1372 }
1373 }
1374 }
1375
1231 /// <summary> 1376 /// <summary>
1232 /// Update the scale of an individual prim. 1377 /// Update the scale of an individual prim.
1233 /// </summary> 1378 /// </summary>
@@ -1242,7 +1387,17 @@ namespace OpenSim.Region.Framework.Scenes
1242 { 1387 {
1243 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1388 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1244 { 1389 {
1390 bool physbuild = false;
1391 if (part.ParentGroup.RootPart.PhysActor != null)
1392 {
1393 part.ParentGroup.RootPart.PhysActor.Building = true;
1394 physbuild = true;
1395 }
1396
1245 part.Resize(scale); 1397 part.Resize(scale);
1398
1399 if (physbuild)
1400 part.ParentGroup.RootPart.PhysActor.Building = false;
1246 } 1401 }
1247 } 1402 }
1248 } 1403 }
@@ -1254,7 +1409,17 @@ namespace OpenSim.Region.Framework.Scenes
1254 { 1409 {
1255 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1410 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1256 { 1411 {
1412 bool physbuild = false;
1413 if (group.RootPart.PhysActor != null)
1414 {
1415 group.RootPart.PhysActor.Building = true;
1416 physbuild = true;
1417 }
1418
1257 group.GroupResize(scale); 1419 group.GroupResize(scale);
1420
1421 if (physbuild)
1422 group.RootPart.PhysActor.Building = false;
1258 } 1423 }
1259 } 1424 }
1260 } 1425 }
@@ -1393,8 +1558,13 @@ namespace OpenSim.Region.Framework.Scenes
1393 { 1558 {
1394 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1559 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1395 { 1560 {
1396 if (m_parentScene.AttachmentsModule != null) 1561 // Set the new attachment point data in the object
1397 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1562 byte attachmentPoint = group.GetAttachmentPoint();
1563 group.UpdateGroupPosition(pos);
1564 group.IsAttachment = false;
1565 group.AbsolutePosition = group.RootPart.AttachedPos;
1566 group.AttachmentPoint = attachmentPoint;
1567 group.HasGroupChanged = true;
1398 } 1568 }
1399 else 1569 else
1400 { 1570 {
@@ -1452,6 +1622,7 @@ namespace OpenSim.Region.Framework.Scenes
1452 // VolumeDetect can't be set via UI and will always be off when a change is made there 1622 // VolumeDetect can't be set via UI and will always be off when a change is made there
1453 // now only change volume dtc if phantom off 1623 // now only change volume dtc if phantom off
1454 1624
1625 bool wantedPhys = UsePhysics;
1455 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1626 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1456 { 1627 {
1457 bool vdtc; 1628 bool vdtc;
@@ -1468,10 +1639,17 @@ namespace OpenSim.Region.Framework.Scenes
1468 if (part != null) 1639 if (part != null)
1469 { 1640 {
1470 part.UpdateExtraPhysics(PhysData); 1641 part.UpdateExtraPhysics(PhysData);
1471 if (part.UpdatePhysRequired) 1642 if (part.UpdatePhysRequired && remoteClient != null)
1472 remoteClient.SendPartPhysicsProprieties(part); 1643 remoteClient.SendPartPhysicsProprieties(part);
1473 } 1644 }
1474 } 1645 }
1646
1647 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1648 {
1649 remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " +
1650 m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None");
1651 group.RootPart.ScheduleFullUpdate();
1652 }
1475 } 1653 }
1476 } 1654 }
1477 } 1655 }
@@ -1616,6 +1794,7 @@ namespace OpenSim.Region.Framework.Scenes
1616 { 1794 {
1617 part.Material = Convert.ToByte(material); 1795 part.Material = Convert.ToByte(material);
1618 group.HasGroupChanged = true; 1796 group.HasGroupChanged = true;
1797 remoteClient.SendPartPhysicsProprieties(part);
1619 } 1798 }
1620 } 1799 }
1621 } 1800 }
@@ -1694,12 +1873,14 @@ namespace OpenSim.Region.Framework.Scenes
1694 return; 1873 return;
1695 1874
1696 Monitor.Enter(m_updateLock); 1875 Monitor.Enter(m_updateLock);
1876
1697 try 1877 try
1698 { 1878 {
1879
1699 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1880 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1700 1881
1701 // We do this in reverse to get the link order of the prims correct 1882 // We do this in reverse to get the link order of the prims correct
1702 for (int i = 0 ; i < children.Count ; i++) 1883 for (int i = 0; i < children.Count; i++)
1703 { 1884 {
1704 SceneObjectGroup child = children[i].ParentGroup; 1885 SceneObjectGroup child = children[i].ParentGroup;
1705 1886
@@ -1710,9 +1891,13 @@ namespace OpenSim.Region.Framework.Scenes
1710 // Make sure no child prim is set for sale 1891 // Make sure no child prim is set for sale
1711 // So that, on delink, no prims are unwittingly 1892 // So that, on delink, no prims are unwittingly
1712 // left for sale and sold off 1893 // left for sale and sold off
1713 child.RootPart.ObjectSaleType = 0; 1894
1714 child.RootPart.SalePrice = 10; 1895 if (child != null)
1715 childGroups.Add(child); 1896 {
1897 child.RootPart.ObjectSaleType = 0;
1898 child.RootPart.SalePrice = 10;
1899 childGroups.Add(child);
1900 }
1716 } 1901 }
1717 1902
1718 foreach (SceneObjectGroup child in childGroups) 1903 foreach (SceneObjectGroup child in childGroups)
@@ -1741,6 +1926,17 @@ namespace OpenSim.Region.Framework.Scenes
1741 } 1926 }
1742 finally 1927 finally
1743 { 1928 {
1929/*
1930 lock (SceneObjectGroupsByLocalPartID)
1931 {
1932 foreach (SceneObjectPart part in parentGroup.Parts)
1933 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1934 }
1935*/
1936 parentGroup.AdjustChildPrimPermissions(false);
1937 parentGroup.HasGroupChanged = true;
1938 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1939 parentGroup.ScheduleGroupForFullUpdate();
1744 Monitor.Exit(m_updateLock); 1940 Monitor.Exit(m_updateLock);
1745 } 1941 }
1746 } 1942 }
@@ -1782,21 +1978,23 @@ namespace OpenSim.Region.Framework.Scenes
1782 1978
1783 SceneObjectGroup group = part.ParentGroup; 1979 SceneObjectGroup group = part.ParentGroup;
1784 if (!affectedGroups.Contains(group)) 1980 if (!affectedGroups.Contains(group))
1981 {
1785 affectedGroups.Add(group); 1982 affectedGroups.Add(group);
1983 }
1786 } 1984 }
1787 } 1985 }
1788 } 1986 }
1789 1987
1790 foreach (SceneObjectPart child in childParts) 1988 if (childParts.Count > 0)
1791 { 1989 {
1792 // Unlink all child parts from their groups 1990 foreach (SceneObjectPart child in childParts)
1793 // 1991 {
1794 child.ParentGroup.DelinkFromGroup(child, true); 1992 // Unlink all child parts from their groups
1795 1993 //
1796 // These are not in affected groups and will not be 1994 child.ParentGroup.DelinkFromGroup(child, true);
1797 // handled further. Do the honors here. 1995 child.ParentGroup.HasGroupChanged = true;
1798 child.ParentGroup.HasGroupChanged = true; 1996 child.ParentGroup.ScheduleGroupForFullUpdate();
1799 child.ParentGroup.ScheduleGroupForFullUpdate(); 1997 }
1800 } 1998 }
1801 1999
1802 foreach (SceneObjectPart root in rootParts) 2000 foreach (SceneObjectPart root in rootParts)
@@ -1810,52 +2008,58 @@ namespace OpenSim.Region.Framework.Scenes
1810 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 2008 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1811 int numChildren = newSet.Count; 2009 int numChildren = newSet.Count;
1812 2010
2011 if (numChildren == 1)
2012 break;
2013
1813 // If there are prims left in a link set, but the root is 2014 // If there are prims left in a link set, but the root is
1814 // slated for unlink, we need to do this 2015 // slated for unlink, we need to do this
2016 // Unlink the remaining set
1815 // 2017 //
1816 if (numChildren != 1) 2018 bool sendEventsToRemainder = false;
1817 { 2019 if (numChildren == 2) // only one child prim no re-link needed
1818 // Unlink the remaining set 2020 sendEventsToRemainder = true;
1819 //
1820 bool sendEventsToRemainder = true;
1821 if (numChildren > 1)
1822 sendEventsToRemainder = false;
1823 2021
1824 foreach (SceneObjectPart p in newSet) 2022 foreach (SceneObjectPart p in newSet)
2023 {
2024 if (p != group.RootPart)
1825 { 2025 {
1826 if (p != group.RootPart) 2026 group.DelinkFromGroup(p, sendEventsToRemainder);
1827 group.DelinkFromGroup(p, sendEventsToRemainder); 2027 if (sendEventsToRemainder) // finish single child prim now
2028 {
2029 p.ParentGroup.HasGroupChanged = true;
2030 p.ParentGroup.ScheduleGroupForFullUpdate();
2031 }
1828 } 2032 }
2033 }
2034
2035 // If there is more than one prim remaining, we
2036 // need to re-link
2037 //
2038 if (numChildren > 2)
2039 {
2040 // Remove old root
2041 //
2042 if (newSet.Contains(root))
2043 newSet.Remove(root);
1829 2044
1830 // If there is more than one prim remaining, we 2045 // Preserve link ordering
1831 // need to re-link
1832 // 2046 //
1833 if (numChildren > 2) 2047 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1834 { 2048 {
1835 // Remove old root 2049 return a.LinkNum.CompareTo(b.LinkNum);
1836 // 2050 });
1837 if (newSet.Contains(root))
1838 newSet.Remove(root);
1839
1840 // Preserve link ordering
1841 //
1842 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1843 {
1844 return a.LinkNum.CompareTo(b.LinkNum);
1845 });
1846 2051
1847 // Determine new root 2052 // Determine new root
1848 // 2053 //
1849 SceneObjectPart newRoot = newSet[0]; 2054 SceneObjectPart newRoot = newSet[0];
1850 newSet.RemoveAt(0); 2055 newSet.RemoveAt(0);
1851 2056
1852 foreach (SceneObjectPart newChild in newSet) 2057 foreach (SceneObjectPart newChild in newSet)
1853 newChild.ClearUpdateSchedule(); 2058 newChild.ClearUpdateSchedule();
1854 2059
1855 LinkObjects(newRoot, newSet); 2060 LinkObjects(newRoot, newSet);
1856 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2061// if (!affectedGroups.Contains(newRoot.ParentGroup))
1857 affectedGroups.Add(newRoot.ParentGroup); 2062// affectedGroups.Add(newRoot.ParentGroup);
1858 }
1859 } 2063 }
1860 } 2064 }
1861 2065
@@ -1863,6 +2067,12 @@ namespace OpenSim.Region.Framework.Scenes
1863 // 2067 //
1864 foreach (SceneObjectGroup g in affectedGroups) 2068 foreach (SceneObjectGroup g in affectedGroups)
1865 { 2069 {
2070 // Child prims that have been unlinked and deleted will
2071 // return unless the root is deleted. This will remove them
2072 // from the database. They will be rewritten immediately,
2073 // minus the rows for the unlinked child prims.
2074 g.AdjustChildPrimPermissions(false);
2075 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1866 g.TriggerScriptChangedEvent(Changed.LINK); 2076 g.TriggerScriptChangedEvent(Changed.LINK);
1867 g.HasGroupChanged = true; // Persist 2077 g.HasGroupChanged = true; // Persist
1868 g.ScheduleGroupForFullUpdate(); 2078 g.ScheduleGroupForFullUpdate();
@@ -1936,120 +2146,90 @@ namespace OpenSim.Region.Framework.Scenes
1936 /// <param name="GroupID"></param> 2146 /// <param name="GroupID"></param>
1937 /// <param name="rot"></param> 2147 /// <param name="rot"></param>
1938 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2148 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1939 public SceneObjectGroup DuplicateObject( 2149 /// <summary>
1940 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2150 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1941 { 2151 {
1942 Monitor.Enter(m_updateLock); 2152// m_log.DebugFormat(
2153// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2154// originalPrimID, offset, AgentID);
1943 2155
1944 try 2156 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2157 if (original != null)
1945 { 2158 {
1946 // m_log.DebugFormat( 2159 if (m_parentScene.Permissions.CanDuplicateObject(
1947 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1948 // originalPrimID, offset, AgentID);
1949
1950 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1951 if (original == null)
1952 {
1953 m_log.WarnFormat(
1954 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID);
1955
1956 return null;
1957 }
1958
1959 if (!m_parentScene.Permissions.CanDuplicateObject(
1960 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 2160 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1961 return null;
1962
1963 SceneObjectGroup copy = original.Copy(true);
1964 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1965
1966 if (original.OwnerID != AgentID)
1967 { 2161 {
1968 copy.SetOwnerId(AgentID); 2162 SceneObjectGroup copy = original.Copy(true);
1969 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); 2163 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1970 2164
1971 SceneObjectPart[] partList = copy.Parts; 2165 if (original.OwnerID != AgentID)
1972
1973 if (m_parentScene.Permissions.PropagatePermissions())
1974 { 2166 {
1975 foreach (SceneObjectPart child in partList) 2167 copy.SetOwnerId(AgentID);
2168 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
2169
2170 SceneObjectPart[] partList = copy.Parts;
2171
2172 if (m_parentScene.Permissions.PropagatePermissions())
1976 { 2173 {
1977 child.Inventory.ChangeInventoryOwner(AgentID); 2174 foreach (SceneObjectPart child in partList)
1978 child.TriggerScriptChangedEvent(Changed.OWNER); 2175 {
1979 child.ApplyNextOwnerPermissions(); 2176 child.Inventory.ChangeInventoryOwner(AgentID);
2177 child.TriggerScriptChangedEvent(Changed.OWNER);
2178 child.ApplyNextOwnerPermissions();
2179 }
1980 } 2180 }
1981 } 2181 }
1982 2182
1983 copy.RootPart.ObjectSaleType = 0; 2183 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1984 copy.RootPart.SalePrice = 10; 2184 Entities.Add(copy);
1985 }
1986 2185
1987 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2186 lock (SceneObjectGroupsByFullID)
1988 Entities.Add(copy); 2187 SceneObjectGroupsByFullID[copy.UUID] = copy;
1989
1990 lock (SceneObjectGroupsByFullID)
1991 SceneObjectGroupsByFullID[copy.UUID] = copy;
1992
1993 SceneObjectPart[] children = copy.Parts;
1994
1995 lock (SceneObjectGroupsByFullPartID)
1996 {
1997 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1998 foreach (SceneObjectPart part in children)
1999 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2000 }
2001
2002 lock (SceneObjectGroupsByLocalPartID)
2003 {
2004 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2005 foreach (SceneObjectPart part in children)
2006 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2007 }
2008 // PROBABLE END OF FIXME
2009 2188
2010 // Since we copy from a source group that is in selected 2189 SceneObjectPart[] parts = copy.Parts;
2011 // state, but the copy is shown deselected in the viewer, 2190 foreach (SceneObjectPart part in parts)
2012 // We need to clear the selection flag here, else that 2191 {
2013 // prim never gets persisted at all. The client doesn't 2192 lock (SceneObjectGroupsByFullPartID)
2014 // think it's selected, so it will never send a deselect... 2193 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2015 copy.IsSelected = false; 2194 lock (SceneObjectGroupsByLocalPartID)
2195 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2196 }
2016 2197
2017 m_numTotalPrim += copy.Parts.Length; 2198 // PROBABLE END OF FIXME
2018 2199
2019 // Go through all parts (primitives and meshes) of this Scene Object 2200 // Since we copy from a source group that is in selected
2020 foreach (SceneObjectPart part in copy.Parts) 2201 // state, but the copy is shown deselected in the viewer,
2021 { 2202 // We need to clear the selection flag here, else that
2022 // Keep track of the total number of meshes or geometric primitives now in the scene; 2203 // prim never gets persisted at all. The client doesn't
2023 // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to 2204 // think it's selected, so it will never send a deselect...
2024 // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives 2205 copy.IsSelected = false;
2025 if (part.GetPrimType() == PrimType.SCULPT)
2026 m_numMesh++;
2027 else
2028 m_numPrim++;
2029 }
2030 2206
2031 if (rot != Quaternion.Identity) 2207 m_numPrim += copy.Parts.Length;
2032 {
2033 copy.UpdateGroupRotationR(rot);
2034 }
2035 2208
2036 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2209 if (rot != Quaternion.Identity)
2037 copy.HasGroupChanged = true; 2210 {
2038 copy.ScheduleGroupForFullUpdate(); 2211 copy.UpdateGroupRotationR(rot);
2039 copy.ResumeScripts(); 2212 }
2213
2214 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
2215 copy.HasGroupChanged = true;
2216 copy.ScheduleGroupForFullUpdate();
2217 copy.ResumeScripts();
2040 2218
2041 // required for physics to update it's position 2219 // required for physics to update it's position
2042 copy.AbsolutePosition = copy.AbsolutePosition; 2220 copy.AbsolutePosition = copy.AbsolutePosition;
2043 2221
2044 return copy; 2222 return copy;
2223 }
2045 } 2224 }
2046 finally 2225 else
2047 { 2226 {
2048 Monitor.Exit(m_updateLock); 2227 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2049 } 2228 }
2229
2230 return null;
2050 } 2231 }
2051 2232
2052 /// <summary>
2053 /// Calculates the distance between two Vector3s 2233 /// Calculates the distance between two Vector3s
2054 /// </summary> 2234 /// </summary>
2055 /// <param name="v1"></param> 2235 /// <param name="v1"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 28f7896..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -99,11 +99,11 @@ namespace OpenSim.Region.Framework.Scenes
99 } 99 }
100 } 100 }
101 101
102 private readonly List<Scene> m_localScenes = new List<Scene>(); 102 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
103 103
104 public List<Scene> Scenes 104 public List<Scene> Scenes
105 { 105 {
106 get { return new List<Scene>(m_localScenes); } 106 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
107 } 107 }
108 108
109 /// <summary> 109 /// <summary>
@@ -120,13 +120,10 @@ namespace OpenSim.Region.Framework.Scenes
120 { 120 {
121 if (CurrentScene == null) 121 if (CurrentScene == null)
122 { 122 {
123 lock (m_localScenes) 123 List<Scene> sceneList = Scenes;
124 { 124 if (sceneList.Count == 0)
125 if (m_localScenes.Count > 0) 125 return null;
126 return m_localScenes[0]; 126 return sceneList[0];
127 else
128 return null;
129 }
130 } 127 }
131 else 128 else
132 { 129 {
@@ -138,41 +135,35 @@ namespace OpenSim.Region.Framework.Scenes
138 public SceneManager() 135 public SceneManager()
139 { 136 {
140 m_instance = this; 137 m_instance = this;
141 m_localScenes = new List<Scene>(); 138 m_localScenes = new DoubleDictionary<UUID, string, Scene>();
142 } 139 }
143 140
144 public void Close() 141 public void Close()
145 { 142 {
143 List<Scene> localScenes = null;
144
146 lock (m_localScenes) 145 lock (m_localScenes)
147 { 146 {
148 for (int i = 0; i < m_localScenes.Count; i++) 147 localScenes = Scenes;
149 { 148 }
150 m_localScenes[i].Close(); 149
151 } 150 for (int i = 0; i < localScenes.Count; i++)
151 {
152 localScenes[i].Close();
152 } 153 }
153 } 154 }
154 155
155 public void Close(Scene cscene) 156 public void Close(Scene cscene)
156 { 157 {
157 lock (m_localScenes) 158 if (!m_localScenes.ContainsKey(cscene.RegionInfo.RegionID))
158 { 159 return;
159 if (m_localScenes.Contains(cscene)) 160 cscene.Close();
160 {
161 for (int i = 0; i < m_localScenes.Count; i++)
162 {
163 if (m_localScenes[i].Equals(cscene))
164 {
165 m_localScenes[i].Close();
166 }
167 }
168 }
169 }
170 } 161 }
171 162
172 public void Add(Scene scene) 163 public void Add(Scene scene)
173 { 164 {
174 lock (m_localScenes) 165 lock (m_localScenes)
175 m_localScenes.Add(scene); 166 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
176 167
177 scene.OnRestart += HandleRestart; 168 scene.OnRestart += HandleRestart;
178 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange; 169 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange;
@@ -184,15 +175,8 @@ namespace OpenSim.Region.Framework.Scenes
184 175
185 lock (m_localScenes) 176 lock (m_localScenes)
186 { 177 {
187 for (int i = 0; i < m_localScenes.Count; i++) 178 m_localScenes.TryGetValue(rdata.RegionID, out restartedScene);
188 { 179 m_localScenes.Remove(rdata.RegionID);
189 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
190 {
191 restartedScene = m_localScenes[i];
192 m_localScenes.RemoveAt(i);
193 break;
194 }
195 }
196 } 180 }
197 181
198 // If the currently selected scene has been restarted, then we can't reselect here since we the scene 182 // If the currently selected scene has been restarted, then we can't reselect here since we the scene
@@ -207,39 +191,36 @@ namespace OpenSim.Region.Framework.Scenes
207 private void HandleRegionReadyStatusChange(IScene scene) 191 private void HandleRegionReadyStatusChange(IScene scene)
208 { 192 {
209 lock (m_localScenes) 193 lock (m_localScenes)
210 AllRegionsReady = m_localScenes.TrueForAll(s => s.Ready); 194 AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0;
211 } 195 }
212 196
213 public void SendSimOnlineNotification(ulong regionHandle) 197 public void SendSimOnlineNotification(ulong regionHandle)
214 { 198 {
215 RegionInfo Result = null; 199 RegionInfo Result = null;
216 200
217 lock (m_localScenes) 201 Scene s = m_localScenes.FindValue(delegate(Scene x)
218 {
219 for (int i = 0; i < m_localScenes.Count; i++)
220 {
221 if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
222 { 202 {
223 // Inform other regions to tell their avatar about me 203 if (x.RegionInfo.RegionHandle == regionHandle)
224 Result = m_localScenes[i].RegionInfo; 204 return true;
225 } 205 return false;
226 } 206 });
207
208 if (s != null)
209 {
210 List<Scene> sceneList = Scenes;
227 211
228 if (Result != null) 212 for (int i = 0; i < sceneList.Count; i++)
229 { 213 {
230 for (int i = 0; i < m_localScenes.Count; i++) 214 if (sceneList[i]!= s)
231 { 215 {
232 if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) 216 // Inform other regions to tell their avatar about me
233 { 217 //sceneList[i].OtherRegionUp(Result);
234 // Inform other regions to tell their avatar about me
235 //m_localScenes[i].OtherRegionUp(Result);
236 }
237 } 218 }
238 } 219 }
239 else 220 }
240 { 221 else
241 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up"); 222 {
242 } 223 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
243 } 224 }
244 } 225 }
245 226
@@ -368,16 +349,12 @@ namespace OpenSim.Region.Framework.Scenes
368 } 349 }
369 else 350 else
370 { 351 {
371 lock (m_localScenes) 352 Scene s;
353
354 if (m_localScenes.TryGetValue(regionName, out s))
372 { 355 {
373 foreach (Scene scene in m_localScenes) 356 CurrentScene = s;
374 { 357 return true;
375 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
376 {
377 CurrentScene = scene;
378 return true;
379 }
380 }
381 } 358 }
382 359
383 return false; 360 return false;
@@ -386,18 +363,14 @@ namespace OpenSim.Region.Framework.Scenes
386 363
387 public bool TrySetCurrentScene(UUID regionID) 364 public bool TrySetCurrentScene(UUID regionID)
388 { 365 {
389 m_log.Debug("Searching for Region: '" + regionID + "'"); 366// m_log.Debug("Searching for Region: '" + regionID + "'");
390 367
391 lock (m_localScenes) 368 Scene s;
369
370 if (m_localScenes.TryGetValue(regionID, out s))
392 { 371 {
393 foreach (Scene scene in m_localScenes) 372 CurrentScene = s;
394 { 373 return true;
395 if (scene.RegionInfo.RegionID == regionID)
396 {
397 CurrentScene = scene;
398 return true;
399 }
400 }
401 } 374 }
402 375
403 return false; 376 return false;
@@ -405,52 +378,24 @@ namespace OpenSim.Region.Framework.Scenes
405 378
406 public bool TryGetScene(string regionName, out Scene scene) 379 public bool TryGetScene(string regionName, out Scene scene)
407 { 380 {
408 lock (m_localScenes) 381 return m_localScenes.TryGetValue(regionName, out scene);
409 {
410 foreach (Scene mscene in m_localScenes)
411 {
412 if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
413 {
414 scene = mscene;
415 return true;
416 }
417 }
418 }
419
420 scene = null;
421 return false;
422 } 382 }
423 383
424 public bool TryGetScene(UUID regionID, out Scene scene) 384 public bool TryGetScene(UUID regionID, out Scene scene)
425 { 385 {
426 lock (m_localScenes) 386 return m_localScenes.TryGetValue(regionID, out scene);
427 {
428 foreach (Scene mscene in m_localScenes)
429 {
430 if (mscene.RegionInfo.RegionID == regionID)
431 {
432 scene = mscene;
433 return true;
434 }
435 }
436 }
437
438 scene = null;
439 return false;
440 } 387 }
441 388
442 public bool TryGetScene(uint locX, uint locY, out Scene scene) 389 public bool TryGetScene(uint locX, uint locY, out Scene scene)
443 { 390 {
444 lock (m_localScenes) 391 List<Scene> sceneList = Scenes;
392 foreach (Scene mscene in sceneList)
445 { 393 {
446 foreach (Scene mscene in m_localScenes) 394 if (mscene.RegionInfo.RegionLocX == locX &&
395 mscene.RegionInfo.RegionLocY == locY)
447 { 396 {
448 if (mscene.RegionInfo.RegionLocX == locX && 397 scene = mscene;
449 mscene.RegionInfo.RegionLocY == locY) 398 return true;
450 {
451 scene = mscene;
452 return true;
453 }
454 } 399 }
455 } 400 }
456 401
@@ -460,16 +405,14 @@ namespace OpenSim.Region.Framework.Scenes
460 405
461 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene) 406 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
462 { 407 {
463 lock (m_localScenes) 408 List<Scene> sceneList = Scenes;
409 foreach (Scene mscene in sceneList)
464 { 410 {
465 foreach (Scene mscene in m_localScenes) 411 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
412 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
466 { 413 {
467 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) && 414 scene = mscene;
468 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port)) 415 return true;
469 {
470 scene = mscene;
471 return true;
472 }
473 } 416 }
474 } 417 }
475 418
@@ -511,15 +454,10 @@ namespace OpenSim.Region.Framework.Scenes
511 454
512 public RegionInfo GetRegionInfo(UUID regionID) 455 public RegionInfo GetRegionInfo(UUID regionID)
513 { 456 {
514 lock (m_localScenes) 457 Scene s;
458 if (m_localScenes.TryGetValue(regionID, out s))
515 { 459 {
516 foreach (Scene scene in m_localScenes) 460 return s.RegionInfo;
517 {
518 if (scene.RegionInfo.RegionID == regionID)
519 {
520 return scene.RegionInfo;
521 }
522 }
523 } 461 }
524 462
525 return null; 463 return null;
@@ -537,14 +475,12 @@ namespace OpenSim.Region.Framework.Scenes
537 475
538 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar) 476 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar)
539 { 477 {
540 lock (m_localScenes) 478 List<Scene> sceneList = Scenes;
479 foreach (Scene scene in sceneList)
541 { 480 {
542 foreach (Scene scene in m_localScenes) 481 if (scene.TryGetScenePresence(avatarId, out avatar))
543 { 482 {
544 if (scene.TryGetScenePresence(avatarId, out avatar)) 483 return true;
545 {
546 return true;
547 }
548 } 484 }
549 } 485 }
550 486
@@ -554,15 +490,13 @@ namespace OpenSim.Region.Framework.Scenes
554 490
555 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar) 491 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar)
556 { 492 {
557 lock (m_localScenes) 493 List<Scene> sceneList = Scenes;
494 foreach (Scene scene in sceneList)
558 { 495 {
559 foreach (Scene scene in m_localScenes) 496 avatar = scene.GetScenePresence(avatarId);
560 {
561 avatar = scene.GetScenePresence(avatarId);
562 497
563 if (avatar != null && !avatar.IsChildAgent) 498 if (avatar != null && !avatar.IsChildAgent)
564 return true; 499 return true;
565 }
566 } 500 }
567 501
568 avatar = null; 502 avatar = null;
@@ -572,21 +506,19 @@ namespace OpenSim.Region.Framework.Scenes
572 public void CloseScene(Scene scene) 506 public void CloseScene(Scene scene)
573 { 507 {
574 lock (m_localScenes) 508 lock (m_localScenes)
575 m_localScenes.Remove(scene); 509 m_localScenes.Remove(scene.RegionInfo.RegionID);
576 510
577 scene.Close(); 511 scene.Close();
578 } 512 }
579 513
580 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) 514 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
581 { 515 {
582 lock (m_localScenes) 516 List<Scene> sceneList = Scenes;
517 foreach (Scene scene in sceneList)
583 { 518 {
584 foreach (Scene scene in m_localScenes) 519 if (scene.TryGetAvatarByName(avatarName, out avatar))
585 { 520 {
586 if (scene.TryGetAvatarByName(avatarName, out avatar)) 521 return true;
587 {
588 return true;
589 }
590 } 522 }
591 } 523 }
592 524
@@ -596,14 +528,12 @@ namespace OpenSim.Region.Framework.Scenes
596 528
597 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp) 529 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp)
598 { 530 {
599 lock (m_localScenes) 531 List<Scene> sceneList = Scenes;
532 foreach (Scene scene in sceneList)
600 { 533 {
601 foreach (Scene scene in m_localScenes) 534 sp = scene.GetScenePresence(firstName, lastName);
602 { 535 if (sp != null && !sp.IsChildAgent)
603 sp = scene.GetScenePresence(firstName, lastName); 536 return true;
604 if (sp != null && !sp.IsChildAgent)
605 return true;
606 }
607 } 537 }
608 538
609 sp = null; 539 sp = null;
@@ -612,8 +542,8 @@ namespace OpenSim.Region.Framework.Scenes
612 542
613 public void ForEachScene(Action<Scene> action) 543 public void ForEachScene(Action<Scene> action)
614 { 544 {
615 lock (m_localScenes) 545 List<Scene> sceneList = Scenes;
616 m_localScenes.ForEach(action); 546 sceneList.ForEach(action);
617 } 547 }
618 } 548 }
619} 549}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 81cef5b..98617d1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -88,10 +88,6 @@ namespace OpenSim.Region.Framework.Scenes
88 /// <summary> 88 /// <summary>
89 /// Stop and remove the scripts contained in all the prims in this group 89 /// Stop and remove the scripts contained in all the prims in this group
90 /// </summary> 90 /// </summary>
91 /// <param name="sceneObjectBeingDeleted">
92 /// Should be true if these scripts are being removed because the scene
93 /// object is being deleted. This will prevent spurious updates to the client.
94 /// </param>
95 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 91 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
96 { 92 {
97 SceneObjectPart[] parts = m_parts.GetArray(); 93 SceneObjectPart[] parts = m_parts.GetArray();
@@ -254,6 +250,11 @@ namespace OpenSim.Region.Framework.Scenes
254 250
255 public uint GetEffectivePermissions() 251 public uint GetEffectivePermissions()
256 { 252 {
253 return GetEffectivePermissions(false);
254 }
255
256 public uint GetEffectivePermissions(bool useBase)
257 {
257 uint perms=(uint)(PermissionMask.Modify | 258 uint perms=(uint)(PermissionMask.Modify |
258 PermissionMask.Copy | 259 PermissionMask.Copy |
259 PermissionMask.Move | 260 PermissionMask.Move |
@@ -265,8 +266,12 @@ namespace OpenSim.Region.Framework.Scenes
265 for (int i = 0; i < parts.Length; i++) 266 for (int i = 0; i < parts.Length; i++)
266 { 267 {
267 SceneObjectPart part = parts[i]; 268 SceneObjectPart part = parts[i];
268// m_log.DebugFormat("[SCENE OBJECT GROUP INVENTORY]: Effective perms of {0} are {1}", part.Name, (OpenMetaverse.PermissionMask)part.OwnerMask); 269
269 ownerMask &= part.OwnerMask; 270 if (useBase)
271 ownerMask &= part.BaseMask;
272 else
273 ownerMask &= part.OwnerMask;
274
270 perms &= part.Inventory.MaskEffectivePermissions(); 275 perms &= part.Inventory.MaskEffectivePermissions();
271 } 276 }
272 277
@@ -408,6 +413,9 @@ namespace OpenSim.Region.Framework.Scenes
408 413
409 public void ResumeScripts() 414 public void ResumeScripts()
410 { 415 {
416 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
417 return;
418
411 SceneObjectPart[] parts = m_parts.GetArray(); 419 SceneObjectPart[] parts = m_parts.GetArray();
412 for (int i = 0; i < parts.Length; i++) 420 for (int i = 0; i < parts.Length; i++)
413 parts[i].Inventory.ResumeScripts(); 421 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 1c4b77a..b3bd7e0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,12 +24,13 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.ComponentModel; 29using System.ComponentModel;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Drawing; 31using System.Drawing;
32using System.IO; 32using System.IO;
33using System.Diagnostics;
33using System.Linq; 34using System.Linq;
34using System.Threading; 35using System.Threading;
35using System.Xml; 36using System.Xml;
@@ -44,6 +45,7 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
44 45
45namespace OpenSim.Region.Framework.Scenes 46namespace OpenSim.Region.Framework.Scenes
46{ 47{
48
47 [Flags] 49 [Flags]
48 public enum scriptEvents 50 public enum scriptEvents
49 { 51 {
@@ -79,14 +81,14 @@ namespace OpenSim.Region.Framework.Scenes
79 object_rez = 4194304 81 object_rez = 4194304
80 } 82 }
81 83
82 struct scriptPosTarget 84 public struct scriptPosTarget
83 { 85 {
84 public Vector3 targetPos; 86 public Vector3 targetPos;
85 public float tolerance; 87 public float tolerance;
86 public uint handle; 88 public uint handle;
87 } 89 }
88 90
89 struct scriptRotTarget 91 public struct scriptRotTarget
90 { 92 {
91 public Quaternion targetRot; 93 public Quaternion targetRot;
92 public float tolerance; 94 public float tolerance;
@@ -120,8 +122,12 @@ namespace OpenSim.Region.Framework.Scenes
120 /// since the group's last persistent backup 122 /// since the group's last persistent backup
121 /// </summary> 123 /// </summary>
122 private bool m_hasGroupChanged = false; 124 private bool m_hasGroupChanged = false;
123 private long timeFirstChanged; 125 private long timeFirstChanged = 0;
124 private long timeLastChanged; 126 private long timeLastChanged = 0;
127 private long m_maxPersistTime = 0;
128 private long m_minPersistTime = 0;
129// private Random m_rand;
130 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
125 131
126 /// <summary> 132 /// <summary>
127 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 133 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -138,9 +144,44 @@ namespace OpenSim.Region.Framework.Scenes
138 { 144 {
139 if (value) 145 if (value)
140 { 146 {
147
148 if (m_isBackedUp)
149 {
150 m_scene.SceneGraph.FireChangeBackup(this);
151 }
141 timeLastChanged = DateTime.Now.Ticks; 152 timeLastChanged = DateTime.Now.Ticks;
142 if (!m_hasGroupChanged) 153 if (!m_hasGroupChanged)
143 timeFirstChanged = DateTime.Now.Ticks; 154 timeFirstChanged = DateTime.Now.Ticks;
155 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
156 {
157/*
158 if (m_rand == null)
159 {
160 byte[] val = new byte[16];
161 m_rootPart.UUID.ToBytes(val, 0);
162 m_rand = new Random(BitConverter.ToInt32(val, 0));
163 }
164 */
165 if (m_scene.GetRootAgentCount() == 0)
166 {
167 //If the region is empty, this change has been made by an automated process
168 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
169
170// float factor = 1.5f + (float)(m_rand.NextDouble());
171 float factor = 2.0f;
172 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
173 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
174 }
175 else
176 {
177 //If the region is not empty, we want to obey the minimum and maximum persist times
178 //but add a random factor so we stagger the object persistance a little
179// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
180// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
181 m_maxPersistTime = m_scene.m_persistAfter;
182 m_minPersistTime = m_scene.m_dontPersistBefore;
183 }
184 }
144 } 185 }
145 m_hasGroupChanged = value; 186 m_hasGroupChanged = value;
146 187
@@ -171,6 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
171 get { return m_groupContainsForeignPrims; } 212 get { return m_groupContainsForeignPrims; }
172 } 213 }
173 214
215 public bool HasGroupChangedDueToDelink { get; set; }
174 216
175 private bool isTimeToPersist() 217 private bool isTimeToPersist()
176 { 218 {
@@ -180,8 +222,19 @@ namespace OpenSim.Region.Framework.Scenes
180 return false; 222 return false;
181 if (m_scene.ShuttingDown) 223 if (m_scene.ShuttingDown)
182 return true; 224 return true;
225
226 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
227 {
228 m_maxPersistTime = m_scene.m_persistAfter;
229 m_minPersistTime = m_scene.m_dontPersistBefore;
230 }
231
183 long currentTime = DateTime.Now.Ticks; 232 long currentTime = DateTime.Now.Ticks;
184 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 233
234 if (timeLastChanged == 0) timeLastChanged = currentTime;
235 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
236
237 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
185 return true; 238 return true;
186 return false; 239 return false;
187 } 240 }
@@ -239,6 +292,11 @@ namespace OpenSim.Region.Framework.Scenes
239 { 292 {
240 AttachmentPoint = 0; 293 AttachmentPoint = 0;
241 294
295 // Don't zap trees
296 if (RootPart.Shape.PCode == (byte)PCode.Tree ||
297 RootPart.Shape.PCode == (byte)PCode.NewTree)
298 return;
299
242 // Even though we don't use child part state parameters for attachments any more, we still need to set 300 // Even though we don't use child part state parameters for attachments any more, we still need to set
243 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if 301 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if
244 // we store them correctly, scene objects that we receive from elsewhere might not. 302 // we store them correctly, scene objects that we receive from elsewhere might not.
@@ -292,21 +350,38 @@ namespace OpenSim.Region.Framework.Scenes
292 /// </summary> 350 /// </summary>
293 public bool Backup { get; private set; } 351 public bool Backup { get; private set; }
294 352
353 private bool m_isBackedUp;
354
355 public bool IsBackedUp
356 {
357 get { return m_isBackedUp; }
358 }
359
295 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>(); 360 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>();
296 361
297 protected ulong m_regionHandle; 362 protected ulong m_regionHandle;
298 protected SceneObjectPart m_rootPart; 363 protected SceneObjectPart m_rootPart;
299 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 364 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
300 365
301 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 366 private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>();
302 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 367 private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>();
368
369 public SortedDictionary<uint, scriptPosTarget> AtTargets
370 {
371 get { return m_targets; }
372 }
373
374 public SortedDictionary<uint, scriptRotTarget> RotTargets
375 {
376 get { return m_rotTargets; }
377 }
303 378
304 private bool m_scriptListens_atTarget; 379 private bool m_scriptListens_atTarget;
305 private bool m_scriptListens_notAtTarget; 380 private bool m_scriptListens_notAtTarget;
306
307 private bool m_scriptListens_atRotTarget; 381 private bool m_scriptListens_atRotTarget;
308 private bool m_scriptListens_notAtRotTarget; 382 private bool m_scriptListens_notAtRotTarget;
309 383
384 public bool m_dupeInProgress = false;
310 internal Dictionary<UUID, string> m_savedScriptState; 385 internal Dictionary<UUID, string> m_savedScriptState;
311 386
312 #region Properties 387 #region Properties
@@ -343,6 +418,16 @@ namespace OpenSim.Region.Framework.Scenes
343 get { return m_parts.Count; } 418 get { return m_parts.Count; }
344 } 419 }
345 420
421// protected Quaternion m_rotation = Quaternion.Identity;
422//
423// public virtual Quaternion Rotation
424// {
425// get { return m_rotation; }
426// set {
427// m_rotation = value;
428// }
429// }
430
346 public Quaternion GroupRotation 431 public Quaternion GroupRotation
347 { 432 {
348 get { return m_rootPart.RotationOffset; } 433 get { return m_rootPart.RotationOffset; }
@@ -456,6 +541,10 @@ namespace OpenSim.Region.Framework.Scenes
456 public uint ParentID; 541 public uint ParentID;
457 } 542 }
458 543
544
545 public bool inTransit = false;
546 public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
547
459 /// <summary> 548 /// <summary>
460 /// The absolute position of this scene object in the scene 549 /// The absolute position of this scene object in the scene
461 /// </summary> 550 /// </summary>
@@ -465,181 +554,255 @@ namespace OpenSim.Region.Framework.Scenes
465 set 554 set
466 { 555 {
467 Vector3 val = value; 556 Vector3 val = value;
557 if (Scene != null
558 && !Scene.PositionIsInCurrentRegion(val)
559 && !IsAttachmentCheckFull()
560 && !Scene.LoadingPrims
561 )
562 {
563 if (!inTransit)
564 {
565 inTransit = true;
566 SOGCrossDelegate d = CrossAsync;
567 d.BeginInvoke(this, val, CrossAsyncCompleted, d);
568 }
569 return;
570 }
468 571
469 if (Scene != null) 572 if (RootPart.GetStatusSandbox())
470 { 573 {
471 if ( 574 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
472 !Scene.PositionIsInCurrentRegion(val)
473 && !IsAttachmentCheckFull()
474 && (!Scene.LoadingPrims)
475 )
476 { 575 {
477 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 576 RootPart.ScriptSetPhysicsStatus(false);
478 string version = String.Empty;
479 Vector3 newpos = Vector3.Zero;
480 string failureReason = String.Empty;
481 OpenSim.Services.Interfaces.GridRegion destination = null;
482 577
483 if (m_rootPart.KeyframeMotion != null) 578 if (Scene != null)
484 m_rootPart.KeyframeMotion.StartCrossingCheck(); 579 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
580 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
485 581
486 bool canCross = true; 582 return;
487 foreach (ScenePresence av in GetSittingAvatars()) 583 }
488 { 584 }
489 // We need to cross these agents. First, let's find
490 // out if any of them can't cross for some reason.
491 // We have to deny the crossing entirely if any
492 // of them are banned. Alternatively, we could
493 // unsit banned agents....
494 585
586 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
587 if (m_dupeInProgress || IsDeleted)
588 triggerScriptEvent = false;
495 589
496 // We set the avatar position as being the object 590 m_rootPart.GroupPosition = val;
497 // position to get the region to send to
498 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out version, out newpos, out failureReason)) == null)
499 {
500 canCross = false;
501 break;
502 }
503 591
504 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); 592 // Restuff the new GroupPosition into each child SOP of the linkset.
505 } 593 // this is needed because physics may not have linksets but just loose SOPs in world
506 594
507 if (canCross) 595 SceneObjectPart[] parts = m_parts.GetArray();
508 {
509 // We unparent the SP quietly so that it won't
510 // be made to stand up
511 596
512 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); 597 foreach (SceneObjectPart part in parts)
598 {
599 if (part != m_rootPart)
600 part.GroupPosition = val;
601 }
513 602
514 foreach (ScenePresence av in GetSittingAvatars()) 603 foreach (ScenePresence av in m_linkedAvatars)
515 { 604 {
516 avtocrossInfo avinfo = new avtocrossInfo(); 605 av.sitSOGmoved();
517 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); 606 }
518 if (parentPart != null)
519 av.ParentUUID = parentPart.UUID;
520 607
521 avinfo.av = av;
522 avinfo.ParentID = av.ParentID;
523 avsToCross.Add(avinfo);
524 608
525 av.PrevSitOffset = av.OffsetPosition; 609 // now that position is changed tell it to scripts
526 av.ParentID = 0; 610 if (triggerScriptEvent)
527 } 611 {
612 foreach (SceneObjectPart part in parts)
613 {
614 part.TriggerScriptChangedEvent(Changed.POSITION);
615 }
616 }
528 617
529 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 618 if (Scene != null)
619 Scene.EventManager.TriggerParcelPrimCountTainted();
530 620
531 // Normalize 621 }
532 if (val.X >= m_scene.RegionInfo.RegionSizeX) 622 }
533 val.X -= m_scene.RegionInfo.RegionSizeX;
534 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
535 val.Y -= m_scene.RegionInfo.RegionSizeY;
536 if (val.X < 0)
537 val.X += m_scene.RegionInfo.RegionSizeX;
538 if (val.Y < 0)
539 val.Y += m_scene.RegionInfo.RegionSizeY;
540 623
541 // If it's deleted, crossing was successful 624 public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
542 if (IsDeleted) 625 {
543 { 626 Scene sogScene = sog.m_scene;
544 foreach (avtocrossInfo avinfo in avsToCross) 627 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
545 {
546 ScenePresence av = avinfo.av;
547 if (!av.IsInTransit) // just in case...
548 {
549 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
550
551 av.IsInTransit = true;
552
553 // A temporary measure to allow regression tests to work.
554 // Quite possibly, all BeginInvoke() calls should be replaced by Util.FireAndForget
555 // or similar since BeginInvoke() always uses the system threadpool to launch
556 // threads rather than any replace threadpool that we might be using.
557 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
558 {
559 entityTransfer.CrossAgentToNewRegionAsync(av, val, destination, av.Flying, version);
560 CrossAgentToNewRegionCompleted(av);
561 }
562 else
563 {
564 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
565 d.BeginInvoke(
566 av, val, destination, av.Flying, version,
567 ar => CrossAgentToNewRegionCompleted(d.EndInvoke(ar)), null);
568 }
569 }
570 else
571 {
572 m_log.DebugFormat("[SCENE OBJECT]: Not crossing avatar {0} to {1} because it's already in transit", av.Name, val);
573 }
574 }
575 628
576 return; 629 Vector3 newpos = Vector3.Zero;
577 } 630 OpenSim.Services.Interfaces.GridRegion destination = null;
578 else // cross failed, put avas back ??
579 {
580 foreach (avtocrossInfo avinfo in avsToCross)
581 {
582 ScenePresence av = avinfo.av;
583 av.ParentUUID = UUID.Zero;
584 av.ParentID = avinfo.ParentID;
585 }
586 }
587 }
588 else
589 {
590 if (m_rootPart.KeyframeMotion != null)
591 m_rootPart.KeyframeMotion.CrossingFailure();
592 631
593 if (RootPart.PhysActor != null) 632 if (sog.RootPart.DIE_AT_EDGE)
633 {
634 try
635 {
636 sogScene.DeleteSceneObject(sog, false);
637 }
638 catch (Exception)
639 {
640 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
641 }
642 return sog;
643 }
644
645 if (sog.RootPart.RETURN_AT_EDGE)
646 {
647 // We remove the object here
648 try
649 {
650 List<uint> localIDs = new List<uint>();
651 localIDs.Add(sog.RootPart.LocalId);
652 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
653 "Returned at region cross");
654 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
655 }
656 catch (Exception)
657 {
658 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
659 }
660 return sog;
661 }
662
663 if (sog.m_rootPart.KeyframeMotion != null)
664 sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
665
666 if (entityTransfer == null)
667 return sog;
668
669 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
670 if (destination == null)
671 return sog;
672
673 if (sog.m_linkedAvatars.Count == 0)
674 {
675 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true);
676 return sog;
677 }
678
679 string reason = String.Empty;
680 string version = String.Empty;
681
682 foreach (ScenePresence av in sog.m_linkedAvatars)
683 {
684 // We need to cross these agents. First, let's find
685 // out if any of them can't cross for some reason.
686 // We have to deny the crossing entirely if any
687 // of them are banned. Alternatively, we could
688 // unsit banned agents....
689
690 // We set the avatar position as being the object
691 // position to get the region to send to
692 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason))
693 {
694 return sog;
695 }
696 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
697 }
698
699 // We unparent the SP quietly so that it won't
700 // be made to stand up
701
702 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
703
704 foreach (ScenePresence av in sog.m_linkedAvatars)
705 {
706 avtocrossInfo avinfo = new avtocrossInfo();
707 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
708 if (parentPart != null)
709 av.ParentUUID = parentPart.UUID;
710
711 avinfo.av = av;
712 avinfo.ParentID = av.ParentID;
713 avsToCross.Add(avinfo);
714
715 av.PrevSitOffset = av.OffsetPosition;
716 av.ParentID = 0;
717 }
718
719 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true))
720 {
721 foreach (avtocrossInfo avinfo in avsToCross)
722 {
723 ScenePresence av = avinfo.av;
724 if (!av.IsInTransit) // just in case...
725 {
726 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
727
728 av.IsInTransit = true;
729
730// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
731// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
732 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version);
733 if(av.IsChildAgent)
734 {
735 if (av.ParentUUID != UUID.Zero)
594 { 736 {
595 RootPart.PhysActor.CrossingFailure(); 737 av.ClearControls();
738 av.ParentPart = null;
596 } 739 }
597 } 740 }
741 av.ParentUUID = UUID.Zero;
742 // In any case
743 av.IsInTransit = false;
598 744
599 Vector3 oldp = AbsolutePosition; 745 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
600 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
601 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
602 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
603 } 746 }
747 else
748 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
604 } 749 }
605 750 avsToCross.Clear();
606 if (RootPart.GetStatusSandbox()) 751 return sog;
752 }
753 else // cross failed, put avas back ??
754 {
755 foreach (avtocrossInfo avinfo in avsToCross)
607 { 756 {
608 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 757 ScenePresence av = avinfo.av;
609 { 758 av.ParentUUID = UUID.Zero;
610 RootPart.ScriptSetPhysicsStatus(false); 759 av.ParentID = avinfo.ParentID;
611
612 if (Scene != null)
613 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
614 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
615
616 return;
617 }
618 } 760 }
619
620 // Restuff the new GroupPosition into each SOP of the linkset.
621 // This has the affect of resetting and tainting the physics actors.
622 SceneObjectPart[] parts = m_parts.GetArray();
623 for (int i = 0; i < parts.Length; i++)
624 parts[i].GroupPosition = val;
625
626 //if (m_rootPart.PhysActor != null)
627 //{
628 //m_rootPart.PhysActor.Position =
629 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
630 //m_rootPart.GroupPosition.Z);
631 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
632 //}
633
634 if (Scene != null)
635 Scene.EventManager.TriggerParcelPrimCountTainted();
636 } 761 }
762 avsToCross.Clear();
763
764 return sog;
637 } 765 }
638 766
639 public override Vector3 Velocity 767 public void CrossAsyncCompleted(IAsyncResult iar)
640 { 768 {
641 get { return RootPart.Velocity; } 769 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
642 set { RootPart.Velocity = value; } 770 SceneObjectGroup sog = icon.EndInvoke(iar);
771
772 if (!sog.IsDeleted)
773 {
774 SceneObjectPart rootp = sog.m_rootPart;
775 Vector3 oldp = rootp.GroupPosition;
776 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
777 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
778 rootp.GroupPosition = oldp;
779
780 SceneObjectPart[] parts = sog.m_parts.GetArray();
781
782 foreach (SceneObjectPart part in parts)
783 {
784 if (part != rootp)
785 part.GroupPosition = oldp;
786 }
787
788 foreach (ScenePresence av in sog.m_linkedAvatars)
789 {
790 av.sitSOGmoved();
791 }
792
793 sog.Velocity = Vector3.Zero;
794
795 if (sog.m_rootPart.KeyframeMotion != null)
796 sog.m_rootPart.KeyframeMotion.CrossingFailure();
797
798 if (sog.RootPart.PhysActor != null)
799 {
800 sog.RootPart.PhysActor.CrossingFailure();
801 }
802
803 sog.inTransit = false;
804 sog.ScheduleGroupForFullUpdate();
805 }
643 } 806 }
644 807
645 private void CrossAgentToNewRegionCompleted(ScenePresence agent) 808 private void CrossAgentToNewRegionCompleted(ScenePresence agent)
@@ -649,6 +812,7 @@ namespace OpenSim.Region.Framework.Scenes
649 { 812 {
650 if (agent.ParentUUID != UUID.Zero) 813 if (agent.ParentUUID != UUID.Zero)
651 { 814 {
815 agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID);
652 agent.ParentPart = null; 816 agent.ParentPart = null;
653// agent.ParentPosition = Vector3.Zero; 817// agent.ParentPosition = Vector3.Zero;
654// agent.ParentUUID = UUID.Zero; 818// agent.ParentUUID = UUID.Zero;
@@ -666,6 +830,12 @@ namespace OpenSim.Region.Framework.Scenes
666 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 830 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
667 } 831 }
668 832
833 public override Vector3 Velocity
834 {
835 get { return RootPart.Velocity; }
836 set { RootPart.Velocity = value; }
837 }
838
669 public override uint LocalId 839 public override uint LocalId
670 { 840 {
671 get { return m_rootPart.LocalId; } 841 get { return m_rootPart.LocalId; }
@@ -740,6 +910,11 @@ namespace OpenSim.Region.Framework.Scenes
740 m_isSelected = value; 910 m_isSelected = value;
741 // Tell physics engine that group is selected 911 // Tell physics engine that group is selected
742 912
913 // this is not right
914 // but ode engines should only really need to know about root part
915 // so they can put entire object simulation on hold and not colliding
916 // keep as was for now
917
743 PhysicsActor pa = m_rootPart.PhysActor; 918 PhysicsActor pa = m_rootPart.PhysActor;
744 if (pa != null) 919 if (pa != null)
745 { 920 {
@@ -761,13 +936,47 @@ namespace OpenSim.Region.Framework.Scenes
761 } 936 }
762 } 937 }
763 938
939 public void PartSelectChanged(bool partSelect)
940 {
941 // any part selected makes group selected
942 if (m_isSelected == partSelect)
943 return;
944
945 if (partSelect)
946 {
947 IsSelected = partSelect;
948// if (!IsAttachment)
949// ScheduleGroupForFullUpdate();
950 }
951 else
952 {
953 // bad bad bad 2 heavy for large linksets
954 // since viewer does send lot of (un)selects
955 // this needs to be replaced by a specific list or count ?
956 // but that will require extra code in several places
957
958 SceneObjectPart[] parts = m_parts.GetArray();
959 for (int i = 0; i < parts.Length; i++)
960 {
961 SceneObjectPart part = parts[i];
962 if (part.IsSelected)
963 return;
964 }
965 IsSelected = partSelect;
966// if (!IsAttachment)
967// {
968// ScheduleGroupForFullUpdate();
969// }
970 }
971 }
972 // PlaySoundMasterPrim no longer in use to remove
764 private SceneObjectPart m_PlaySoundMasterPrim = null; 973 private SceneObjectPart m_PlaySoundMasterPrim = null;
765 public SceneObjectPart PlaySoundMasterPrim 974 public SceneObjectPart PlaySoundMasterPrim
766 { 975 {
767 get { return m_PlaySoundMasterPrim; } 976 get { return m_PlaySoundMasterPrim; }
768 set { m_PlaySoundMasterPrim = value; } 977 set { m_PlaySoundMasterPrim = value; }
769 } 978 }
770 979 // PlaySoundSlavePrims no longer in use to remove
771 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 980 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
772 public List<SceneObjectPart> PlaySoundSlavePrims 981 public List<SceneObjectPart> PlaySoundSlavePrims
773 { 982 {
@@ -775,6 +984,7 @@ namespace OpenSim.Region.Framework.Scenes
775 set { m_PlaySoundSlavePrims = value; } 984 set { m_PlaySoundSlavePrims = value; }
776 } 985 }
777 986
987 // LoopSoundMasterPrim no longer in use to remove
778 private SceneObjectPart m_LoopSoundMasterPrim = null; 988 private SceneObjectPart m_LoopSoundMasterPrim = null;
779 public SceneObjectPart LoopSoundMasterPrim 989 public SceneObjectPart LoopSoundMasterPrim
780 { 990 {
@@ -782,6 +992,7 @@ namespace OpenSim.Region.Framework.Scenes
782 set { m_LoopSoundMasterPrim = value; } 992 set { m_LoopSoundMasterPrim = value; }
783 } 993 }
784 994
995 // m_LoopSoundSlavePrims no longer in use to remove
785 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 996 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
786 public List<SceneObjectPart> LoopSoundSlavePrims 997 public List<SceneObjectPart> LoopSoundSlavePrims
787 { 998 {
@@ -844,7 +1055,7 @@ namespace OpenSim.Region.Framework.Scenes
844 /// No avatar should appear more than once in this list. 1055 /// No avatar should appear more than once in this list.
845 /// Do not manipulate this list directly - use the Add/Remove sitting avatar methods on SceneObjectPart. 1056 /// Do not manipulate this list directly - use the Add/Remove sitting avatar methods on SceneObjectPart.
846 /// </remarks> 1057 /// </remarks>
847 protected internal List<ScenePresence> m_sittingAvatars = new List<ScenePresence>(); 1058 protected internal List<UUID> m_sittingAvatars = new List<UUID>();
848 1059
849 #endregion 1060 #endregion
850 1061
@@ -861,6 +1072,7 @@ namespace OpenSim.Region.Framework.Scenes
861 /// </summary> 1072 /// </summary>
862 public SceneObjectGroup() 1073 public SceneObjectGroup()
863 { 1074 {
1075
864 } 1076 }
865 1077
866 /// <summary> 1078 /// <summary>
@@ -878,8 +1090,8 @@ namespace OpenSim.Region.Framework.Scenes
878 /// Constructor. This object is added to the scene later via AttachToScene() 1090 /// Constructor. This object is added to the scene later via AttachToScene()
879 /// </summary> 1091 /// </summary>
880 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 1092 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
881 :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) 1093 {
882 { 1094 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
883 } 1095 }
884 1096
885 /// <summary> 1097 /// <summary>
@@ -954,7 +1166,10 @@ namespace OpenSim.Region.Framework.Scenes
954 /// </summary> 1166 /// </summary>
955 public virtual void AttachToBackup() 1167 public virtual void AttachToBackup()
956 { 1168 {
957 if (CanBeBackedUp) 1169 if (IsAttachment) return;
1170 m_scene.SceneGraph.FireAttachToBackup(this);
1171
1172// if (InSceneBackup)
958 { 1173 {
959// m_log.DebugFormat( 1174// m_log.DebugFormat(
960// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); 1175// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
@@ -1001,6 +1216,13 @@ namespace OpenSim.Region.Framework.Scenes
1001 1216
1002 ApplyPhysics(); 1217 ApplyPhysics();
1003 1218
1219 if (RootPart.PhysActor != null)
1220 RootPart.Force = RootPart.Force;
1221 if (RootPart.PhysActor != null)
1222 RootPart.Torque = RootPart.Torque;
1223 if (RootPart.PhysActor != null)
1224 RootPart.Buoyancy = RootPart.Buoyancy;
1225
1004 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1226 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
1005 // for the same object with very different properties. The caller must schedule the update. 1227 // for the same object with very different properties. The caller must schedule the update.
1006 //ScheduleGroupForFullUpdate(); 1228 //ScheduleGroupForFullUpdate();
@@ -1016,6 +1238,10 @@ namespace OpenSim.Region.Framework.Scenes
1016 EntityIntersection result = new EntityIntersection(); 1238 EntityIntersection result = new EntityIntersection();
1017 1239
1018 SceneObjectPart[] parts = m_parts.GetArray(); 1240 SceneObjectPart[] parts = m_parts.GetArray();
1241
1242 // Find closest hit here
1243 float idist = float.MaxValue;
1244
1019 for (int i = 0; i < parts.Length; i++) 1245 for (int i = 0; i < parts.Length; i++)
1020 { 1246 {
1021 SceneObjectPart part = parts[i]; 1247 SceneObjectPart part = parts[i];
@@ -1030,11 +1256,6 @@ namespace OpenSim.Region.Framework.Scenes
1030 1256
1031 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1257 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
1032 1258
1033 // This may need to be updated to the maximum draw distance possible..
1034 // We might (and probably will) be checking for prim creation from other sims
1035 // when the camera crosses the border.
1036 float idist = Constants.RegionSize;
1037
1038 if (inter.HitTF) 1259 if (inter.HitTF)
1039 { 1260 {
1040 // We need to find the closest prim to return to the testcaller along the ray 1261 // We need to find the closest prim to return to the testcaller along the ray
@@ -1045,10 +1266,11 @@ namespace OpenSim.Region.Framework.Scenes
1045 result.obj = part; 1266 result.obj = part;
1046 result.normal = inter.normal; 1267 result.normal = inter.normal;
1047 result.distance = inter.distance; 1268 result.distance = inter.distance;
1269
1270 idist = inter.distance;
1048 } 1271 }
1049 } 1272 }
1050 } 1273 }
1051
1052 return result; 1274 return result;
1053 } 1275 }
1054 1276
@@ -1060,25 +1282,27 @@ namespace OpenSim.Region.Framework.Scenes
1060 /// <returns></returns> 1282 /// <returns></returns>
1061 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1283 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
1062 { 1284 {
1063 maxX = -256f; 1285 maxX = float.MinValue;
1064 maxY = -256f; 1286 maxY = float.MinValue;
1065 maxZ = -256f; 1287 maxZ = float.MinValue;
1066 minX = 10000f; 1288 minX = float.MaxValue;
1067 minY = 10000f; 1289 minY = float.MaxValue;
1068 minZ = 10000f; 1290 minZ = float.MaxValue;
1069 1291
1070 SceneObjectPart[] parts = m_parts.GetArray(); 1292 SceneObjectPart[] parts = m_parts.GetArray();
1071 for (int i = 0; i < parts.Length; i++) 1293 foreach (SceneObjectPart part in parts)
1072 { 1294 {
1073 SceneObjectPart part = parts[i];
1074
1075 Vector3 worldPos = part.GetWorldPosition(); 1295 Vector3 worldPos = part.GetWorldPosition();
1076 Vector3 offset = worldPos - AbsolutePosition; 1296 Vector3 offset = worldPos - AbsolutePosition;
1077 Quaternion worldRot; 1297 Quaternion worldRot;
1078 if (part.ParentID == 0) 1298 if (part.ParentID == 0)
1299 {
1079 worldRot = part.RotationOffset; 1300 worldRot = part.RotationOffset;
1301 }
1080 else 1302 else
1303 {
1081 worldRot = part.GetWorldRotation(); 1304 worldRot = part.GetWorldRotation();
1305 }
1082 1306
1083 Vector3 frontTopLeft; 1307 Vector3 frontTopLeft;
1084 Vector3 frontTopRight; 1308 Vector3 frontTopRight;
@@ -1090,6 +1314,8 @@ namespace OpenSim.Region.Framework.Scenes
1090 Vector3 backBottomLeft; 1314 Vector3 backBottomLeft;
1091 Vector3 backBottomRight; 1315 Vector3 backBottomRight;
1092 1316
1317 // Vector3[] corners = new Vector3[8];
1318
1093 Vector3 orig = Vector3.Zero; 1319 Vector3 orig = Vector3.Zero;
1094 1320
1095 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1321 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -1124,6 +1350,38 @@ namespace OpenSim.Region.Framework.Scenes
1124 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1350 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
1125 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1351 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
1126 1352
1353
1354
1355 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1356 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1357 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1358 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1359 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1360 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1361 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1362 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1363
1364 //for (int i = 0; i < 8; i++)
1365 //{
1366 // corners[i] = corners[i] * worldRot;
1367 // corners[i] += offset;
1368
1369 // if (corners[i].X > maxX)
1370 // maxX = corners[i].X;
1371 // if (corners[i].X < minX)
1372 // minX = corners[i].X;
1373
1374 // if (corners[i].Y > maxY)
1375 // maxY = corners[i].Y;
1376 // if (corners[i].Y < minY)
1377 // minY = corners[i].Y;
1378
1379 // if (corners[i].Z > maxZ)
1380 // maxZ = corners[i].Y;
1381 // if (corners[i].Z < minZ)
1382 // minZ = corners[i].Z;
1383 //}
1384
1127 frontTopLeft = frontTopLeft * worldRot; 1385 frontTopLeft = frontTopLeft * worldRot;
1128 frontTopRight = frontTopRight * worldRot; 1386 frontTopRight = frontTopRight * worldRot;
1129 frontBottomLeft = frontBottomLeft * worldRot; 1387 frontBottomLeft = frontBottomLeft * worldRot;
@@ -1145,6 +1403,15 @@ namespace OpenSim.Region.Framework.Scenes
1145 backTopLeft += offset; 1403 backTopLeft += offset;
1146 backTopRight += offset; 1404 backTopRight += offset;
1147 1405
1406 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1407 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1408 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1409 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1410 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1411 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1412 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1413 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1414
1148 if (frontTopRight.X > maxX) 1415 if (frontTopRight.X > maxX)
1149 maxX = frontTopRight.X; 1416 maxX = frontTopRight.X;
1150 if (frontTopLeft.X > maxX) 1417 if (frontTopLeft.X > maxX)
@@ -1288,17 +1555,118 @@ namespace OpenSim.Region.Framework.Scenes
1288 1555
1289 #endregion 1556 #endregion
1290 1557
1558 public void GetResourcesCosts(SceneObjectPart apart,
1559 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1560 {
1561 // this information may need to be cached
1562
1563 float cost;
1564 float tmpcost;
1565
1566 bool ComplexCost = false;
1567
1568 SceneObjectPart p;
1569 SceneObjectPart[] parts;
1570
1571 lock (m_parts)
1572 {
1573 parts = m_parts.GetArray();
1574 }
1575
1576 int nparts = parts.Length;
1577
1578
1579 for (int i = 0; i < nparts; i++)
1580 {
1581 p = parts[i];
1582
1583 if (p.UsesComplexCost)
1584 {
1585 ComplexCost = true;
1586 break;
1587 }
1588 }
1589
1590 if (ComplexCost)
1591 {
1592 linksetResCost = 0;
1593 linksetPhysCost = 0;
1594 partCost = 0;
1595 partPhysCost = 0;
1596
1597 for (int i = 0; i < nparts; i++)
1598 {
1599 p = parts[i];
1600
1601 cost = p.StreamingCost;
1602 tmpcost = p.SimulationCost;
1603 if (tmpcost > cost)
1604 cost = tmpcost;
1605 tmpcost = p.PhysicsCost;
1606 if (tmpcost > cost)
1607 cost = tmpcost;
1608
1609 linksetPhysCost += tmpcost;
1610 linksetResCost += cost;
1611
1612 if (p == apart)
1613 {
1614 partCost = cost;
1615 partPhysCost = tmpcost;
1616 }
1617 }
1618 }
1619 else
1620 {
1621 partPhysCost = 1.0f;
1622 partCost = 1.0f;
1623 linksetResCost = (float)nparts;
1624 linksetPhysCost = linksetResCost;
1625 }
1626 }
1627
1628 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1629 {
1630 SceneObjectPart p;
1631 SceneObjectPart[] parts;
1632
1633 lock (m_parts)
1634 {
1635 parts = m_parts.GetArray();
1636 }
1637
1638 int nparts = parts.Length;
1639
1640 PhysCost = 0;
1641 StreamCost = 0;
1642 SimulCost = 0;
1643
1644 for (int i = 0; i < nparts; i++)
1645 {
1646 p = parts[i];
1647
1648 StreamCost += p.StreamingCost;
1649 SimulCost += p.SimulationCost;
1650 PhysCost += p.PhysicsCost;
1651 }
1652 }
1653
1291 public void SaveScriptedState(XmlTextWriter writer) 1654 public void SaveScriptedState(XmlTextWriter writer)
1292 { 1655 {
1656 SaveScriptedState(writer, false);
1657 }
1658
1659 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1660 {
1293 XmlDocument doc = new XmlDocument(); 1661 XmlDocument doc = new XmlDocument();
1294 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1662 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1295 1663
1296 SceneObjectPart[] parts = m_parts.GetArray(); 1664 SceneObjectPart[] parts = m_parts.GetArray();
1297 for (int i = 0; i < parts.Length; i++) 1665 for (int i = 0; i < parts.Length; i++)
1298 { 1666 {
1299 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1667 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1300 foreach (KeyValuePair<UUID, string> kvp in pstates) 1668 foreach (KeyValuePair<UUID, string> kvp in pstates)
1301 states.Add(kvp.Key, kvp.Value); 1669 states[kvp.Key] = kvp.Value;
1302 } 1670 }
1303 1671
1304 if (states.Count > 0) 1672 if (states.Count > 0)
@@ -1317,6 +1685,171 @@ namespace OpenSim.Region.Framework.Scenes
1317 } 1685 }
1318 } 1686 }
1319 1687
1688 /// <summary>
1689 /// Add the avatar to this linkset (avatar is sat).
1690 /// </summary>
1691 /// <param name="agentID"></param>
1692 public void AddAvatar(UUID agentID)
1693 {
1694 ScenePresence presence;
1695 if (m_scene.TryGetScenePresence(agentID, out presence))
1696 {
1697 if (!m_linkedAvatars.Contains(presence))
1698 {
1699 m_linkedAvatars.Add(presence);
1700 }
1701 }
1702 }
1703
1704 /// <summary>
1705 /// Delete the avatar from this linkset (avatar is unsat).
1706 /// </summary>
1707 /// <param name="agentID"></param>
1708 public void DeleteAvatar(UUID agentID)
1709 {
1710 ScenePresence presence;
1711 if (m_scene.TryGetScenePresence(agentID, out presence))
1712 {
1713 if (m_linkedAvatars.Contains(presence))
1714 {
1715 m_linkedAvatars.Remove(presence);
1716 }
1717 }
1718 }
1719
1720 /// <summary>
1721 /// Returns the list of linked presences (avatars sat on this group)
1722 /// </summary>
1723 /// <param name="agentID"></param>
1724 public List<ScenePresence> GetLinkedAvatars()
1725 {
1726 return m_linkedAvatars;
1727 }
1728
1729 /// <summary>
1730 /// Attach this scene object to the given avatar.
1731 /// </summary>
1732 /// <param name="agentID"></param>
1733 /// <param name="attachmentpoint"></param>
1734 /// <param name="AttachOffset"></param>
1735 private void AttachToAgent(
1736 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1737 {
1738 if (avatar != null)
1739 {
1740 // don't attach attachments to child agents
1741 if (avatar.IsChildAgent) return;
1742
1743 // Remove from database and parcel prim count
1744 m_scene.DeleteFromStorage(so.UUID);
1745 m_scene.EventManager.TriggerParcelPrimCountTainted();
1746
1747 so.AttachedAvatar = avatar.UUID;
1748
1749 if (so.RootPart.PhysActor != null)
1750 {
1751 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1752 so.RootPart.PhysActor = null;
1753 }
1754
1755 so.AbsolutePosition = attachOffset;
1756 so.RootPart.AttachedPos = attachOffset;
1757 so.IsAttachment = true;
1758 so.RootPart.SetParentLocalId(avatar.LocalId);
1759 so.AttachmentPoint = attachmentpoint;
1760
1761 avatar.AddAttachment(this);
1762
1763 if (!silent)
1764 {
1765 // Killing it here will cause the client to deselect it
1766 // It then reappears on the avatar, deselected
1767 // through the full update below
1768 //
1769 if (IsSelected)
1770 {
1771 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1772 }
1773
1774 IsSelected = false; // fudge....
1775 ScheduleGroupForFullUpdate();
1776 }
1777 }
1778 else
1779 {
1780 m_log.WarnFormat(
1781 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1782 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1783 }
1784 }
1785
1786 public byte GetAttachmentPoint()
1787 {
1788 return m_rootPart.Shape.State;
1789 }
1790
1791 public void DetachToGround()
1792 {
1793 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1794 if (avatar == null)
1795 return;
1796 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1797 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1798 avatar.RemoveAttachment(this);
1799
1800 Vector3 detachedpos = new Vector3(127f,127f,127f);
1801 if (avatar == null)
1802 return;
1803
1804 detachedpos = avatar.AbsolutePosition;
1805 FromItemID = UUID.Zero;
1806
1807 AbsolutePosition = detachedpos;
1808 AttachedAvatar = UUID.Zero;
1809
1810 //SceneObjectPart[] parts = m_parts.GetArray();
1811 //for (int i = 0; i < parts.Length; i++)
1812 // parts[i].AttachedAvatar = UUID.Zero;
1813
1814 m_rootPart.SetParentLocalId(0);
1815 AttachmentPoint = (byte)0;
1816 // must check if buildind should be true or false here
1817// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1818 ApplyPhysics();
1819
1820 HasGroupChanged = true;
1821 RootPart.Rezzed = DateTime.Now;
1822 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1823 AttachToBackup();
1824 m_scene.EventManager.TriggerParcelPrimCountTainted();
1825 m_rootPart.ScheduleFullUpdate();
1826 m_rootPart.ClearUndoState();
1827 }
1828
1829 public void DetachToInventoryPrep()
1830 {
1831 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1832 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1833 if (avatar != null)
1834 {
1835 //detachedpos = avatar.AbsolutePosition;
1836 avatar.RemoveAttachment(this);
1837 }
1838
1839 AttachedAvatar = UUID.Zero;
1840
1841 /*SceneObjectPart[] parts = m_parts.GetArray();
1842 for (int i = 0; i < parts.Length; i++)
1843 parts[i].AttachedAvatar = UUID.Zero;*/
1844
1845 m_rootPart.SetParentLocalId(0);
1846 //m_rootPart.SetAttachmentPoint((byte)0);
1847 IsAttachment = false;
1848 AbsolutePosition = m_rootPart.AttachedPos;
1849 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1850 //AttachToBackup();
1851 //m_rootPart.ScheduleFullUpdate();
1852 }
1320 1853
1321 /// <summary> 1854 /// <summary>
1322 /// 1855 ///
@@ -1358,7 +1891,10 @@ namespace OpenSim.Region.Framework.Scenes
1358 public void AddPart(SceneObjectPart part) 1891 public void AddPart(SceneObjectPart part)
1359 { 1892 {
1360 part.SetParent(this); 1893 part.SetParent(this);
1361 part.LinkNum = m_parts.Add(part.UUID, part); 1894 m_parts.Add(part.UUID, part);
1895
1896 part.LinkNum = m_parts.Count;
1897
1362 if (part.LinkNum == 2) 1898 if (part.LinkNum == 2)
1363 RootPart.LinkNum = 1; 1899 RootPart.LinkNum = 1;
1364 } 1900 }
@@ -1384,6 +1920,14 @@ namespace OpenSim.Region.Framework.Scenes
1384 parts[i].UUID = UUID.Random(); 1920 parts[i].UUID = UUID.Random();
1385 } 1921 }
1386 1922
1923 // helper provided for parts.
1924 public int GetSceneMaxUndo()
1925 {
1926 if (m_scene != null)
1927 return m_scene.MaxUndoCount;
1928 return 5;
1929 }
1930
1387 // justincc: I don't believe this hack is needed any longer, especially since the physics 1931 // justincc: I don't believe this hack is needed any longer, especially since the physics
1388 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false 1932 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1389 // this method was preventing proper reload of scene objects. 1933 // this method was preventing proper reload of scene objects.
@@ -1405,11 +1949,21 @@ namespace OpenSim.Region.Framework.Scenes
1405 // Setting this SOG's absolute position also loops through and sets the positions 1949 // Setting this SOG's absolute position also loops through and sets the positions
1406 // of the SOP's in this SOG's linkset. This has the side affect of making sure 1950 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1407 // the physics world matches the simulated world. 1951 // the physics world matches the simulated world.
1408 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1952 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1409 1953
1410 // teravus: AbsolutePosition is NOT a normal property! 1954 // teravus: AbsolutePosition is NOT a normal property!
1411 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1955 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1412 // jhurliman: Then why is it a property instead of two methods? 1956 // jhurliman: Then why is it a property instead of two methods?
1957
1958 // do only what is supposed to do
1959 Vector3 groupPosition = m_rootPart.GroupPosition;
1960 SceneObjectPart[] parts = m_parts.GetArray();
1961
1962 foreach (SceneObjectPart part in parts)
1963 {
1964 if (part != m_rootPart)
1965 part.GroupPosition = groupPosition;
1966 }
1413 } 1967 }
1414 1968
1415 public UUID GetPartsFullID(uint localID) 1969 public UUID GetPartsFullID(uint localID)
@@ -1441,7 +1995,7 @@ namespace OpenSim.Region.Framework.Scenes
1441// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1995// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1442// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1996// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1443 1997
1444 part.StoreUndoState(); 1998// part.StoreUndoState();
1445 part.OnGrab(offsetPos, remoteClient); 1999 part.OnGrab(offsetPos, remoteClient);
1446 } 2000 }
1447 2001
@@ -1461,28 +2015,36 @@ namespace OpenSim.Region.Framework.Scenes
1461 /// <param name="silent">If true then deletion is not broadcast to clients</param> 2015 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1462 public void DeleteGroupFromScene(bool silent) 2016 public void DeleteGroupFromScene(bool silent)
1463 { 2017 {
2018 // We need to keep track of this state in case this group is still queued for backup.
2019 IsDeleted = true;
2020
2021 DetachFromBackup();
2022
1464 SceneObjectPart[] parts = m_parts.GetArray(); 2023 SceneObjectPart[] parts = m_parts.GetArray();
1465 for (int i = 0; i < parts.Length; i++) 2024 for (int i = 0; i < parts.Length; i++)
1466 { 2025 {
1467 SceneObjectPart part = parts[i]; 2026 SceneObjectPart part = parts[i];
1468 2027
1469 Scene.ForEachScenePresence(sp => 2028 if (Scene != null)
1470 { 2029 {
1471 if (!sp.IsChildAgent && sp.ParentID == part.LocalId) 2030 Scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
1472 sp.StandUp();
1473
1474 if (!silent)
1475 { 2031 {
1476 part.ClearUpdateSchedule(); 2032 if (avatar.ParentID == LocalId)
1477 if (part == m_rootPart) 2033 avatar.StandUp();
2034
2035 if (!silent)
1478 { 2036 {
1479 if (!IsAttachment 2037 part.ClearUpdateSchedule();
1480 || AttachedAvatar == sp.UUID 2038 if (part == m_rootPart)
1481 || !HasPrivateAttachmentPoint) 2039 {
1482 sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); 2040 if (!IsAttachment
2041 || AttachedAvatar == avatar.ControllingClient.AgentId
2042 || !HasPrivateAttachmentPoint)
2043 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
2044 }
1483 } 2045 }
1484 } 2046 });
1485 }); 2047 }
1486 } 2048 }
1487 } 2049 }
1488 2050
@@ -1553,28 +2115,43 @@ namespace OpenSim.Region.Framework.Scenes
1553 /// </summary> 2115 /// </summary>
1554 public void ApplyPhysics() 2116 public void ApplyPhysics()
1555 { 2117 {
1556 // Apply physics to the root prim
1557 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1558
1559 // Apply physics to child prims
1560 SceneObjectPart[] parts = m_parts.GetArray(); 2118 SceneObjectPart[] parts = m_parts.GetArray();
1561 if (parts.Length > 1) 2119 if (parts.Length > 1)
1562 { 2120 {
2121 ResetChildPrimPhysicsPositions();
2122
2123 // Apply physics to the root prim
2124 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
2125
2126
1563 for (int i = 0; i < parts.Length; i++) 2127 for (int i = 0; i < parts.Length; i++)
1564 { 2128 {
1565 SceneObjectPart part = parts[i]; 2129 SceneObjectPart part = parts[i];
1566 if (part.LocalId != m_rootPart.LocalId) 2130 if (part.LocalId != m_rootPart.LocalId)
1567 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 2131 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1568 } 2132 }
1569
1570 // Hack to get the physics scene geometries in the right spot 2133 // Hack to get the physics scene geometries in the right spot
1571 ResetChildPrimPhysicsPositions(); 2134// ResetChildPrimPhysicsPositions();
2135 if (m_rootPart.PhysActor != null)
2136 {
2137 m_rootPart.PhysActor.Building = false;
2138 }
2139 }
2140 else
2141 {
2142 // Apply physics to the root prim
2143 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1572 } 2144 }
1573 } 2145 }
1574 2146
1575 public void SetOwnerId(UUID userId) 2147 public void SetOwnerId(UUID userId)
1576 { 2148 {
1577 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 2149 ForEachPart(delegate(SceneObjectPart part)
2150 {
2151
2152 part.OwnerID = userId;
2153
2154 });
1578 } 2155 }
1579 2156
1580 public void ForEachPart(Action<SceneObjectPart> whatToDo) 2157 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1599,18 +2176,24 @@ namespace OpenSim.Region.Framework.Scenes
1599 return; 2176 return;
1600 } 2177 }
1601 2178
1602 if (IsDeleted || UUID == UUID.Zero) 2179 if (IsDeleted || inTransit || UUID == UUID.Zero)
1603 { 2180 {
1604// m_log.DebugFormat( 2181// m_log.DebugFormat(
1605// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2182// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
1606 return; 2183 return;
1607 } 2184 }
1608 2185
2186 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
2187 return;
2188
1609 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 2189 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1610 // any exception propogate upwards. 2190 // any exception propogate upwards.
1611 try 2191 try
1612 { 2192 {
1613 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 2193 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
2194 !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
2195 m_scene.LoadingPrims) // Land may not be valid yet
2196
1614 { 2197 {
1615 ILandObject parcel = m_scene.LandChannel.GetLandObject( 2198 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1616 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 2199 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1637,6 +2220,7 @@ namespace OpenSim.Region.Framework.Scenes
1637 } 2220 }
1638 } 2221 }
1639 } 2222 }
2223
1640 } 2224 }
1641 2225
1642 if (m_scene.UseBackup && HasGroupChanged) 2226 if (m_scene.UseBackup && HasGroupChanged)
@@ -1644,10 +2228,31 @@ namespace OpenSim.Region.Framework.Scenes
1644 // don't backup while it's selected or you're asking for changes mid stream. 2228 // don't backup while it's selected or you're asking for changes mid stream.
1645 if (isTimeToPersist() || forcedBackup) 2229 if (isTimeToPersist() || forcedBackup)
1646 { 2230 {
2231 if (m_rootPart.PhysActor != null &&
2232 (!m_rootPart.PhysActor.IsPhysical))
2233 {
2234 // Possible ghost prim
2235 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2236 {
2237 foreach (SceneObjectPart part in m_parts.GetArray())
2238 {
2239 // Re-set physics actor positions and
2240 // orientations
2241 part.GroupPosition = m_rootPart.GroupPosition;
2242 }
2243 }
2244 }
1647// m_log.DebugFormat( 2245// m_log.DebugFormat(
1648// "[SCENE]: Storing {0}, {1} in {2}", 2246// "[SCENE]: Storing {0}, {1} in {2}",
1649// Name, UUID, m_scene.RegionInfo.RegionName); 2247// Name, UUID, m_scene.RegionInfo.RegionName);
1650 2248
2249 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2250 {
2251 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2252 RootPart.Shape.State = 0;
2253 ScheduleGroupForFullUpdate();
2254 }
2255
1651 SceneObjectGroup backup_group = Copy(false); 2256 SceneObjectGroup backup_group = Copy(false);
1652 backup_group.RootPart.Velocity = RootPart.Velocity; 2257 backup_group.RootPart.Velocity = RootPart.Velocity;
1653 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2258 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1657,13 +2262,22 @@ namespace OpenSim.Region.Framework.Scenes
1657 GroupContainsForeignPrims = false; 2262 GroupContainsForeignPrims = false;
1658 2263
1659 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2264 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2265
1660 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2266 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1661 2267
1662 backup_group.ForEachPart(delegate(SceneObjectPart part) 2268 backup_group.ForEachPart(delegate(SceneObjectPart part)
1663 { 2269 {
1664 part.Inventory.ProcessInventoryBackup(datastore); 2270 part.Inventory.ProcessInventoryBackup(datastore);
2271
2272 // take the change to delete things
2273 if(part.KeyframeMotion != null)
2274 {
2275 part.KeyframeMotion.Delete();
2276 part.KeyframeMotion = null;
2277 }
1665 }); 2278 });
1666 2279
2280
1667 backup_group = null; 2281 backup_group = null;
1668 } 2282 }
1669// else 2283// else
@@ -1713,26 +2327,30 @@ namespace OpenSim.Region.Framework.Scenes
1713 /// <returns></returns> 2327 /// <returns></returns>
1714 public SceneObjectGroup Copy(bool userExposed) 2328 public SceneObjectGroup Copy(bool userExposed)
1715 { 2329 {
1716 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2330 m_dupeInProgress = true;
1717 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1718 // but not between regions on different simulators). Really, all copying should be done explicitly.
1719 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2331 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1720 2332 dupe.m_isBackedUp = false;
1721 dupe.Backup = false;
1722 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2333 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1723 dupe.m_sittingAvatars = new List<ScenePresence>(); 2334
2335 dupe.inTransit = inTransit; // this shouldn't be needed TEST
2336
2337 // new group as no sitting avatars
2338 dupe.m_linkedAvatars = new List<ScenePresence>();
2339 dupe.m_sittingAvatars = new List<UUID>();
2340
1724 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2341 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1725 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2342 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
2343
1726 2344
1727 if (userExposed) 2345 if (userExposed)
1728 dupe.m_rootPart.TrimPermissions(); 2346 dupe.m_rootPart.TrimPermissions();
1729 2347
1730 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2348 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1731 2349
1732 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2350 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1733 { 2351 {
1734 return p1.LinkNum.CompareTo(p2.LinkNum); 2352 return p1.LinkNum.CompareTo(p2.LinkNum);
1735 } 2353 }
1736 ); 2354 );
1737 2355
1738 foreach (SceneObjectPart part in partList) 2356 foreach (SceneObjectPart part in partList)
@@ -1742,43 +2360,56 @@ namespace OpenSim.Region.Framework.Scenes
1742 { 2360 {
1743 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2361 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1744 newPart.LinkNum = part.LinkNum; 2362 newPart.LinkNum = part.LinkNum;
1745 } 2363// if (userExposed)
2364 newPart.ParentID = dupe.m_rootPart.LocalId;
2365 }
1746 else 2366 else
1747 { 2367 {
1748 newPart = dupe.m_rootPart; 2368 newPart = dupe.m_rootPart;
1749 } 2369 }
2370/*
2371 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2372 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1750 2373
1751 // Need to duplicate the physics actor as well 2374 // Need to duplicate the physics actor as well
1752 PhysicsActor originalPartPa = part.PhysActor; 2375 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1753 if (originalPartPa != null && userExposed)
1754 { 2376 {
1755 PrimitiveBaseShape pbs = newPart.Shape; 2377 PrimitiveBaseShape pbs = newPart.Shape;
1756
1757 newPart.PhysActor 2378 newPart.PhysActor
1758 = m_scene.PhysicsScene.AddPrimShape( 2379 = m_scene.PhysicsScene.AddPrimShape(
1759 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2380 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1760 pbs, 2381 pbs,
1761 newPart.AbsolutePosition, 2382 newPart.AbsolutePosition,
1762 newPart.Scale, 2383 newPart.Scale,
1763 newPart.RotationOffset, 2384 newPart.GetWorldRotation(),
1764 originalPartPa.IsPhysical, 2385 isphys,
2386 isphan,
1765 newPart.LocalId); 2387 newPart.LocalId);
1766 2388
1767 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2389 newPart.DoPhysicsPropertyUpdate(isphys, true);
1768 } 2390 */
2391 if (userExposed)
2392 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2393// }
2394 // copy keyframemotion
1769 if (part.KeyframeMotion != null) 2395 if (part.KeyframeMotion != null)
1770 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); 2396 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe);
1771 } 2397 }
1772 2398
1773 if (userExposed) 2399 if (userExposed)
1774 { 2400 {
1775 dupe.UpdateParentIDs(); 2401// done above dupe.UpdateParentIDs();
2402
2403 if (dupe.m_rootPart.PhysActor != null)
2404 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2405
1776 dupe.HasGroupChanged = true; 2406 dupe.HasGroupChanged = true;
1777 dupe.AttachToBackup(); 2407 dupe.AttachToBackup();
1778 2408
1779 ScheduleGroupForFullUpdate(); 2409 ScheduleGroupForFullUpdate();
1780 } 2410 }
1781 2411
2412 m_dupeInProgress = false;
1782 return dupe; 2413 return dupe;
1783 } 2414 }
1784 2415
@@ -1790,7 +2421,13 @@ namespace OpenSim.Region.Framework.Scenes
1790 /// <param name="cGroupID"></param> 2421 /// <param name="cGroupID"></param>
1791 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2422 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1792 { 2423 {
1793 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2424 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2425// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2426// newpart.LocalId = m_scene.AllocateLocalId();
2427
2428 SetRootPart(newpart);
2429 if (userExposed)
2430 RootPart.Velocity = Vector3.Zero; // In case source is moving
1794 } 2431 }
1795 2432
1796 public void ScriptSetPhysicsStatus(bool usePhysics) 2433 public void ScriptSetPhysicsStatus(bool usePhysics)
@@ -1848,13 +2485,14 @@ namespace OpenSim.Region.Framework.Scenes
1848 2485
1849 if (pa != null) 2486 if (pa != null)
1850 { 2487 {
1851 pa.AddForce(impulse, true); 2488 // false to be applied as a impulse
2489 pa.AddForce(impulse, false);
1852 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2490 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1853 } 2491 }
1854 } 2492 }
1855 } 2493 }
1856 2494
1857 public void applyAngularImpulse(Vector3 impulse) 2495 public void ApplyAngularImpulse(Vector3 impulse)
1858 { 2496 {
1859 PhysicsActor pa = RootPart.PhysActor; 2497 PhysicsActor pa = RootPart.PhysActor;
1860 2498
@@ -1862,21 +2500,8 @@ namespace OpenSim.Region.Framework.Scenes
1862 { 2500 {
1863 if (!IsAttachment) 2501 if (!IsAttachment)
1864 { 2502 {
1865 pa.AddAngularForce(impulse, true); 2503 // false to be applied as a impulse
1866 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2504 pa.AddAngularForce(impulse, false);
1867 }
1868 }
1869 }
1870
1871 public void setAngularImpulse(Vector3 impulse)
1872 {
1873 PhysicsActor pa = RootPart.PhysActor;
1874
1875 if (pa != null)
1876 {
1877 if (!IsAttachment)
1878 {
1879 pa.Torque = impulse;
1880 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2505 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1881 } 2506 }
1882 } 2507 }
@@ -1884,20 +2509,10 @@ namespace OpenSim.Region.Framework.Scenes
1884 2509
1885 public Vector3 GetTorque() 2510 public Vector3 GetTorque()
1886 { 2511 {
1887 PhysicsActor pa = RootPart.PhysActor; 2512 return RootPart.Torque;
1888
1889 if (pa != null)
1890 {
1891 if (!IsAttachment)
1892 {
1893 Vector3 torque = pa.Torque;
1894 return torque;
1895 }
1896 }
1897
1898 return Vector3.Zero;
1899 } 2513 }
1900 2514
2515 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1901 public void MoveToTarget(Vector3 target, float tau) 2516 public void MoveToTarget(Vector3 target, float tau)
1902 { 2517 {
1903 if (IsAttachment) 2518 if (IsAttachment)
@@ -1927,21 +2542,61 @@ namespace OpenSim.Region.Framework.Scenes
1927 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 2542 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1928 2543
1929 if (avatar != null) 2544 if (avatar != null)
2545 {
1930 avatar.ResetMoveToTarget(); 2546 avatar.ResetMoveToTarget();
2547 }
1931 } 2548 }
1932 else 2549 else
1933 { 2550 {
1934 PhysicsActor pa = RootPart.PhysActor; 2551 PhysicsActor pa = RootPart.PhysActor;
1935 2552
1936 if (pa != null && pa.PIDActive) 2553 if (pa != null)
1937 {
1938 pa.PIDActive = false; 2554 pa.PIDActive = false;
1939 2555
1940 ScheduleGroupForTerseUpdate(); 2556 RootPart.ScheduleTerseUpdate(); // send a stop information
2557 }
2558 }
2559
2560 public void rotLookAt(Quaternion target, float strength, float damping)
2561 {
2562 SceneObjectPart rootpart = m_rootPart;
2563 if (rootpart != null)
2564 {
2565 if (IsAttachment)
2566 {
2567 /*
2568 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2569 if (avatar != null)
2570 {
2571 Rotate the Av?
2572 } */
2573 }
2574 else
2575 {
2576 if (rootpart.PhysActor != null)
2577 { // APID must be implemented in your physics system for this to function.
2578 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2579 rootpart.PhysActor.APIDStrength = strength;
2580 rootpart.PhysActor.APIDDamping = damping;
2581 rootpart.PhysActor.APIDActive = true;
2582 }
1941 } 2583 }
1942 } 2584 }
1943 } 2585 }
2586
2587 public void stopLookAt()
2588 {
2589 SceneObjectPart rootpart = m_rootPart;
2590 if (rootpart != null)
2591 {
2592 if (rootpart.PhysActor != null)
2593 { // APID must be implemented in your physics system for this to function.
2594 rootpart.PhysActor.APIDActive = false;
2595 }
2596 }
1944 2597
2598 }
2599
1945 /// <summary> 2600 /// <summary>
1946 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2601 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1947 /// </summary> 2602 /// </summary>
@@ -1958,7 +2613,7 @@ namespace OpenSim.Region.Framework.Scenes
1958 { 2613 {
1959 pa.PIDHoverHeight = height; 2614 pa.PIDHoverHeight = height;
1960 pa.PIDHoverType = hoverType; 2615 pa.PIDHoverType = hoverType;
1961 pa.PIDTau = tau; 2616 pa.PIDHoverTau = tau;
1962 pa.PIDHoverActive = true; 2617 pa.PIDHoverActive = true;
1963 } 2618 }
1964 else 2619 else
@@ -1999,6 +2654,9 @@ namespace OpenSim.Region.Framework.Scenes
1999 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2654 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2000 { 2655 {
2001 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2656 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2657// SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2658// newPart.LocalId = m_scene.AllocateLocalId();
2659
2002 AddPart(newPart); 2660 AddPart(newPart);
2003 2661
2004 SetPartAsNonRoot(newPart); 2662 SetPartAsNonRoot(newPart);
@@ -2048,6 +2706,7 @@ namespace OpenSim.Region.Framework.Scenes
2048 2706
2049 #endregion 2707 #endregion
2050 2708
2709
2051 public override void Update() 2710 public override void Update()
2052 { 2711 {
2053 // Check that the group was not deleted before the scheduled update 2712 // Check that the group was not deleted before the scheduled update
@@ -2055,7 +2714,7 @@ namespace OpenSim.Region.Framework.Scenes
2055 // an object has been deleted from a scene before update was processed. 2714 // an object has been deleted from a scene before update was processed.
2056 // A more fundamental overhaul of the update mechanism is required to eliminate all 2715 // A more fundamental overhaul of the update mechanism is required to eliminate all
2057 // the race conditions. 2716 // the race conditions.
2058 if (IsDeleted) 2717 if (IsDeleted || inTransit)
2059 return; 2718 return;
2060 2719
2061 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2720 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2066,18 +2725,17 @@ namespace OpenSim.Region.Framework.Scenes
2066 // check to see if the physical position or rotation warrant an update. 2725 // check to see if the physical position or rotation warrant an update.
2067 if (m_rootPart.UpdateFlag == UpdateRequired.NONE) 2726 if (m_rootPart.UpdateFlag == UpdateRequired.NONE)
2068 { 2727 {
2069 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2728 // rootpart SendScheduledUpdates will check if a update is needed
2070 2729 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2071 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 2730 }
2072 {
2073 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2074 lastPhysGroupPos = AbsolutePosition;
2075 }
2076 2731
2077 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) 2732 if (IsAttachment)
2733 {
2734 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2735 if (sp != null)
2078 { 2736 {
2079 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 2737 sp.SendAttachmentScheduleUpdate(this);
2080 lastPhysGroupRot = GroupRotation; 2738 return;
2081 } 2739 }
2082 } 2740 }
2083 2741
@@ -2137,20 +2795,30 @@ namespace OpenSim.Region.Framework.Scenes
2137 /// Immediately send a full update for this scene object. 2795 /// Immediately send a full update for this scene object.
2138 /// </summary> 2796 /// </summary>
2139 public void SendGroupFullUpdate() 2797 public void SendGroupFullUpdate()
2140 { 2798 {
2141 if (IsDeleted) 2799 if (IsDeleted)
2142 return; 2800 return;
2143 2801
2144// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2802// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2145 2803
2146 RootPart.SendFullUpdateToAllClients(); 2804 if (IsAttachment)
2805 {
2806 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2807 if (sp != null)
2808 {
2809 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
2810 return;
2811 }
2812 }
2813
2814 RootPart.SendFullUpdateToAllClientsInternal();
2147 2815
2148 SceneObjectPart[] parts = m_parts.GetArray(); 2816 SceneObjectPart[] parts = m_parts.GetArray();
2149 for (int i = 0; i < parts.Length; i++) 2817 for (int i = 0; i < parts.Length; i++)
2150 { 2818 {
2151 SceneObjectPart part = parts[i]; 2819 SceneObjectPart part = parts[i];
2152 if (part != RootPart) 2820 if (part != RootPart)
2153 part.SendFullUpdateToAllClients(); 2821 part.SendFullUpdateToAllClientsInternal();
2154 } 2822 }
2155 } 2823 }
2156 2824
@@ -2162,7 +2830,7 @@ namespace OpenSim.Region.Framework.Scenes
2162 /// </summary> 2830 /// </summary>
2163 public void SendGroupRootTerseUpdate() 2831 public void SendGroupRootTerseUpdate()
2164 { 2832 {
2165 if (IsDeleted) 2833 if (IsDeleted || inTransit)
2166 return; 2834 return;
2167 2835
2168 RootPart.SendTerseUpdateToAllClients(); 2836 RootPart.SendTerseUpdateToAllClients();
@@ -2181,12 +2849,22 @@ namespace OpenSim.Region.Framework.Scenes
2181 /// </summary> 2849 /// </summary>
2182 public void SendGroupTerseUpdate() 2850 public void SendGroupTerseUpdate()
2183 { 2851 {
2184 if (IsDeleted) 2852 if (IsDeleted || inTransit)
2185 return; 2853 return;
2186 2854
2855 if (IsAttachment)
2856 {
2857 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2858 if (sp != null)
2859 {
2860 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
2861 return;
2862 }
2863 }
2864
2187 SceneObjectPart[] parts = m_parts.GetArray(); 2865 SceneObjectPart[] parts = m_parts.GetArray();
2188 for (int i = 0; i < parts.Length; i++) 2866 for (int i = 0; i < parts.Length; i++)
2189 parts[i].SendTerseUpdateToAllClients(); 2867 parts[i].SendTerseUpdateToAllClientsInternal();
2190 } 2868 }
2191 2869
2192 /// <summary> 2870 /// <summary>
@@ -2294,9 +2972,41 @@ namespace OpenSim.Region.Framework.Scenes
2294 return; 2972 return;
2295 } 2973 }
2296 2974
2975 // physical prims count limit
2976 // not very eficient :(
2977
2978 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
2979 m_scene.m_linksetPhysCapacity)
2980 {
2981 int cntr = 0;
2982 foreach (SceneObjectPart part in Parts)
2983 {
2984 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2985 cntr++;
2986 }
2987 foreach (SceneObjectPart part in objectGroup.Parts)
2988 {
2989 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2990 cntr++;
2991 }
2992
2993 if (cntr > m_scene.m_linksetPhysCapacity)
2994 {
2995 // cancel physics
2996 RootPart.Flags &= ~PrimFlags.Physics;
2997 ApplyPhysics();
2998 }
2999 }
3000
3001
2297 // 'linkPart' == the root of the group being linked into this group 3002 // 'linkPart' == the root of the group being linked into this group
2298 SceneObjectPart linkPart = objectGroup.m_rootPart; 3003 SceneObjectPart linkPart = objectGroup.m_rootPart;
2299 3004
3005 if (m_rootPart.PhysActor != null)
3006 m_rootPart.PhysActor.Building = true;
3007 if (linkPart.PhysActor != null)
3008 linkPart.PhysActor.Building = true;
3009
2300 // physics flags from group to be applied to linked parts 3010 // physics flags from group to be applied to linked parts
2301 bool grpusephys = UsesPhysics; 3011 bool grpusephys = UsesPhysics;
2302 bool grptemporary = IsTemporary; 3012 bool grptemporary = IsTemporary;
@@ -2313,22 +3023,24 @@ namespace OpenSim.Region.Framework.Scenes
2313 // First move the new group's root SOP's position to be relative to ours 3023 // First move the new group's root SOP's position to be relative to ours
2314 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, 3024 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2315 // this code can be reordered to have a more logical flow.) 3025 // this code can be reordered to have a more logical flow.)
2316 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 3026 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2317 // Assign the new parent to the root of the old group 3027 // Assign the new parent to the root of the old group
2318 linkPart.ParentID = m_rootPart.LocalId; 3028 linkPart.ParentID = m_rootPart.LocalId;
2319 // Now that it's a child, it's group position is our root position 3029 // Now that it's a child, it's group position is our root position
2320 linkPart.GroupPosition = AbsolutePosition; 3030 linkPart.setGroupPosition(AbsolutePosition);
2321 3031
2322 Vector3 axPos = linkPart.OffsetPosition;
2323 // Rotate the linking root SOP's position to be relative to the new root prim 3032 // Rotate the linking root SOP's position to be relative to the new root prim
2324 Quaternion parentRot = m_rootPart.RotationOffset; 3033 Quaternion parentRot = m_rootPart.RotationOffset;
2325 axPos *= Quaternion.Inverse(parentRot);
2326 linkPart.OffsetPosition = axPos;
2327 3034
2328 // Make the linking root SOP's rotation relative to the new root prim 3035 // Make the linking root SOP's rotation relative to the new root prim
2329 Quaternion oldRot = linkPart.RotationOffset; 3036 Quaternion oldRot = linkPart.RotationOffset;
2330 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3037 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2331 linkPart.RotationOffset = newRot; 3038 linkPart.setRotationOffset(newRot);
3039
3040 Vector3 axPos = linkPart.OffsetPosition;
3041 axPos *= Quaternion.Conjugate(parentRot);
3042 linkPart.OffsetPosition = axPos;
3043
2332 3044
2333 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 3045 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2334 // Now that we know this SOG has at least two SOPs in it, the new root 3046 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2358,10 +3070,12 @@ namespace OpenSim.Region.Framework.Scenes
2358 m_parts.Add(linkPart.UUID, linkPart); 3070 m_parts.Add(linkPart.UUID, linkPart);
2359 3071
2360 linkPart.SetParent(this); 3072 linkPart.SetParent(this);
3073 m_scene.updateScenePartGroup(linkPart, this);
3074
2361 linkPart.CreateSelected = true; 3075 linkPart.CreateSelected = true;
2362 3076
2363 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 3077 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2364 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 3078 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2365 3079
2366 // If the added SOP is physical, also tell the physics engine about the link relationship. 3080 // If the added SOP is physical, also tell the physics engine about the link relationship.
2367 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3081 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2371,6 +3085,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 } 3085 }
2372 3086
2373 linkPart.LinkNum = linkNum++; 3087 linkPart.LinkNum = linkNum++;
3088 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2374 3089
2375 // Get a list of the SOP's in the old group in order of their linknum's. 3090 // Get a list of the SOP's in the old group in order of their linknum's.
2376 SceneObjectPart[] ogParts = objectGroup.Parts; 3091 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2389,7 +3104,7 @@ namespace OpenSim.Region.Framework.Scenes
2389 3104
2390 // Update the physics flags for the newly added SOP 3105 // Update the physics flags for the newly added SOP
2391 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) 3106 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
2392 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 3107 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2393 3108
2394 // If the added SOP is physical, also tell the physics engine about the link relationship. 3109 // If the added SOP is physical, also tell the physics engine about the link relationship.
2395 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3110 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2407,7 +3122,7 @@ namespace OpenSim.Region.Framework.Scenes
2407 objectGroup.IsDeleted = true; 3122 objectGroup.IsDeleted = true;
2408 3123
2409 objectGroup.m_parts.Clear(); 3124 objectGroup.m_parts.Clear();
2410 3125
2411 // Can't do this yet since backup still makes use of the root part without any synchronization 3126 // Can't do this yet since backup still makes use of the root part without any synchronization
2412// objectGroup.m_rootPart = null; 3127// objectGroup.m_rootPart = null;
2413 3128
@@ -2423,6 +3138,9 @@ namespace OpenSim.Region.Framework.Scenes
2423 // unmoved prims! 3138 // unmoved prims!
2424 ResetChildPrimPhysicsPositions(); 3139 ResetChildPrimPhysicsPositions();
2425 3140
3141 if (m_rootPart.PhysActor != null)
3142 m_rootPart.PhysActor.Building = false;
3143
2426 //HasGroupChanged = true; 3144 //HasGroupChanged = true;
2427 //ScheduleGroupForFullUpdate(); 3145 //ScheduleGroupForFullUpdate();
2428 } 3146 }
@@ -2490,7 +3208,10 @@ namespace OpenSim.Region.Framework.Scenes
2490// m_log.DebugFormat( 3208// m_log.DebugFormat(
2491// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 3209// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2492// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 3210// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2493 3211
3212 if (m_rootPart.PhysActor != null)
3213 m_rootPart.PhysActor.Building = true;
3214
2494 linkPart.ClearUndoState(); 3215 linkPart.ClearUndoState();
2495 3216
2496 Vector3 worldPos = linkPart.GetWorldPosition(); 3217 Vector3 worldPos = linkPart.GetWorldPosition();
@@ -2545,30 +3266,31 @@ namespace OpenSim.Region.Framework.Scenes
2545 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3266 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2546 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3267 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2547 */ 3268 */
2548 linkPart.GroupPosition = worldPos; 3269 linkPart.setGroupPosition(worldPos);
2549 linkPart.OffsetPosition = Vector3.Zero; 3270 linkPart.setOffsetPosition(Vector3.Zero);
2550 linkPart.RotationOffset = worldRot; 3271 linkPart.setRotationOffset(worldRot);
2551 3272
2552 // Create a new SOG to go around this unlinked and unattached SOP 3273 // Create a new SOG to go around this unlinked and unattached SOP
2553 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3274 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2554 3275
2555 m_scene.AddNewSceneObject(objectGroup, true); 3276 m_scene.AddNewSceneObject(objectGroup, true);
2556 3277
2557 if (sendEvents)
2558 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2559
2560 linkPart.Rezzed = RootPart.Rezzed; 3278 linkPart.Rezzed = RootPart.Rezzed;
2561 3279
2562 // We must persist the delinked group to the database immediately, for safety. The problem 3280 // When we delete a group, we currently have to force persist to the database if the object id has changed
2563 // is that although in memory the new group has a new SceneGroupID, in the database it 3281 // (since delete works by deleting all rows which have a given object id)
2564 // still has the parent group's SceneGroupID (until the next backup). This means that if the 3282
2565 // parent group is deleted then the delinked group will also be deleted from the database. 3283 // this is as it seems to be in sl now
2566 // This problem will disappear if the region remains alive long enough for another backup, 3284 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2567 // since at that time the delinked group's new SceneGroupID will be written to the database. 3285 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2568 // But if the region crashes before that then the prims will be permanently gone, and this must 3286
2569 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case 3287 if (m_rootPart.PhysActor != null)
2570 // because the delinked group doesn't know when the source group is deleted.) 3288 m_rootPart.PhysActor.Building = false;
2571 m_scene.ForceSceneObjectBackup(objectGroup); 3289
3290 objectGroup.HasGroupChangedDueToDelink = true;
3291
3292 if (sendEvents)
3293 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2572 3294
2573 return objectGroup; 3295 return objectGroup;
2574 } 3296 }
@@ -2579,7 +3301,9 @@ namespace OpenSim.Region.Framework.Scenes
2579 /// <param name="objectGroup"></param> 3301 /// <param name="objectGroup"></param>
2580 public virtual void DetachFromBackup() 3302 public virtual void DetachFromBackup()
2581 { 3303 {
2582 if (Backup && Scene != null) 3304 if (m_scene != null)
3305 m_scene.SceneGraph.FireDetachFromBackup(this);
3306 if (m_isBackedUp && Scene != null)
2583 m_scene.EventManager.OnBackup -= ProcessBackup; 3307 m_scene.EventManager.OnBackup -= ProcessBackup;
2584 3308
2585 Backup = false; 3309 Backup = false;
@@ -2595,14 +3319,14 @@ namespace OpenSim.Region.Framework.Scenes
2595 Quaternion parentRot = oldGroupRotation; 3319 Quaternion parentRot = oldGroupRotation;
2596 Quaternion oldRot = part.RotationOffset; 3320 Quaternion oldRot = part.RotationOffset;
2597 3321
2598 // Move our position to not be relative to the old parent 3322 // Move our position in world
2599 Vector3 axPos = part.OffsetPosition; 3323 Vector3 axPos = part.OffsetPosition;
2600 axPos *= parentRot; 3324 axPos *= parentRot;
2601 part.OffsetPosition = axPos; 3325 Vector3 newPos = oldGroupPosition + axPos;
2602 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 3326 part.setGroupPosition(newPos);
2603 part.OffsetPosition = Vector3.Zero; 3327 part.setOffsetPosition(Vector3.Zero);
2604 3328
2605 // Compution our rotation to be not relative to the old parent 3329 // Compution our rotation in world
2606 Quaternion worldRot = parentRot * oldRot; 3330 Quaternion worldRot = parentRot * oldRot;
2607 part.RotationOffset = worldRot; 3331 part.RotationOffset = worldRot;
2608 3332
@@ -2613,29 +3337,32 @@ namespace OpenSim.Region.Framework.Scenes
2613 3337
2614 part.LinkNum = linkNum; 3338 part.LinkNum = linkNum;
2615 3339
3340 m_scene.updateScenePartGroup(part, this);
3341
2616 // Compute the new position of this SOP relative to the group position 3342 // Compute the new position of this SOP relative to the group position
2617 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 3343 part.setOffsetPosition(newPos - AbsolutePosition);
2618 3344
2619 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3345 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
2620 // It would have the affect of setting the physics engine position multiple 3346 // It would have the affect of setting the physics engine position multiple
2621 // times. In theory, that is not necessary but I don't have a good linkset 3347 // times. In theory, that is not necessary but I don't have a good linkset
2622 // test to know that cleaning up this code wouldn't break things.) 3348 // test to know that cleaning up this code wouldn't break things.)
2623 3349
2624 // Rotate the relative position by the rotation of the group
2625 Quaternion rootRotation = m_rootPart.RotationOffset;
2626 Vector3 pos = part.OffsetPosition;
2627 pos *= Quaternion.Inverse(rootRotation);
2628 part.OffsetPosition = pos;
2629
2630 // Compute the SOP's rotation relative to the rotation of the group. 3350 // Compute the SOP's rotation relative to the rotation of the group.
2631 parentRot = m_rootPart.RotationOffset; 3351 parentRot = m_rootPart.RotationOffset;
3352
2632 oldRot = part.RotationOffset; 3353 oldRot = part.RotationOffset;
2633 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3354 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2634 part.RotationOffset = newRot; 3355 part.setRotationOffset(newRot);
3356
3357 Vector3 pos = part.OffsetPosition;
3358 pos *= Quaternion.Conjugate(parentRot);
3359
3360 part.OffsetPosition = pos; // update position and orientation on physics also
2635 3361
2636 // Since this SOP's state has changed, push those changes into the physics engine 3362 // Since this SOP's state has changed, push those changes into the physics engine
2637 // and the simulator. 3363 // and the simulator.
2638 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3364 // done on caller
3365// part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2639 } 3366 }
2640 3367
2641 /// <summary> 3368 /// <summary>
@@ -2663,10 +3390,14 @@ namespace OpenSim.Region.Framework.Scenes
2663 { 3390 {
2664 if (!BlockGrabOverride && !part.BlockGrab) 3391 if (!BlockGrabOverride && !part.BlockGrab)
2665 { 3392 {
2666 Vector3 llmoveforce = pos - AbsolutePosition; 3393/* Vector3 llmoveforce = pos - AbsolutePosition;
2667 Vector3 grabforce = llmoveforce; 3394 Vector3 grabforce = llmoveforce;
2668 grabforce = (grabforce / 10) * pa.Mass; 3395 grabforce = (grabforce / 10) * pa.Mass;
2669 pa.AddForce(grabforce, true); 3396 */
3397 // empirically convert distance diference to a impulse
3398 Vector3 grabforce = pos - AbsolutePosition;
3399 grabforce = grabforce * (pa.Mass/ 10.0f);
3400 pa.AddForce(grabforce, false);
2670 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 3401 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2671 } 3402 }
2672 } 3403 }
@@ -2880,6 +3611,8 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <param name="SetVolumeDetect"></param> 3611 /// <param name="SetVolumeDetect"></param>
2881 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) 3612 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
2882 { 3613 {
3614 HasGroupChanged = true;
3615
2883 SceneObjectPart selectionPart = GetPart(localID); 3616 SceneObjectPart selectionPart = GetPart(localID);
2884 3617
2885 if (Scene != null) 3618 if (Scene != null)
@@ -2905,8 +3638,12 @@ namespace OpenSim.Region.Framework.Scenes
2905 { 3638 {
2906 SceneObjectPart[] parts = m_parts.GetArray(); 3639 SceneObjectPart[] parts = m_parts.GetArray();
2907 3640
2908 if (Scene != null) 3641 if (Scene != null && UsePhysics)
2909 { 3642 {
3643 int maxprims = m_scene.m_linksetPhysCapacity;
3644 bool checkShape = (maxprims > 0 &&
3645 parts.Length > maxprims);
3646
2910 for (int i = 0; i < parts.Length; i++) 3647 for (int i = 0; i < parts.Length; i++)
2911 { 3648 {
2912 SceneObjectPart part = parts[i]; 3649 SceneObjectPart part = parts[i];
@@ -2917,11 +3654,34 @@ namespace OpenSim.Region.Framework.Scenes
2917 UsePhysics = false; // Reset physics 3654 UsePhysics = false; // Reset physics
2918 break; 3655 break;
2919 } 3656 }
3657
3658 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3659 {
3660 if (--maxprims < 0)
3661 {
3662 UsePhysics = false;
3663 break;
3664 }
3665 }
2920 } 3666 }
2921 } 3667 }
2922 3668
2923 for (int i = 0; i < parts.Length; i++) 3669 if (parts.Length > 1)
2924 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3670 {
3671 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3672
3673 for (int i = 0; i < parts.Length; i++)
3674 {
3675
3676 if (parts[i].UUID != m_rootPart.UUID)
3677 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3678 }
3679
3680 if (m_rootPart.PhysActor != null)
3681 m_rootPart.PhysActor.Building = false;
3682 }
3683 else
3684 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2925 } 3685 }
2926 } 3686 }
2927 3687
@@ -2934,6 +3694,17 @@ namespace OpenSim.Region.Framework.Scenes
2934 } 3694 }
2935 } 3695 }
2936 3696
3697
3698
3699 /// <summary>
3700 /// Gets the number of parts
3701 /// </summary>
3702 /// <returns></returns>
3703 public int GetPartCount()
3704 {
3705 return Parts.Count();
3706 }
3707
2937 /// <summary> 3708 /// <summary>
2938 /// Update the texture entry for this part 3709 /// Update the texture entry for this part
2939 /// </summary> 3710 /// </summary>
@@ -2978,7 +3749,23 @@ namespace OpenSim.Region.Framework.Scenes
2978 { 3749 {
2979 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); 3750 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2980 3751
2981 AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); 3752 bool god = Scene.Permissions.IsGod(AgentID);
3753
3754 if (field == 1 && god)
3755 {
3756 ForEachPart(part =>
3757 {
3758 part.BaseMask = RootPart.BaseMask;
3759 });
3760 }
3761
3762 AdjustChildPrimPermissions(false);
3763
3764 if (field == 1 && god) // Base mask was set. Update all child part inventories
3765 {
3766 foreach (SceneObjectPart part in Parts)
3767 part.Inventory.ApplyGodPermissions(RootPart.BaseMask);
3768 }
2982 3769
2983 HasGroupChanged = true; 3770 HasGroupChanged = true;
2984 3771
@@ -3025,8 +3812,6 @@ namespace OpenSim.Region.Framework.Scenes
3025 3812
3026 PhysicsActor pa = m_rootPart.PhysActor; 3813 PhysicsActor pa = m_rootPart.PhysActor;
3027 3814
3028 RootPart.StoreUndoState(true);
3029
3030 if (Scene != null) 3815 if (Scene != null)
3031 { 3816 {
3032 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); 3817 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
@@ -3054,7 +3839,6 @@ namespace OpenSim.Region.Framework.Scenes
3054 SceneObjectPart obPart = parts[i]; 3839 SceneObjectPart obPart = parts[i];
3055 if (obPart.UUID != m_rootPart.UUID) 3840 if (obPart.UUID != m_rootPart.UUID)
3056 { 3841 {
3057// obPart.IgnoreUndoUpdate = true;
3058 Vector3 oldSize = new Vector3(obPart.Scale); 3842 Vector3 oldSize = new Vector3(obPart.Scale);
3059 3843
3060 float f = 1.0f; 3844 float f = 1.0f;
@@ -3166,8 +3950,6 @@ namespace OpenSim.Region.Framework.Scenes
3166 z *= a; 3950 z *= a;
3167 } 3951 }
3168 } 3952 }
3169
3170// obPart.IgnoreUndoUpdate = false;
3171 } 3953 }
3172 } 3954 }
3173 } 3955 }
@@ -3177,9 +3959,7 @@ namespace OpenSim.Region.Framework.Scenes
3177 prevScale.Y *= y; 3959 prevScale.Y *= y;
3178 prevScale.Z *= z; 3960 prevScale.Z *= z;
3179 3961
3180// RootPart.IgnoreUndoUpdate = true;
3181 RootPart.Resize(prevScale); 3962 RootPart.Resize(prevScale);
3182// RootPart.IgnoreUndoUpdate = false;
3183 3963
3184 for (int i = 0; i < parts.Length; i++) 3964 for (int i = 0; i < parts.Length; i++)
3185 { 3965 {
@@ -3187,8 +3967,6 @@ namespace OpenSim.Region.Framework.Scenes
3187 3967
3188 if (obPart.UUID != m_rootPart.UUID) 3968 if (obPart.UUID != m_rootPart.UUID)
3189 { 3969 {
3190 obPart.IgnoreUndoUpdate = true;
3191
3192 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3970 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3193 currentpos.X *= x; 3971 currentpos.X *= x;
3194 currentpos.Y *= y; 3972 currentpos.Y *= y;
@@ -3201,16 +3979,12 @@ namespace OpenSim.Region.Framework.Scenes
3201 3979
3202 obPart.Resize(newSize); 3980 obPart.Resize(newSize);
3203 obPart.UpdateOffSet(currentpos); 3981 obPart.UpdateOffSet(currentpos);
3204
3205 obPart.IgnoreUndoUpdate = false;
3206 } 3982 }
3207 3983
3208// obPart.IgnoreUndoUpdate = false; 3984 HasGroupChanged = true;
3209// obPart.StoreUndoState(); 3985 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3986 ScheduleGroupForTerseUpdate();
3210 } 3987 }
3211
3212// m_log.DebugFormat(
3213// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
3214 } 3988 }
3215 3989
3216 #endregion 3990 #endregion
@@ -3223,14 +3997,6 @@ namespace OpenSim.Region.Framework.Scenes
3223 /// <param name="pos"></param> 3997 /// <param name="pos"></param>
3224 public void UpdateGroupPosition(Vector3 pos) 3998 public void UpdateGroupPosition(Vector3 pos)
3225 { 3999 {
3226// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
3227
3228 RootPart.StoreUndoState(true);
3229
3230// SceneObjectPart[] parts = m_parts.GetArray();
3231// for (int i = 0; i < parts.Length; i++)
3232// parts[i].StoreUndoState();
3233
3234 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 4000 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
3235 { 4001 {
3236 if (IsAttachment) 4002 if (IsAttachment)
@@ -3263,21 +4029,17 @@ namespace OpenSim.Region.Framework.Scenes
3263 /// </summary> 4029 /// </summary>
3264 /// <param name="pos"></param> 4030 /// <param name="pos"></param>
3265 /// <param name="localID"></param> 4031 /// <param name="localID"></param>
4032 ///
4033
3266 public void UpdateSinglePosition(Vector3 pos, uint localID) 4034 public void UpdateSinglePosition(Vector3 pos, uint localID)
3267 { 4035 {
3268 SceneObjectPart part = GetPart(localID); 4036 SceneObjectPart part = GetPart(localID);
3269 4037
3270// SceneObjectPart[] parts = m_parts.GetArray();
3271// for (int i = 0; i < parts.Length; i++)
3272// parts[i].StoreUndoState();
3273
3274 if (part != null) 4038 if (part != null)
3275 { 4039 {
3276// m_log.DebugFormat( 4040// unlock parts position change
3277// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 4041 if (m_rootPart.PhysActor != null)
3278 4042 m_rootPart.PhysActor.Building = true;
3279 part.StoreUndoState(false);
3280 part.IgnoreUndoUpdate = true;
3281 4043
3282 if (part.UUID == m_rootPart.UUID) 4044 if (part.UUID == m_rootPart.UUID)
3283 { 4045 {
@@ -3288,8 +4050,10 @@ namespace OpenSim.Region.Framework.Scenes
3288 part.UpdateOffSet(pos); 4050 part.UpdateOffSet(pos);
3289 } 4051 }
3290 4052
4053 if (m_rootPart.PhysActor != null)
4054 m_rootPart.PhysActor.Building = false;
4055
3291 HasGroupChanged = true; 4056 HasGroupChanged = true;
3292 part.IgnoreUndoUpdate = false;
3293 } 4057 }
3294 } 4058 }
3295 4059
@@ -3299,13 +4063,7 @@ namespace OpenSim.Region.Framework.Scenes
3299 /// <param name="newPos"></param> 4063 /// <param name="newPos"></param>
3300 public void UpdateRootPosition(Vector3 newPos) 4064 public void UpdateRootPosition(Vector3 newPos)
3301 { 4065 {
3302// m_log.DebugFormat( 4066 // needs to be called with phys building true
3303// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
3304
3305// SceneObjectPart[] parts = m_parts.GetArray();
3306// for (int i = 0; i < parts.Length; i++)
3307// parts[i].StoreUndoState();
3308
3309 Vector3 oldPos; 4067 Vector3 oldPos;
3310 4068
3311 if (IsAttachment) 4069 if (IsAttachment)
@@ -3326,12 +4084,19 @@ namespace OpenSim.Region.Framework.Scenes
3326 } 4084 }
3327 4085
3328 AbsolutePosition = newPos; 4086 AbsolutePosition = newPos;
3329 4087
3330 if (IsAttachment) 4088 if (IsAttachment)
3331 m_rootPart.AttachedPos = newPos; 4089 m_rootPart.AttachedPos = newPos;
3332 4090
3333 HasGroupChanged = true; 4091 HasGroupChanged = true;
3334 ScheduleGroupForTerseUpdate(); 4092 if (m_rootPart.Undoing)
4093 {
4094 ScheduleGroupForFullUpdate();
4095 }
4096 else
4097 {
4098 ScheduleGroupForTerseUpdate();
4099 }
3335 } 4100 }
3336 4101
3337 #endregion 4102 #endregion
@@ -3344,24 +4109,16 @@ namespace OpenSim.Region.Framework.Scenes
3344 /// <param name="rot"></param> 4109 /// <param name="rot"></param>
3345 public void UpdateGroupRotationR(Quaternion rot) 4110 public void UpdateGroupRotationR(Quaternion rot)
3346 { 4111 {
3347// m_log.DebugFormat(
3348// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
3349
3350// SceneObjectPart[] parts = m_parts.GetArray();
3351// for (int i = 0; i < parts.Length; i++)
3352// parts[i].StoreUndoState();
3353
3354 m_rootPart.StoreUndoState(true);
3355
3356 m_rootPart.UpdateRotation(rot); 4112 m_rootPart.UpdateRotation(rot);
3357 4113
4114/* this is done by rootpart RotationOffset set called by UpdateRotation
3358 PhysicsActor actor = m_rootPart.PhysActor; 4115 PhysicsActor actor = m_rootPart.PhysActor;
3359 if (actor != null) 4116 if (actor != null)
3360 { 4117 {
3361 actor.Orientation = m_rootPart.RotationOffset; 4118 actor.Orientation = m_rootPart.RotationOffset;
3362 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 4119 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
3363 } 4120 }
3364 4121*/
3365 HasGroupChanged = true; 4122 HasGroupChanged = true;
3366 ScheduleGroupForTerseUpdate(); 4123 ScheduleGroupForTerseUpdate();
3367 } 4124 }
@@ -3373,16 +4130,6 @@ namespace OpenSim.Region.Framework.Scenes
3373 /// <param name="rot"></param> 4130 /// <param name="rot"></param>
3374 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 4131 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3375 { 4132 {
3376// m_log.DebugFormat(
3377// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
3378
3379// SceneObjectPart[] parts = m_parts.GetArray();
3380// for (int i = 0; i < parts.Length; i++)
3381// parts[i].StoreUndoState();
3382
3383 RootPart.StoreUndoState(true);
3384 RootPart.IgnoreUndoUpdate = true;
3385
3386 m_rootPart.UpdateRotation(rot); 4133 m_rootPart.UpdateRotation(rot);
3387 4134
3388 PhysicsActor actor = m_rootPart.PhysActor; 4135 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3401,8 +4148,6 @@ namespace OpenSim.Region.Framework.Scenes
3401 4148
3402 HasGroupChanged = true; 4149 HasGroupChanged = true;
3403 ScheduleGroupForTerseUpdate(); 4150 ScheduleGroupForTerseUpdate();
3404
3405 RootPart.IgnoreUndoUpdate = false;
3406 } 4151 }
3407 4152
3408 /// <summary> 4153 /// <summary>
@@ -3415,13 +4160,11 @@ namespace OpenSim.Region.Framework.Scenes
3415 SceneObjectPart part = GetPart(localID); 4160 SceneObjectPart part = GetPart(localID);
3416 4161
3417 SceneObjectPart[] parts = m_parts.GetArray(); 4162 SceneObjectPart[] parts = m_parts.GetArray();
3418 for (int i = 0; i < parts.Length; i++)
3419 parts[i].StoreUndoState();
3420 4163
3421 if (part != null) 4164 if (part != null)
3422 { 4165 {
3423// m_log.DebugFormat( 4166 if (m_rootPart.PhysActor != null)
3424// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 4167 m_rootPart.PhysActor.Building = true;
3425 4168
3426 if (part.UUID == m_rootPart.UUID) 4169 if (part.UUID == m_rootPart.UUID)
3427 { 4170 {
@@ -3431,6 +4174,9 @@ namespace OpenSim.Region.Framework.Scenes
3431 { 4174 {
3432 part.UpdateRotation(rot); 4175 part.UpdateRotation(rot);
3433 } 4176 }
4177
4178 if (m_rootPart.PhysActor != null)
4179 m_rootPart.PhysActor.Building = false;
3434 } 4180 }
3435 } 4181 }
3436 4182
@@ -3444,12 +4190,8 @@ namespace OpenSim.Region.Framework.Scenes
3444 SceneObjectPart part = GetPart(localID); 4190 SceneObjectPart part = GetPart(localID);
3445 if (part != null) 4191 if (part != null)
3446 { 4192 {
3447// m_log.DebugFormat( 4193 if (m_rootPart.PhysActor != null)
3448// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 4194 m_rootPart.PhysActor.Building = true;
3449// part.Name, part.LocalId, rot);
3450
3451 part.StoreUndoState();
3452 part.IgnoreUndoUpdate = true;
3453 4195
3454 if (part.UUID == m_rootPart.UUID) 4196 if (part.UUID == m_rootPart.UUID)
3455 { 4197 {
@@ -3462,7 +4204,8 @@ namespace OpenSim.Region.Framework.Scenes
3462 part.OffsetPosition = pos; 4204 part.OffsetPosition = pos;
3463 } 4205 }
3464 4206
3465 part.IgnoreUndoUpdate = false; 4207 if (m_rootPart.PhysActor != null)
4208 m_rootPart.PhysActor.Building = false;
3466 } 4209 }
3467 } 4210 }
3468 4211
@@ -3472,15 +4215,12 @@ namespace OpenSim.Region.Framework.Scenes
3472 /// <param name="rot"></param> 4215 /// <param name="rot"></param>
3473 public void UpdateRootRotation(Quaternion rot) 4216 public void UpdateRootRotation(Quaternion rot)
3474 { 4217 {
3475// m_log.DebugFormat( 4218 // needs to be called with phys building true
3476// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3477// Name, LocalId, rot);
3478
3479 Quaternion axRot = rot; 4219 Quaternion axRot = rot;
3480 Quaternion oldParentRot = m_rootPart.RotationOffset; 4220 Quaternion oldParentRot = m_rootPart.RotationOffset;
3481 4221
3482 m_rootPart.StoreUndoState(); 4222 //Don't use UpdateRotation because it schedules an update prematurely
3483 m_rootPart.UpdateRotation(rot); 4223 m_rootPart.RotationOffset = rot;
3484 4224
3485 PhysicsActor pa = m_rootPart.PhysActor; 4225 PhysicsActor pa = m_rootPart.PhysActor;
3486 4226
@@ -3496,35 +4236,145 @@ namespace OpenSim.Region.Framework.Scenes
3496 SceneObjectPart prim = parts[i]; 4236 SceneObjectPart prim = parts[i];
3497 if (prim.UUID != m_rootPart.UUID) 4237 if (prim.UUID != m_rootPart.UUID)
3498 { 4238 {
3499 prim.IgnoreUndoUpdate = true; 4239 Quaternion NewRot = oldParentRot * prim.RotationOffset;
4240 NewRot = Quaternion.Inverse(axRot) * NewRot;
4241 prim.RotationOffset = NewRot;
4242
3500 Vector3 axPos = prim.OffsetPosition; 4243 Vector3 axPos = prim.OffsetPosition;
4244
3501 axPos *= oldParentRot; 4245 axPos *= oldParentRot;
3502 axPos *= Quaternion.Inverse(axRot); 4246 axPos *= Quaternion.Inverse(axRot);
3503 prim.OffsetPosition = axPos; 4247 prim.OffsetPosition = axPos;
3504 Quaternion primsRot = prim.RotationOffset;
3505 Quaternion newRot = oldParentRot * primsRot;
3506 newRot = Quaternion.Inverse(axRot) * newRot;
3507 prim.RotationOffset = newRot;
3508 prim.ScheduleTerseUpdate();
3509 prim.IgnoreUndoUpdate = false;
3510 } 4248 }
3511 } 4249 }
3512 4250
3513// for (int i = 0; i < parts.Length; i++) 4251 HasGroupChanged = true;
3514// { 4252 ScheduleGroupForFullUpdate();
3515// SceneObjectPart childpart = parts[i]; 4253 }
3516// if (childpart != m_rootPart)
3517// {
3518//// childpart.IgnoreUndoUpdate = false;
3519//// childpart.StoreUndoState();
3520// }
3521// }
3522 4254
3523 m_rootPart.ScheduleTerseUpdate(); 4255 private enum updatetype :int
4256 {
4257 none = 0,
4258 partterse = 1,
4259 partfull = 2,
4260 groupterse = 3,
4261 groupfull = 4
4262 }
3524 4263
3525// m_log.DebugFormat( 4264 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3526// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 4265 {
3527// Name, LocalId, rot); 4266 // TODO this still as excessive *.Schedule*Update()s
4267
4268 if (part != null && part.ParentGroup != null)
4269 {
4270 ObjectChangeType change = data.change;
4271 bool togroup = ((change & ObjectChangeType.Group) != 0);
4272 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
4273
4274 SceneObjectGroup group = part.ParentGroup;
4275 PhysicsActor pha = group.RootPart.PhysActor;
4276
4277 updatetype updateType = updatetype.none;
4278
4279 if (togroup)
4280 {
4281 // related to group
4282 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
4283 {
4284 if ((change & ObjectChangeType.Rotation) != 0)
4285 {
4286 group.RootPart.UpdateRotation(data.rotation);
4287 updateType = updatetype.none;
4288 }
4289 if ((change & ObjectChangeType.Position) != 0)
4290 {
4291 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
4292 UpdateGroupPosition(data.position);
4293 updateType = updatetype.groupterse;
4294 }
4295 else
4296 // ugly rotation update of all parts
4297 {
4298 group.ResetChildPrimPhysicsPositions();
4299 }
4300
4301 }
4302 if ((change & ObjectChangeType.Scale) != 0)
4303 {
4304 if (pha != null)
4305 pha.Building = true;
4306
4307 group.GroupResize(data.scale);
4308 updateType = updatetype.none;
4309
4310 if (pha != null)
4311 pha.Building = false;
4312 }
4313 }
4314 else
4315 {
4316 // related to single prim in a link-set ( ie group)
4317 if (pha != null)
4318 pha.Building = true;
4319
4320 // root part is special
4321 // parts offset positions or rotations need to change also
4322
4323 if (part == group.RootPart)
4324 {
4325 if ((change & ObjectChangeType.Rotation) != 0)
4326 group.UpdateRootRotation(data.rotation);
4327 if ((change & ObjectChangeType.Position) != 0)
4328 group.UpdateRootPosition(data.position);
4329 if ((change & ObjectChangeType.Scale) != 0)
4330 part.Resize(data.scale);
4331 }
4332 else
4333 {
4334 if ((change & ObjectChangeType.Position) != 0)
4335 {
4336 part.OffsetPosition = data.position;
4337 updateType = updatetype.partterse;
4338 }
4339 if ((change & ObjectChangeType.Rotation) != 0)
4340 {
4341 part.UpdateRotation(data.rotation);
4342 updateType = updatetype.none;
4343 }
4344 if ((change & ObjectChangeType.Scale) != 0)
4345 {
4346 part.Resize(data.scale);
4347 updateType = updatetype.none;
4348 }
4349 }
4350
4351 if (pha != null)
4352 pha.Building = false;
4353 }
4354
4355 if (updateType != updatetype.none)
4356 {
4357 group.HasGroupChanged = true;
4358
4359 switch (updateType)
4360 {
4361 case updatetype.partterse:
4362 part.ScheduleTerseUpdate();
4363 break;
4364 case updatetype.partfull:
4365 part.ScheduleFullUpdate();
4366 break;
4367 case updatetype.groupterse:
4368 group.ScheduleGroupForTerseUpdate();
4369 break;
4370 case updatetype.groupfull:
4371 group.ScheduleGroupForFullUpdate();
4372 break;
4373 default:
4374 break;
4375 }
4376 }
4377 }
3528 } 4378 }
3529 4379
3530 #endregion 4380 #endregion
@@ -3565,6 +4415,8 @@ namespace OpenSim.Region.Framework.Scenes
3565 waypoint.handle = handle; 4415 waypoint.handle = handle;
3566 lock (m_rotTargets) 4416 lock (m_rotTargets)
3567 { 4417 {
4418 if (m_rotTargets.Count >= 8)
4419 m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key);
3568 m_rotTargets.Add(handle, waypoint); 4420 m_rotTargets.Add(handle, waypoint);
3569 } 4421 }
3570 m_scene.AddGroupTarget(this); 4422 m_scene.AddGroupTarget(this);
@@ -3590,6 +4442,8 @@ namespace OpenSim.Region.Framework.Scenes
3590 waypoint.handle = handle; 4442 waypoint.handle = handle;
3591 lock (m_targets) 4443 lock (m_targets)
3592 { 4444 {
4445 if (m_targets.Count >= 8)
4446 m_targets.Remove(m_targets.ElementAt(0).Key);
3593 m_targets.Add(handle, waypoint); 4447 m_targets.Add(handle, waypoint);
3594 } 4448 }
3595 m_scene.AddGroupTarget(this); 4449 m_scene.AddGroupTarget(this);
@@ -3623,10 +4477,11 @@ namespace OpenSim.Region.Framework.Scenes
3623 scriptPosTarget target = m_targets[idx]; 4477 scriptPosTarget target = m_targets[idx];
3624 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 4478 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3625 { 4479 {
4480 at_target = true;
4481
3626 // trigger at_target 4482 // trigger at_target
3627 if (m_scriptListens_atTarget) 4483 if (m_scriptListens_atTarget)
3628 { 4484 {
3629 at_target = true;
3630 scriptPosTarget att = new scriptPosTarget(); 4485 scriptPosTarget att = new scriptPosTarget();
3631 att.targetPos = target.targetPos; 4486 att.targetPos = target.targetPos;
3632 att.tolerance = target.tolerance; 4487 att.tolerance = target.tolerance;
@@ -3744,11 +4599,50 @@ namespace OpenSim.Region.Framework.Scenes
3744 } 4599 }
3745 } 4600 }
3746 } 4601 }
3747 4602
4603 public Vector3 GetGeometricCenter()
4604 {
4605 // this is not real geometric center but a average of positions relative to root prim acording to
4606 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4607 // ignoring tortured prims details since sl also seems to ignore
4608 // so no real use in doing it on physics
4609
4610 Vector3 gc = Vector3.Zero;
4611
4612 int nparts = m_parts.Count;
4613 if (nparts <= 1)
4614 return gc;
4615
4616 SceneObjectPart[] parts = m_parts.GetArray();
4617 nparts = parts.Length; // just in case it changed
4618 if (nparts <= 1)
4619 return gc;
4620
4621 Quaternion parentRot = RootPart.RotationOffset;
4622 Vector3 pPos;
4623
4624 // average all parts positions
4625 for (int i = 0; i < nparts; i++)
4626 {
4627 // do it directly
4628 // gc += parts[i].GetWorldPosition();
4629 if (parts[i] != RootPart)
4630 {
4631 pPos = parts[i].OffsetPosition;
4632 gc += pPos;
4633 }
4634
4635 }
4636 gc /= nparts;
4637
4638 // relative to root:
4639// gc -= AbsolutePosition;
4640 return gc;
4641 }
4642
3748 public float GetMass() 4643 public float GetMass()
3749 { 4644 {
3750 float retmass = 0f; 4645 float retmass = 0f;
3751
3752 SceneObjectPart[] parts = m_parts.GetArray(); 4646 SceneObjectPart[] parts = m_parts.GetArray();
3753 for (int i = 0; i < parts.Length; i++) 4647 for (int i = 0; i < parts.Length; i++)
3754 retmass += parts[i].GetMass(); 4648 retmass += parts[i].GetMass();
@@ -3756,6 +4650,39 @@ namespace OpenSim.Region.Framework.Scenes
3756 return retmass; 4650 return retmass;
3757 } 4651 }
3758 4652
4653 // center of mass of full object
4654 public Vector3 GetCenterOfMass()
4655 {
4656 PhysicsActor pa = RootPart.PhysActor;
4657
4658 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4659 {
4660 // physics knows better about center of mass of physical prims
4661 Vector3 tmp = pa.CenterOfMass;
4662 return tmp;
4663 }
4664
4665 Vector3 Ptot = Vector3.Zero;
4666 float totmass = 0f;
4667 float m;
4668
4669 SceneObjectPart[] parts = m_parts.GetArray();
4670 for (int i = 0; i < parts.Length; i++)
4671 {
4672 m = parts[i].GetMass();
4673 Ptot += parts[i].GetPartCenterOfMass() * m;
4674 totmass += m;
4675 }
4676
4677 if (totmass == 0)
4678 totmass = 0;
4679 else
4680 totmass = 1 / totmass;
4681 Ptot *= totmass;
4682
4683 return Ptot;
4684 }
4685
3759 /// <summary> 4686 /// <summary>
3760 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4687 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3761 /// the physics engine can use it. 4688 /// the physics engine can use it.
@@ -3882,10 +4809,10 @@ namespace OpenSim.Region.Framework.Scenes
3882 /// down after it move one place down the list. 4809 /// down after it move one place down the list.
3883 /// </remarks> 4810 /// </remarks>
3884 /// <returns>A list of the sitting avatars. Returns an empty list if there are no sitting avatars.</returns> 4811 /// <returns>A list of the sitting avatars. Returns an empty list if there are no sitting avatars.</returns>
3885 public List<ScenePresence> GetSittingAvatars() 4812 public List<UUID> GetSittingAvatars()
3886 { 4813 {
3887 lock (m_sittingAvatars) 4814 lock (m_sittingAvatars)
3888 return new List<ScenePresence>(m_sittingAvatars); 4815 return new List<UUID>(m_sittingAvatars);
3889 } 4816 }
3890 4817
3891 /// <summary> 4818 /// <summary>
@@ -3935,6 +4862,14 @@ namespace OpenSim.Region.Framework.Scenes
3935 FromItemID = uuid; 4862 FromItemID = uuid;
3936 } 4863 }
3937 4864
4865 public void ResetOwnerChangeFlag()
4866 {
4867 ForEachPart(delegate(SceneObjectPart part)
4868 {
4869 part.ResetOwnerChangeFlag();
4870 });
4871 }
4872
3938 #endregion 4873 #endregion
3939 } 4874 }
3940} 4875}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 25aa83f..ea96d9e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.Framework.Scenes
64 TELEPORT = 512, 64 TELEPORT = 512,
65 REGION_RESTART = 1024, 65 REGION_RESTART = 1024,
66 MEDIA = 2048, 66 MEDIA = 2048,
67 ANIMATION = 16384 67 ANIMATION = 16384,
68 POSITION = 32768
68 } 69 }
69 70
70 // I don't really know where to put this except here. 71 // I don't really know where to put this except here.
@@ -123,7 +124,18 @@ namespace OpenSim.Region.Framework.Scenes
123 /// Denote all sides of the prim 124 /// Denote all sides of the prim
124 /// </value> 125 /// </value>
125 public const int ALL_SIDES = -1; 126 public const int ALL_SIDES = -1;
126 127
128 private const scriptEvents PhysicsNeededSubsEvents = (
129 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
130 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
131 );
132 private const scriptEvents PhyscicsPhantonSubsEvents = (
133 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
134 );
135 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
136 scriptEvents.collision_start | scriptEvents.collision_end
137 );
138
127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 139 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
128 140
129 /// <summary> 141 /// <summary>
@@ -160,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes
160 /// </remarks> 172 /// </remarks>
161 public bool IsRoot 173 public bool IsRoot
162 { 174 {
163 get { return ParentGroup.RootPart == this; } 175 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
164 } 176 }
165 177
166 /// <summary> 178 /// <summary>
@@ -233,6 +245,15 @@ namespace OpenSim.Region.Framework.Scenes
233 245
234 public uint TimeStampTerse; 246 public uint TimeStampTerse;
235 247
248 // The following two are to hold the attachment data
249 // while an object is inworld
250 [XmlIgnore]
251 public byte AttachPoint = 0;
252
253 [XmlIgnore]
254 public Quaternion AttachRotation = Quaternion.Identity;
255
256 [XmlIgnore]
236 public int STATUS_ROTATE_X; 257 public int STATUS_ROTATE_X;
237 258
238 public int STATUS_ROTATE_Y; 259 public int STATUS_ROTATE_Y;
@@ -259,8 +280,7 @@ namespace OpenSim.Region.Framework.Scenes
259 280
260 public Vector3 RotationAxis = Vector3.One; 281 public Vector3 RotationAxis = Vector3.One;
261 282
262 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 283 public bool VolumeDetectActive;
263 // Certainly this must be a persistant setting finally
264 284
265 public bool IsWaitingForFirstSpinUpdatePacket; 285 public bool IsWaitingForFirstSpinUpdatePacket;
266 286
@@ -300,10 +320,10 @@ namespace OpenSim.Region.Framework.Scenes
300 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 320 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
301 private Vector3 m_sitTargetPosition; 321 private Vector3 m_sitTargetPosition;
302 private string m_sitAnimation = "SIT"; 322 private string m_sitAnimation = "SIT";
323 private bool m_occupied; // KF if any av is sitting on this prim
303 private string m_text = String.Empty; 324 private string m_text = String.Empty;
304 private string m_touchName = String.Empty; 325 private string m_touchName = String.Empty;
305 private readonly List<UndoState> m_undo = new List<UndoState>(5); 326 private UndoRedoState m_UndoRedo = null;
306 private readonly List<UndoState> m_redo = new List<UndoState>(5);
307 327
308 private bool m_passTouches = false; 328 private bool m_passTouches = false;
309 private bool m_passCollisions = false; 329 private bool m_passCollisions = false;
@@ -331,14 +351,20 @@ namespace OpenSim.Region.Framework.Scenes
331 protected Vector3 m_lastVelocity; 351 protected Vector3 m_lastVelocity;
332 protected Vector3 m_lastAcceleration; 352 protected Vector3 m_lastAcceleration;
333 protected Vector3 m_lastAngularVelocity; 353 protected Vector3 m_lastAngularVelocity;
334 protected int m_lastTerseSent; 354 protected int m_lastUpdateSentTime;
355 protected float m_buoyancy = 0.0f;
356 protected Vector3 m_force;
357 protected Vector3 m_torque;
335 358
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 359 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3 360 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f; 361 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood 362 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood 363 protected float m_bounce = 0.5f; // wood
341 364
365
366 protected bool m_isSelected = false;
367
342 /// <summary> 368 /// <summary>
343 /// Stores media texture data 369 /// Stores media texture data
344 /// </summary> 370 /// </summary>
@@ -350,15 +376,23 @@ namespace OpenSim.Region.Framework.Scenes
350 private Vector3 m_cameraAtOffset; 376 private Vector3 m_cameraAtOffset;
351 private bool m_forceMouselook; 377 private bool m_forceMouselook;
352 378
353 // TODO: Collision sound should have default. 379
380 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
381 private sbyte m_collisionSoundType;
354 private UUID m_collisionSound; 382 private UUID m_collisionSound;
355 private float m_collisionSoundVolume; 383 private float m_collisionSoundVolume;
356 384
385 private int LastColSoundSentTime;
386
387
388 private SOPVehicle m_vehicleParams = null;
389
357 public KeyframeMotion KeyframeMotion 390 public KeyframeMotion KeyframeMotion
358 { 391 {
359 get; set; 392 get; set;
360 } 393 }
361 394
395
362 #endregion Fields 396 #endregion Fields
363 397
364// ~SceneObjectPart() 398// ~SceneObjectPart()
@@ -388,6 +422,7 @@ namespace OpenSim.Region.Framework.Scenes
388 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 422 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
389 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 423 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
390 m_inventory = new SceneObjectPartInventory(this); 424 m_inventory = new SceneObjectPartInventory(this);
425 LastColSoundSentTime = Util.EnvironmentTickCount();
391 } 426 }
392 427
393 /// <summary> 428 /// <summary>
@@ -402,7 +437,7 @@ namespace OpenSim.Region.Framework.Scenes
402 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 437 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
403 Quaternion rotationOffset, Vector3 offsetPosition) : this() 438 Quaternion rotationOffset, Vector3 offsetPosition) : this()
404 { 439 {
405 m_name = "Primitive"; 440 m_name = "Object";
406 441
407 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 442 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
408 LastOwnerID = CreatorID = OwnerID = ownerID; 443 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -441,7 +476,7 @@ namespace OpenSim.Region.Framework.Scenes
441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export); 476 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
442 private uint _groupMask = (uint)PermissionMask.None; 477 private uint _groupMask = (uint)PermissionMask.None;
443 private uint _everyoneMask = (uint)PermissionMask.None; 478 private uint _everyoneMask = (uint)PermissionMask.None;
444 private uint _nextOwnerMask = (uint)PermissionMask.All; 479 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
445 private PrimFlags _flags = PrimFlags.None; 480 private PrimFlags _flags = PrimFlags.None;
446 private DateTime m_expires; 481 private DateTime m_expires;
447 private DateTime m_rezzed; 482 private DateTime m_rezzed;
@@ -539,12 +574,16 @@ namespace OpenSim.Region.Framework.Scenes
539 } 574 }
540 575
541 /// <value> 576 /// <value>
542 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 577 /// Get the inventory list
543 /// </value> 578 /// </value>
544 public TaskInventoryDictionary TaskInventory 579 public TaskInventoryDictionary TaskInventory
545 { 580 {
546 get { return m_inventory.Items; } 581 get {
547 set { m_inventory.Items = value; } 582 return m_inventory.Items;
583 }
584 set {
585 m_inventory.Items = value;
586 }
548 } 587 }
549 588
550 /// <summary> 589 /// <summary>
@@ -594,20 +633,6 @@ namespace OpenSim.Region.Framework.Scenes
594 } 633 }
595 } 634 }
596 635
597 public byte Material
598 {
599 get { return (byte) m_material; }
600 set
601 {
602 m_material = (Material)value;
603
604 PhysicsActor pa = PhysActor;
605
606 if (pa != null)
607 pa.SetMaterial((int)value);
608 }
609 }
610
611 [XmlIgnore] 636 [XmlIgnore]
612 public bool PassTouches 637 public bool PassTouches
613 { 638 {
@@ -633,6 +658,19 @@ namespace OpenSim.Region.Framework.Scenes
633 } 658 }
634 } 659 }
635 660
661 public bool IsSelected
662 {
663 get { return m_isSelected; }
664 set
665 {
666 m_isSelected = value;
667 if (ParentGroup != null)
668 ParentGroup.PartSelectChanged(value);
669
670 }
671 }
672
673
636 public Dictionary<int, string> CollisionFilter 674 public Dictionary<int, string> CollisionFilter
637 { 675 {
638 get { return m_CollisionFilter; } 676 get { return m_CollisionFilter; }
@@ -707,14 +745,12 @@ namespace OpenSim.Region.Framework.Scenes
707 set { m_LoopSoundSlavePrims = value; } 745 set { m_LoopSoundSlavePrims = value; }
708 } 746 }
709 747
710
711 public Byte[] TextureAnimation 748 public Byte[] TextureAnimation
712 { 749 {
713 get { return m_TextureAnimation; } 750 get { return m_TextureAnimation; }
714 set { m_TextureAnimation = value; } 751 set { m_TextureAnimation = value; }
715 } 752 }
716 753
717
718 public Byte[] ParticleSystem 754 public Byte[] ParticleSystem
719 { 755 {
720 get { return m_particleSystem; } 756 get { return m_particleSystem; }
@@ -742,18 +778,32 @@ namespace OpenSim.Region.Framework.Scenes
742 set { m_damage = value; } 778 set { m_damage = value; }
743 } 779 }
744 780
781
782
783
784 public void setGroupPosition(Vector3 pos)
785 {
786 m_groupPosition = pos;
787 }
788
745 /// <summary> 789 /// <summary>
746 /// The position of the entire group that this prim belongs to. 790 /// The position of the entire group that this prim belongs to.
747 /// </summary> 791 /// </summary>
792 ///
793
794
748 public Vector3 GroupPosition 795 public Vector3 GroupPosition
749 { 796 {
750 get 797 get
751 { 798 {
752 // If this is a linkset, we don't want the physics engine mucking up our group position here. 799 // If this is a linkset, we don't want the physics engine mucking up our group position here.
753 PhysicsActor actor = PhysActor; 800 PhysicsActor actor = PhysActor;
754 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 801 if (ParentID == 0)
755 if (actor != null && ParentID == 0) 802 {
756 m_groupPosition = actor.Position; 803 if (actor != null)
804 m_groupPosition = actor.Position;
805 return m_groupPosition;
806 }
757 807
758 // If I'm an attachment, my position is reported as the position of who I'm attached to 808 // If I'm an attachment, my position is reported as the position of who I'm attached to
759 if (ParentGroup.IsAttachment) 809 if (ParentGroup.IsAttachment)
@@ -763,21 +813,23 @@ namespace OpenSim.Region.Framework.Scenes
763 return sp.AbsolutePosition; 813 return sp.AbsolutePosition;
764 } 814 }
765 815
816 // use root prim's group position. Physics may have updated it
817 if (ParentGroup.RootPart != this)
818 m_groupPosition = ParentGroup.RootPart.GroupPosition;
766 return m_groupPosition; 819 return m_groupPosition;
767 } 820 }
768 set 821 set
769 { 822 {
770 m_groupPosition = value; 823 m_groupPosition = value;
771
772 PhysicsActor actor = PhysActor; 824 PhysicsActor actor = PhysActor;
773 if (actor != null) 825 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
774 { 826 {
775 try 827 try
776 { 828 {
777 // Root prim actually goes at Position 829 // Root prim actually goes at Position
778 if (ParentID == 0) 830 if (ParentID == 0)
779 { 831 {
780 actor.Position = value; 832 actor.Position = value;
781 } 833 }
782 else 834 else
783 { 835 {
@@ -798,12 +850,17 @@ namespace OpenSim.Region.Framework.Scenes
798 } 850 }
799 } 851 }
800 852
853 public void setOffsetPosition(Vector3 pos)
854 {
855 m_offsetPosition = pos;
856 }
857
801 public Vector3 OffsetPosition 858 public Vector3 OffsetPosition
802 { 859 {
803 get { return m_offsetPosition; } 860 get { return m_offsetPosition; }
804 set 861 set
805 { 862 {
806// StoreUndoState(); 863 Vector3 oldpos = m_offsetPosition;
807 m_offsetPosition = value; 864 m_offsetPosition = value;
808 865
809 if (ParentGroup != null && !ParentGroup.IsDeleted) 866 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -815,10 +872,26 @@ namespace OpenSim.Region.Framework.Scenes
815 actor.Orientation = GetWorldRotation(); 872 actor.Orientation = GetWorldRotation();
816 873
817 // Tell the physics engines that this prim changed. 874 // Tell the physics engines that this prim changed.
818 if (ParentGroup.Scene != null) 875 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 876 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
820 } 877 }
878
879 if (!m_parentGroup.m_dupeInProgress)
880 {
881 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
882 foreach (ScenePresence av in avs)
883 {
884 if (av.ParentID == m_localId)
885 {
886 Vector3 offset = (m_offsetPosition - oldpos);
887 av.AbsolutePosition += offset;
888// av.SendAvatarDataToAllAgents();
889 av.SendTerseUpdateToAllClients();
890 }
891 }
892 }
821 } 893 }
894 TriggerScriptChangedEvent(Changed.POSITION);
822 } 895 }
823 } 896 }
824 897
@@ -840,6 +913,11 @@ namespace OpenSim.Region.Framework.Scenes
840 } 913 }
841 } 914 }
842 915
916 public void setRotationOffset(Quaternion q)
917 {
918 m_rotationOffset = q;
919 }
920
843 public Quaternion RotationOffset 921 public Quaternion RotationOffset
844 { 922 {
845 get 923 get
@@ -869,7 +947,7 @@ namespace OpenSim.Region.Framework.Scenes
869 947
870 set 948 set
871 { 949 {
872 StoreUndoState(); 950// StoreUndoState();
873 m_rotationOffset = value; 951 m_rotationOffset = value;
874 952
875 PhysicsActor actor = PhysActor; 953 PhysicsActor actor = PhysActor;
@@ -960,7 +1038,7 @@ namespace OpenSim.Region.Framework.Scenes
960 get 1038 get
961 { 1039 {
962 PhysicsActor actor = PhysActor; 1040 PhysicsActor actor = PhysActor;
963 if ((actor != null) && actor.IsPhysical) 1041 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
964 { 1042 {
965 m_angularVelocity = actor.RotationalVelocity; 1043 m_angularVelocity = actor.RotationalVelocity;
966 } 1044 }
@@ -974,15 +1052,26 @@ namespace OpenSim.Region.Framework.Scenes
974 m_angularVelocity = value; 1052 m_angularVelocity = value;
975 1053
976 PhysicsActor actor = PhysActor; 1054 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical) 1055 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE)
1056 {
978 actor.RotationalVelocity = m_angularVelocity; 1057 actor.RotationalVelocity = m_angularVelocity;
1058 }
979 } 1059 }
980 } 1060 }
981 1061
982 /// <summary></summary> 1062 /// <summary></summary>
983 public Vector3 Acceleration 1063 public Vector3 Acceleration
984 { 1064 {
985 get { return m_acceleration; } 1065 get
1066 {
1067 PhysicsActor actor = PhysActor;
1068 if (actor != null)
1069 {
1070 m_acceleration = actor.Acceleration;
1071 }
1072 return m_acceleration;
1073 }
1074
986 set 1075 set
987 { 1076 {
988 if (Util.IsNanOrInfinity(value)) 1077 if (Util.IsNanOrInfinity(value))
@@ -1056,7 +1145,10 @@ namespace OpenSim.Region.Framework.Scenes
1056 public PrimitiveBaseShape Shape 1145 public PrimitiveBaseShape Shape
1057 { 1146 {
1058 get { return m_shape; } 1147 get { return m_shape; }
1059 set { m_shape = value;} 1148 set
1149 {
1150 m_shape = value;
1151 }
1060 } 1152 }
1061 1153
1062 /// <summary> 1154 /// <summary>
@@ -1069,7 +1161,6 @@ namespace OpenSim.Region.Framework.Scenes
1069 { 1161 {
1070 if (m_shape != null) 1162 if (m_shape != null)
1071 { 1163 {
1072 StoreUndoState();
1073 1164
1074 m_shape.Scale = value; 1165 m_shape.Scale = value;
1075 1166
@@ -1137,10 +1228,7 @@ namespace OpenSim.Region.Framework.Scenes
1137 { 1228 {
1138 get 1229 get
1139 { 1230 {
1140 if (ParentGroup.IsAttachment) 1231 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1141 return GroupPosition;
1142
1143 return m_offsetPosition + m_groupPosition;
1144 } 1232 }
1145 } 1233 }
1146 1234
@@ -1309,6 +1397,13 @@ namespace OpenSim.Region.Framework.Scenes
1309 _flags = value; 1397 _flags = value;
1310 } 1398 }
1311 } 1399 }
1400
1401 [XmlIgnore]
1402 public bool IsOccupied // KF If an av is sittingon this prim
1403 {
1404 get { return m_occupied; }
1405 set { m_occupied = value; }
1406 }
1312 1407
1313 /// <summary> 1408 /// <summary>
1314 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero 1409 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
@@ -1324,7 +1419,7 @@ namespace OpenSim.Region.Framework.Scenes
1324 /// <value> 1419 /// <value>
1325 /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene. 1420 /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
1326 /// </value> 1421 /// </value>
1327 private HashSet<ScenePresence> m_sittingAvatars; 1422 private HashSet<UUID> m_sittingAvatars;
1328 1423
1329 public virtual UUID RegionID 1424 public virtual UUID RegionID
1330 { 1425 {
@@ -1359,12 +1454,41 @@ namespace OpenSim.Region.Framework.Scenes
1359 set { m_sitAnimation = value; } 1454 set { m_sitAnimation = value; }
1360 } 1455 }
1361 1456
1457 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1458
1459 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1460 // runtime thing.. do not persist
1461 [XmlIgnore]
1462 public sbyte CollisionSoundType
1463 {
1464 get
1465 {
1466 return m_collisionSoundType;
1467 }
1468 set
1469 {
1470 m_collisionSoundType = value;
1471 if (value == -1)
1472 m_collisionSound = invalidCollisionSoundUUID;
1473 else if (value == 0)
1474 m_collisionSound = UUID.Zero;
1475 }
1476 }
1477
1362 public UUID CollisionSound 1478 public UUID CollisionSound
1363 { 1479 {
1364 get { return m_collisionSound; } 1480 get { return m_collisionSound; }
1365 set 1481 set
1366 { 1482 {
1367 m_collisionSound = value; 1483 m_collisionSound = value;
1484
1485 if (value == invalidCollisionSoundUUID)
1486 m_collisionSoundType = -1;
1487 else if (value == UUID.Zero)
1488 m_collisionSoundType = 0;
1489 else
1490 m_collisionSoundType = 1;
1491
1368 aggregateScriptEvents(); 1492 aggregateScriptEvents();
1369 } 1493 }
1370 } 1494 }
@@ -1375,6 +1499,125 @@ namespace OpenSim.Region.Framework.Scenes
1375 set { m_collisionSoundVolume = value; } 1499 set { m_collisionSoundVolume = value; }
1376 } 1500 }
1377 1501
1502 public float Buoyancy
1503 {
1504 get
1505 {
1506 if (ParentGroup.RootPart == this)
1507 return m_buoyancy;
1508
1509 return ParentGroup.RootPart.Buoyancy;
1510 }
1511 set
1512 {
1513 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1514 {
1515 ParentGroup.RootPart.Buoyancy = value;
1516 return;
1517 }
1518 m_buoyancy = value;
1519 if (PhysActor != null)
1520 PhysActor.Buoyancy = value;
1521 }
1522 }
1523
1524 public Vector3 Force
1525 {
1526 get
1527 {
1528 if (ParentGroup.RootPart == this)
1529 return m_force;
1530
1531 return ParentGroup.RootPart.Force;
1532 }
1533
1534 set
1535 {
1536 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1537 {
1538 ParentGroup.RootPart.Force = value;
1539 return;
1540 }
1541 m_force = value;
1542 if (PhysActor != null)
1543 PhysActor.Force = value;
1544 }
1545 }
1546
1547 public Vector3 Torque
1548 {
1549 get
1550 {
1551 if (ParentGroup.RootPart == this)
1552 return m_torque;
1553
1554 return ParentGroup.RootPart.Torque;
1555 }
1556
1557 set
1558 {
1559 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1560 {
1561 ParentGroup.RootPart.Torque = value;
1562 return;
1563 }
1564 m_torque = value;
1565 if (PhysActor != null)
1566 PhysActor.Torque = value;
1567 }
1568 }
1569
1570 public byte Material
1571 {
1572 get { return (byte)m_material; }
1573 set
1574 {
1575 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1576 {
1577 bool update = false;
1578
1579 if (m_material != (Material)value)
1580 {
1581 update = true;
1582 m_material = (Material)value;
1583 }
1584
1585 if (m_friction != SOPMaterialData.friction(m_material))
1586 {
1587 update = true;
1588 m_friction = SOPMaterialData.friction(m_material);
1589 }
1590
1591 if (m_bounce != SOPMaterialData.bounce(m_material))
1592 {
1593 update = true;
1594 m_bounce = SOPMaterialData.bounce(m_material);
1595 }
1596
1597 if (update)
1598 {
1599 if (PhysActor != null)
1600 {
1601 PhysActor.SetMaterial((int)value);
1602 }
1603 if(ParentGroup != null)
1604 ParentGroup.HasGroupChanged = true;
1605 ScheduleFullUpdateIfNone();
1606 UpdatePhysRequired = true;
1607 }
1608 }
1609 }
1610 }
1611
1612 // not a propriety to move to methods place later
1613 private bool HasMesh()
1614 {
1615 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1616 return true;
1617 return false;
1618 }
1619
1620 // not a propriety to move to methods place later
1378 public byte DefaultPhysicsShapeType() 1621 public byte DefaultPhysicsShapeType()
1379 { 1622 {
1380 byte type; 1623 byte type;
@@ -1387,6 +1630,65 @@ namespace OpenSim.Region.Framework.Scenes
1387 return type; 1630 return type;
1388 } 1631 }
1389 1632
1633 [XmlIgnore]
1634 public bool UsesComplexCost
1635 {
1636 get
1637 {
1638 byte pst = PhysicsShapeType;
1639 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1640 return true;
1641 return false;
1642 }
1643 }
1644
1645 [XmlIgnore]
1646 public float PhysicsCost
1647 {
1648 get
1649 {
1650 if(PhysicsShapeType == (byte)PhysShapeType.none)
1651 return 0;
1652
1653 float cost = 0.1f;
1654 if (PhysActor != null)
1655 cost = PhysActor.PhysicsCost;
1656 else
1657 cost = 0.1f;
1658
1659 if ((Flags & PrimFlags.Physics) != 0)
1660 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1661 return cost;
1662 }
1663 }
1664
1665 [XmlIgnore]
1666 public float StreamingCost
1667 {
1668 get
1669 {
1670 float cost;
1671 if (PhysActor != null)
1672 cost = PhysActor.StreamCost;
1673 else
1674 cost = 1.0f;
1675 return 1.0f;
1676 }
1677 }
1678
1679 [XmlIgnore]
1680 public float SimulationCost
1681 {
1682 get
1683 {
1684 // ignoring scripts. Don't like considering them for this
1685 if((Flags & PrimFlags.Physics) != 0)
1686 return 1.0f;
1687
1688 return 0.5f;
1689 }
1690 }
1691
1390 public byte PhysicsShapeType 1692 public byte PhysicsShapeType
1391 { 1693 {
1392 get { return m_physicsShapeType; } 1694 get { return m_physicsShapeType; }
@@ -1420,11 +1722,14 @@ namespace OpenSim.Region.Framework.Scenes
1420 } 1722 }
1421 else if (PhysActor == null) 1723 else if (PhysActor == null)
1422 { 1724 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive); 1725 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1726 UpdatePhysicsSubscribedEvents();
1424 } 1727 }
1425 else 1728 else
1426 { 1729 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType; 1730 PhysActor.PhysicsShapeType = m_physicsShapeType;
1731// if (Shape.SculptEntry)
1732// CheckSculptAndLoad();
1428 } 1733 }
1429 1734
1430 if (ParentGroup != null) 1735 if (ParentGroup != null)
@@ -1526,6 +1831,7 @@ namespace OpenSim.Region.Framework.Scenes
1526 } 1831 }
1527 } 1832 }
1528 1833
1834
1529 #endregion Public Properties with only Get 1835 #endregion Public Properties with only Get
1530 1836
1531 private uint ApplyMask(uint val, bool set, uint mask) 1837 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1636,8 +1942,8 @@ namespace OpenSim.Region.Framework.Scenes
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1942 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1943 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1944 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1945
1639 } 1946 }
1640
1641 m_TextureAnimation = data; 1947 m_TextureAnimation = data;
1642 } 1948 }
1643 1949
@@ -1680,6 +1986,61 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 1986 }
1681 } 1987 }
1682 1988
1989 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1990 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1991 {
1992 if (ParentGroup == null || ParentGroup.IsDeleted)
1993 return;
1994
1995 if (ParentGroup.IsAttachment)
1996 return; // don't work on attachments (for now ??)
1997
1998 SceneObjectPart root = ParentGroup.RootPart;
1999
2000 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2001 return;
2002
2003 PhysicsActor pa = root.PhysActor;
2004
2005 if (pa == null || !pa.IsPhysical)
2006 return;
2007
2008 if (localGlobalTF)
2009 {
2010 pVel = pVel * GetWorldRotation();
2011 }
2012
2013 ParentGroup.Velocity = pVel;
2014 }
2015
2016 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
2017 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
2018 {
2019 if (ParentGroup == null || ParentGroup.IsDeleted)
2020 return;
2021
2022 if (ParentGroup.IsAttachment)
2023 return; // don't work on attachments (for now ??)
2024
2025 SceneObjectPart root = ParentGroup.RootPart;
2026
2027 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2028 return;
2029
2030 PhysicsActor pa = root.PhysActor;
2031
2032 if (pa == null || !pa.IsPhysical)
2033 return;
2034
2035 if (localGlobalTF)
2036 {
2037 pAngVel = pAngVel * GetWorldRotation();
2038 }
2039
2040 root.AngularVelocity = pAngVel;
2041 }
2042
2043
1683 /// <summary> 2044 /// <summary>
1684 /// hook to the physics scene to apply angular impulse 2045 /// hook to the physics scene to apply angular impulse
1685 /// This is sent up to the group, which then finds the root prim 2046 /// This is sent up to the group, which then finds the root prim
@@ -1700,7 +2061,7 @@ namespace OpenSim.Region.Framework.Scenes
1700 impulse = newimpulse; 2061 impulse = newimpulse;
1701 } 2062 }
1702 2063
1703 ParentGroup.applyAngularImpulse(impulse); 2064 ParentGroup.ApplyAngularImpulse(impulse);
1704 } 2065 }
1705 2066
1706 /// <summary> 2067 /// <summary>
@@ -1710,20 +2071,24 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// </summary> 2071 /// </summary>
1711 /// <param name="impulsei">Vector force</param> 2072 /// <param name="impulsei">Vector force</param>
1712 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2073 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1713 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2074
2075 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
2076 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1714 { 2077 {
1715 Vector3 impulse = impulsei; 2078 Vector3 torque = torquei;
1716 2079
1717 if (localGlobalTF) 2080 if (localGlobalTF)
1718 { 2081 {
2082/*
1719 Quaternion grot = GetWorldRotation(); 2083 Quaternion grot = GetWorldRotation();
1720 Quaternion AXgrot = grot; 2084 Quaternion AXgrot = grot;
1721 Vector3 AXimpulsei = impulsei; 2085 Vector3 AXimpulsei = impulsei;
1722 Vector3 newimpulse = AXimpulsei * AXgrot; 2086 Vector3 newimpulse = AXimpulsei * AXgrot;
1723 impulse = newimpulse; 2087 */
2088 torque *= GetWorldRotation();
1724 } 2089 }
1725 2090
1726 ParentGroup.setAngularImpulse(impulse); 2091 Torque = torque;
1727 } 2092 }
1728 2093
1729 /// <summary> 2094 /// <summary>
@@ -1731,7 +2096,9 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// </summary> 2096 /// </summary>
1732 /// <param name="rootObjectFlags"></param> 2097 /// <param name="rootObjectFlags"></param>
1733 /// <param name="VolumeDetectActive"></param> 2098 /// <param name="VolumeDetectActive"></param>
1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive) 2099 /// <param name="building"></param>
2100
2101 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1735 { 2102 {
1736 VolumeDetectActive = _VolumeDetectActive; 2103 VolumeDetectActive = _VolumeDetectActive;
1737 2104
@@ -1741,8 +2108,8 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (PhysicsShapeType == (byte)PhysShapeType.none) 2108 if (PhysicsShapeType == (byte)PhysShapeType.none)
1742 return; 2109 return;
1743 2110
1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2111 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2112 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1746 2113
1747 if (_VolumeDetectActive) 2114 if (_VolumeDetectActive)
1748 isPhantom = true; 2115 isPhantom = true;
@@ -1756,7 +2123,8 @@ namespace OpenSim.Region.Framework.Scenes
1756 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment 2123 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1757 && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 2124 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1758 { 2125 {
1759 AddToPhysics(isPhysical, isPhantom, isPhysical); 2126 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
2127 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1760 } 2128 }
1761 else 2129 else
1762 PhysActor = null; // just to be sure 2130 PhysActor = null; // just to be sure
@@ -1785,7 +2153,7 @@ namespace OpenSim.Region.Framework.Scenes
1785 /// <param name="linkNum"></param> 2153 /// <param name="linkNum"></param>
1786 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2154 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1787 /// <returns></returns> 2155 /// <returns></returns>
1788 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2156 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1789 { 2157 {
1790 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2158 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1791 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator 2159 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
@@ -1815,6 +2183,12 @@ namespace OpenSim.Region.Framework.Scenes
1815 dupe.Category = Category; 2183 dupe.Category = Category;
1816 dupe.m_rezzed = m_rezzed; 2184 dupe.m_rezzed = m_rezzed;
1817 2185
2186 dupe.m_UndoRedo = null;
2187 dupe.m_isSelected = false;
2188
2189 dupe.IgnoreUndoUpdate = false;
2190 dupe.Undoing = false;
2191
1818 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2192 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1819 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2193 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1820 2194
@@ -1829,7 +2203,8 @@ namespace OpenSim.Region.Framework.Scenes
1829 } 2203 }
1830 2204
1831 // Move afterwards ResetIDs as it clears the localID 2205 // Move afterwards ResetIDs as it clears the localID
1832 dupe.LocalId = localID; 2206 dupe.LocalId = plocalID;
2207
1833 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2208 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1834 dupe.LastOwnerID = OwnerID; 2209 dupe.LastOwnerID = OwnerID;
1835 2210
@@ -1837,7 +2212,7 @@ namespace OpenSim.Region.Framework.Scenes
1837 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2212 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1838 dupe.Shape.ExtraParams = extraP; 2213 dupe.Shape.ExtraParams = extraP;
1839 2214
1840 dupe.m_sittingAvatars = new HashSet<ScenePresence>(); 2215 dupe.m_sittingAvatars = new HashSet<UUID>();
1841 2216
1842 // safeguard actual copy is done in sog.copy 2217 // safeguard actual copy is done in sog.copy
1843 dupe.KeyframeMotion = null; 2218 dupe.KeyframeMotion = null;
@@ -1856,8 +2231,12 @@ namespace OpenSim.Region.Framework.Scenes
1856*/ 2231*/
1857 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2232 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1858 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2233 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2234// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1859 } 2235 }
1860 2236
2237 if (dupe.PhysActor != null)
2238 dupe.PhysActor.LocalID = plocalID;
2239
1861 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2240 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1862 2241
1863// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2242// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1876,10 +2255,10 @@ namespace OpenSim.Region.Framework.Scenes
1876 { 2255 {
1877 if (asset != null) 2256 if (asset != null)
1878 SculptTextureCallback(asset); 2257 SculptTextureCallback(asset);
1879 else 2258// else
1880 m_log.WarnFormat( 2259// m_log.WarnFormat(
1881 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2260// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1882 Name, UUID, id); 2261// Name, UUID, id);
1883 } 2262 }
1884*/ 2263*/
1885 /// <summary> 2264 /// <summary>
@@ -1978,6 +2357,7 @@ namespace OpenSim.Region.Framework.Scenes
1978 2357
1979 /// <summary> 2358 /// <summary>
1980 /// Do a physics propery update for this part. 2359 /// Do a physics propery update for this part.
2360 /// now also updates phantom and volume detector
1981 /// </summary> 2361 /// </summary>
1982 /// <param name="UsePhysics"></param> 2362 /// <param name="UsePhysics"></param>
1983 /// <param name="isNew"></param> 2363 /// <param name="isNew"></param>
@@ -2003,64 +2383,69 @@ namespace OpenSim.Region.Framework.Scenes
2003 { 2383 {
2004 if (pa.IsPhysical) // implies UsePhysics==false for this block 2384 if (pa.IsPhysical) // implies UsePhysics==false for this block
2005 { 2385 {
2006 if (!isNew) 2386 if (!isNew) // implies UsePhysics==false for this block
2387 {
2007 ParentGroup.Scene.RemovePhysicalPrim(1); 2388 ParentGroup.Scene.RemovePhysicalPrim(1);
2008 2389
2009 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2390 Velocity = new Vector3(0, 0, 0);
2010 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2391 Acceleration = new Vector3(0, 0, 0);
2011 pa.delink(); 2392 if (ParentGroup.RootPart == this)
2393 AngularVelocity = new Vector3(0, 0, 0);
2012 2394
2013 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2395 if (pa.Phantom && !VolumeDetectActive)
2014 { 2396 {
2015 // destroy all joints connected to this now deactivated body 2397 RemoveFromPhysics();
2016 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2398 return;
2017 } 2399 }
2018 2400
2019 // stop client-side interpolation of all joint proxy objects that have just been deleted 2401 pa.IsPhysical = UsePhysics;
2020 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2402 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
2021 // which stops client-side interpolation of deactivated joint proxy objects. 2403 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2404 pa.delink();
2405 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2406 {
2407 // destroy all joints connected to this now deactivated body
2408 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2409 }
2410 }
2022 } 2411 }
2023 2412
2024 if (!UsePhysics && !isNew) 2413 if (pa.IsPhysical != UsePhysics)
2025 { 2414 pa.IsPhysical = UsePhysics;
2026 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
2027 // prim still has velocity and continues to interpolate its position along the old
2028 // velocity-vector.
2029 Velocity = new Vector3(0, 0, 0);
2030 Acceleration = new Vector3(0, 0, 0);
2031 AngularVelocity = new Vector3(0, 0, 0);
2032 //RotationalVelocity = new Vector3(0, 0, 0);
2033 }
2034 2415
2035 pa.IsPhysical = UsePhysics; 2416 if (UsePhysics)
2417 {
2418 if (ParentGroup.RootPart.KeyframeMotion != null)
2419 ParentGroup.RootPart.KeyframeMotion.Stop();
2420 ParentGroup.RootPart.KeyframeMotion = null;
2421 ParentGroup.Scene.AddPhysicalPrim(1);
2036 2422
2037 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2423 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2038 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2424 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
2039 /// that's not wholesome. Had to make Scene public
2040 //PhysActor = null;
2041 2425
2042 if ((Flags & PrimFlags.Phantom) == 0) 2426 if (ParentID != 0 && ParentID != LocalId)
2043 {
2044 if (UsePhysics)
2045 { 2427 {
2046 if (ParentGroup.RootPart.KeyframeMotion != null) 2428 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2047 ParentGroup.RootPart.KeyframeMotion.Stop();
2048 ParentGroup.RootPart.KeyframeMotion = null;
2049 ParentGroup.Scene.AddPhysicalPrim(1);
2050
2051 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2052 pa.OnOutOfBounds += PhysicsOutOfBounds;
2053 if (ParentID != 0 && ParentID != LocalId)
2054 {
2055 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2056 2429
2057 if (parentPa != null) 2430 if (parentPa != null)
2058 { 2431 {
2059 pa.link(parentPa); 2432 pa.link(parentPa);
2060 }
2061 } 2433 }
2062 } 2434 }
2063 } 2435 }
2436 }
2437
2438 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2439 if (pa.Phantom != phan)
2440 pa.Phantom = phan;
2441
2442// some engines dont' have this check still
2443// if (VolumeDetectActive != pa.IsVolumeDtc)
2444 {
2445 if (VolumeDetectActive)
2446 pa.SetVolumeDetect(1);
2447 else
2448 pa.SetVolumeDetect(0);
2064 } 2449 }
2065 2450
2066 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2451 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -2163,42 +2548,63 @@ namespace OpenSim.Region.Framework.Scenes
2163 2548
2164 public Vector3 GetGeometricCenter() 2549 public Vector3 GetGeometricCenter()
2165 { 2550 {
2551 // this is not real geometric center but a average of positions relative to root prim acording to
2552 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2553 // ignoring tortured prims details since sl also seems to ignore
2554 // so no real use in doing it on physics
2555 if (ParentGroup.IsDeleted)
2556 return new Vector3(0, 0, 0);
2557
2558 return ParentGroup.GetGeometricCenter();
2559 }
2560
2561 public float GetMass()
2562 {
2166 PhysicsActor pa = PhysActor; 2563 PhysicsActor pa = PhysActor;
2167 2564
2168 if (pa != null) 2565 if (pa != null)
2169 return pa.GeometricCenter; 2566 return pa.Mass;
2170 else 2567 else
2171 return Vector3.Zero; 2568 return 0;
2172 } 2569 }
2173 2570
2174 public Vector3 GetCenterOfMass() 2571 public Vector3 GetCenterOfMass()
2175 { 2572 {
2573 if (ParentGroup.RootPart == this)
2574 {
2575 if (ParentGroup.IsDeleted)
2576 return AbsolutePosition;
2577 return ParentGroup.GetCenterOfMass();
2578 }
2579
2176 PhysicsActor pa = PhysActor; 2580 PhysicsActor pa = PhysActor;
2177 2581
2178 if (pa != null) 2582 if (pa != null)
2179 return pa.CenterOfMass; 2583 {
2584 Vector3 tmp = pa.CenterOfMass;
2585 return tmp;
2586 }
2180 else 2587 else
2181 return Vector3.Zero; 2588 return AbsolutePosition;
2182 } 2589 }
2183 2590
2184 public float GetMass() 2591 public Vector3 GetPartCenterOfMass()
2185 { 2592 {
2186 PhysicsActor pa = PhysActor; 2593 PhysicsActor pa = PhysActor;
2187 2594
2188 if (pa != null) 2595 if (pa != null)
2189 return pa.Mass; 2596 {
2597 Vector3 tmp = pa.CenterOfMass;
2598 return tmp;
2599 }
2190 else 2600 else
2191 return 0; 2601 return AbsolutePosition;
2192 } 2602 }
2193 2603
2604
2194 public Vector3 GetForce() 2605 public Vector3 GetForce()
2195 { 2606 {
2196 PhysicsActor pa = PhysActor; 2607 return Force;
2197
2198 if (pa != null)
2199 return pa.Force;
2200 else
2201 return Vector3.Zero;
2202 } 2608 }
2203 2609
2204 /// <summary> 2610 /// <summary>
@@ -2313,6 +2719,7 @@ namespace OpenSim.Region.Framework.Scenes
2313 detobj.velVector = obj.Velocity; 2719 detobj.velVector = obj.Velocity;
2314 detobj.colliderType = 0; 2720 detobj.colliderType = 0;
2315 detobj.groupUUID = obj.GroupID; 2721 detobj.groupUUID = obj.GroupID;
2722 detobj.linkNumber = LinkNum; // pass my link number
2316 2723
2317 return detobj; 2724 return detobj;
2318 } 2725 }
@@ -2328,6 +2735,7 @@ namespace OpenSim.Region.Framework.Scenes
2328 detobj.velVector = av.Velocity; 2735 detobj.velVector = av.Velocity;
2329 detobj.colliderType = 0; 2736 detobj.colliderType = 0;
2330 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2737 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2738 detobj.linkNumber = LinkNum; // pass my link number
2331 2739
2332 return detobj; 2740 return detobj;
2333 } 2741 }
@@ -2343,6 +2751,7 @@ namespace OpenSim.Region.Framework.Scenes
2343 detobj.velVector = Vector3.Zero; 2751 detobj.velVector = Vector3.Zero;
2344 detobj.colliderType = 0; 2752 detobj.colliderType = 0;
2345 detobj.groupUUID = UUID.Zero; 2753 detobj.groupUUID = UUID.Zero;
2754 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2346 2755
2347 return detobj; 2756 return detobj;
2348 } 2757 }
@@ -2392,7 +2801,7 @@ namespace OpenSim.Region.Framework.Scenes
2392 CollidingMessage = CreateColliderArgs(this, colliders); 2801 CollidingMessage = CreateColliderArgs(this, colliders);
2393 2802
2394 if (CollidingMessage.Colliders.Count > 0) 2803 if (CollidingMessage.Colliders.Count > 0)
2395 DoNotify(notify, LocalId, CollidingMessage); 2804 notify(LocalId, CollidingMessage);
2396 2805
2397 if (PassCollisions) 2806 if (PassCollisions)
2398 sendToRoot = true; 2807 sendToRoot = true;
@@ -2406,48 +2815,32 @@ namespace OpenSim.Region.Framework.Scenes
2406 { 2815 {
2407 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2816 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2408 if (CollidingMessage.Colliders.Count > 0) 2817 if (CollidingMessage.Colliders.Count > 0)
2409 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); 2818 notify(ParentGroup.RootPart.LocalId, CollidingMessage);
2410 } 2819 }
2411 } 2820 }
2412 } 2821 }
2413 2822
2414 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2823 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2415 { 2824 {
2416 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2825 bool sendToRoot = true;
2417 {
2418 ColliderArgs LandCollidingMessage = new ColliderArgs();
2419 List<DetectedObject> colliding = new List<DetectedObject>();
2420
2421 colliding.Add(CreateDetObjectForGround());
2422 LandCollidingMessage.Colliders = colliding;
2423 2826
2424 DoNotify(notify, LocalId, LandCollidingMessage); 2827 ColliderArgs LandCollidingMessage = new ColliderArgs();
2425 } 2828 List<DetectedObject> colliding = new List<DetectedObject>();
2426 } 2829
2830 colliding.Add(CreateDetObjectForGround());
2831 LandCollidingMessage.Colliders = colliding;
2427 2832
2428 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) 2833 if (Inventory.ContainsScripts())
2429 {
2430 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2431 { 2834 {
2432 // For those learning C#, FireAndForget takes a function, an object to pass 2835 if (!PassCollisions)
2433 // to that function and an ID string. The "oo => {}" construct is a lambda expression 2836 sendToRoot = false;
2434 // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object
2435 // that is an object array and initializes it with three items (the parameters
2436 // being passed). The parameters passed are the function to call ('notify') and
2437 // its two arguements. Finally, once in the function (called later by the FireAndForget
2438 // thread scheduler), the passed object is cast to an object array and then each
2439 // of its items (aoo[0] to aoo[2]) are individually cast to what they are and
2440 // then used in a call of the passed ScriptCollidingNotification function.
2441 Util.FireAndForget(oo =>
2442 {
2443 Object[] aoo = (Object[])oo;
2444 ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]);
2445
2446 }, new Object[] { notify, id, collargs }, "SOP.Collision");
2447 } 2837 }
2448 else 2838 if ((ScriptEvents & ev) != 0)
2839 notify(LocalId, LandCollidingMessage);
2840
2841 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2449 { 2842 {
2450 notify(id, collargs); 2843 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2451 } 2844 }
2452 } 2845 }
2453 2846
@@ -2463,44 +2856,81 @@ namespace OpenSim.Region.Framework.Scenes
2463 List<uint> endedColliders = new List<uint>(); 2856 List<uint> endedColliders = new List<uint>();
2464 List<uint> startedColliders = new List<uint>(); 2857 List<uint> startedColliders = new List<uint>();
2465 2858
2466 // calculate things that started colliding this time 2859 if (collissionswith.Count == 0)
2467 // and build up list of colliders this time
2468 foreach (uint localid in collissionswith.Keys)
2469 { 2860 {
2470 thisHitColliders.Add(localid); 2861 if (m_lastColliders.Count == 0)
2471 if (!m_lastColliders.Contains(localid)) 2862 return; // nothing to do
2472 startedColliders.Add(localid);
2473 }
2474 2863
2475 // calculate things that ended colliding 2864 foreach (uint localID in m_lastColliders)
2476 foreach (uint localID in m_lastColliders) 2865 {
2477 {
2478 if (!thisHitColliders.Contains(localID))
2479 endedColliders.Add(localID); 2866 endedColliders.Add(localID);
2867 }
2868 m_lastColliders.Clear();
2480 } 2869 }
2481 2870
2482 //add the items that started colliding this time to the last colliders list. 2871 else
2483 foreach (uint localID in startedColliders) 2872 {
2484 m_lastColliders.Add(localID); 2873 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2485 2874
2486 // remove things that ended colliding from the last colliders list 2875 // calculate things that started colliding this time
2487 foreach (uint localID in endedColliders) 2876 // and build up list of colliders this time
2488 m_lastColliders.Remove(localID); 2877 if (!VolumeDetectActive && CollisionSoundType >= 0)
2878 {
2879 CollisionForSoundInfo soundinfo;
2880 ContactPoint curcontact;
2489 2881
2490 // play the sound. 2882 foreach (uint id in collissionswith.Keys)
2491 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2883 {
2492 { 2884 thisHitColliders.Add(id);
2493 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2885 if (!m_lastColliders.Contains(id))
2494 if (soundModule != null) 2886 {
2887 startedColliders.Add(id);
2888
2889 curcontact = collissionswith[id];
2890 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2891 {
2892 soundinfo = new CollisionForSoundInfo();
2893 soundinfo.colliderID = id;
2894 soundinfo.position = curcontact.Position;
2895 soundinfo.relativeVel = curcontact.RelativeSpeed;
2896 soundinfolist.Add(soundinfo);
2897 }
2898 }
2899 }
2900 }
2901 else
2495 { 2902 {
2496 soundModule.SendSound(UUID, CollisionSound, 2903 foreach (uint id in collissionswith.Keys)
2497 CollisionSoundVolume, true, 0, 0, false, 2904 {
2498 false); 2905 thisHitColliders.Add(id);
2906 if (!m_lastColliders.Contains(id))
2907 startedColliders.Add(id);
2908 }
2499 } 2909 }
2910
2911 // calculate things that ended colliding
2912 foreach (uint localID in m_lastColliders)
2913 {
2914 if (!thisHitColliders.Contains(localID))
2915 endedColliders.Add(localID);
2916 }
2917
2918 //add the items that started colliding this time to the last colliders list.
2919 foreach (uint localID in startedColliders)
2920 m_lastColliders.Add(localID);
2921
2922 // remove things that ended colliding from the last colliders list
2923 foreach (uint localID in endedColliders)
2924 m_lastColliders.Remove(localID);
2925
2926 // play sounds.
2927 if (soundinfolist.Count > 0)
2928 CollisionSounds.PartCollisionSound(this, soundinfolist);
2500 } 2929 }
2501 2930
2502 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2931 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2503 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2932 if (!VolumeDetectActive)
2933 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2504 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2934 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2505 2935
2506 if (startedColliders.Contains(0)) 2936 if (startedColliders.Contains(0))
@@ -2511,6 +2941,35 @@ namespace OpenSim.Region.Framework.Scenes
2511 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2941 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2512 } 2942 }
2513 2943
2944 // The Collision sounds code calls this
2945 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2946 {
2947 if (soundID == UUID.Zero)
2948 return;
2949
2950 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2951 if (soundModule == null)
2952 return;
2953
2954 if (volume > 1)
2955 volume = 1;
2956 if (volume < 0)
2957 volume = 0;
2958
2959 int now = Util.EnvironmentTickCount();
2960 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2961 return;
2962
2963 LastColSoundSentTime = now;
2964
2965 UUID ownerID = OwnerID;
2966 UUID objectID = ParentGroup.RootPart.UUID;
2967 UUID parentID = ParentGroup.UUID;
2968 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2969
2970 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2971 }
2972
2514 public void PhysicsOutOfBounds(Vector3 pos) 2973 public void PhysicsOutOfBounds(Vector3 pos)
2515 { 2974 {
2516 // Note: This is only being called on the root prim at this time. 2975 // Note: This is only being called on the root prim at this time.
@@ -2538,7 +2997,7 @@ namespace OpenSim.Region.Framework.Scenes
2538 } 2997 }
2539 //ParentGroup.RootPart.m_groupPosition = newpos; 2998 //ParentGroup.RootPart.m_groupPosition = newpos;
2540 } 2999 }
2541 3000/* ubit: there are no flexible links
2542 if (pa != null && ParentID != 0 && ParentGroup != null) 3001 if (pa != null && ParentID != 0 && ParentGroup != null)
2543 { 3002 {
2544 // Special case where a child object is requesting property updates. 3003 // Special case where a child object is requesting property updates.
@@ -2558,7 +3017,7 @@ namespace OpenSim.Region.Framework.Scenes
2558 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", 3017 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2559 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); 3018 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2560 } 3019 }
2561 3020*/
2562 ScheduleTerseUpdate(); 3021 ScheduleTerseUpdate();
2563 } 3022 }
2564 3023
@@ -2811,7 +3270,19 @@ namespace OpenSim.Region.Framework.Scenes
2811 3270
2812// m_log.DebugFormat( 3271// m_log.DebugFormat(
2813// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3272// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
2814 3273
3274
3275 if (ParentGroup.IsAttachment)
3276 {
3277 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3278 if (sp != null)
3279 {
3280 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3281 }
3282 }
3283
3284/* this does nothing
3285SendFullUpdateToClient(remoteClient, Position) ignores position parameter
2815 if (IsRoot) 3286 if (IsRoot)
2816 { 3287 {
2817 if (ParentGroup.IsAttachment) 3288 if (ParentGroup.IsAttachment)
@@ -2823,6 +3294,7 @@ namespace OpenSim.Region.Framework.Scenes
2823 SendFullUpdateToClient(remoteClient, AbsolutePosition); 3294 SendFullUpdateToClient(remoteClient, AbsolutePosition);
2824 } 3295 }
2825 } 3296 }
3297*/
2826 else 3298 else
2827 { 3299 {
2828 SendFullUpdateToClient(remoteClient); 3300 SendFullUpdateToClient(remoteClient);
@@ -2832,17 +3304,55 @@ namespace OpenSim.Region.Framework.Scenes
2832 /// <summary> 3304 /// <summary>
2833 /// Send a full update for this part to all clients. 3305 /// Send a full update for this part to all clients.
2834 /// </summary> 3306 /// </summary>
2835 public void SendFullUpdateToAllClients() 3307 public void SendFullUpdateToAllClientsInternal()
2836 { 3308 {
2837 if (ParentGroup == null) 3309 if (ParentGroup == null)
2838 return; 3310 return;
2839 3311
3312 // Update the "last" values
3313 m_lastPosition = OffsetPosition;
3314 m_lastRotation = RotationOffset;
3315 m_lastVelocity = Velocity;
3316 m_lastAcceleration = Acceleration;
3317 m_lastAngularVelocity = AngularVelocity;
3318 m_lastUpdateSentTime = Environment.TickCount;
3319
2840 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3320 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2841 { 3321 {
2842 SendFullUpdate(avatar.ControllingClient); 3322 SendFullUpdate(avatar.ControllingClient);
2843 }); 3323 });
2844 } 3324 }
2845 3325
3326 public void SendFullUpdateToAllClients()
3327 {
3328 if (ParentGroup == null)
3329 return;
3330
3331 // Update the "last" values
3332 m_lastPosition = OffsetPosition;
3333 m_lastRotation = RotationOffset;
3334 m_lastVelocity = Velocity;
3335 m_lastAcceleration = Acceleration;
3336 m_lastAngularVelocity = AngularVelocity;
3337 m_lastUpdateSentTime = Environment.TickCount;
3338
3339 if (ParentGroup.IsAttachment)
3340 {
3341 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3342 if (sp != null)
3343 {
3344 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3345 }
3346 }
3347 else
3348 {
3349 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3350 {
3351 SendFullUpdate(avatar.ControllingClient);
3352 });
3353 }
3354 }
3355
2846 /// <summary> 3356 /// <summary>
2847 /// Sends a full update to the client 3357 /// Sends a full update to the client
2848 /// </summary> 3358 /// </summary>
@@ -2863,9 +3373,9 @@ namespace OpenSim.Region.Framework.Scenes
2863 return; 3373 return;
2864 3374
2865 // Suppress full updates during attachment editing 3375 // Suppress full updates during attachment editing
2866 // 3376 // sl Does send them
2867 if (ParentGroup.IsSelected && ParentGroup.IsAttachment) 3377 // if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
2868 return; 3378 // return;
2869 3379
2870 if (ParentGroup.IsDeleted) 3380 if (ParentGroup.IsDeleted)
2871 return; 3381 return;
@@ -2895,8 +3405,8 @@ namespace OpenSim.Region.Framework.Scenes
2895 { 3405 {
2896 const float ROTATION_TOLERANCE = 0.01f; 3406 const float ROTATION_TOLERANCE = 0.01f;
2897 const float VELOCITY_TOLERANCE = 0.001f; 3407 const float VELOCITY_TOLERANCE = 0.001f;
2898 const float POSITION_TOLERANCE = 0.05f; 3408 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2899 const int TIME_MS_TOLERANCE = 3000; 3409 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2900 3410
2901 switch (UpdateFlag) 3411 switch (UpdateFlag)
2902 { 3412 {
@@ -2910,40 +3420,74 @@ namespace OpenSim.Region.Framework.Scenes
2910 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3420 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2911 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3421 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2912 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3422 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2913 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3423 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2914 { 3424 {
2915 SendTerseUpdateToAllClients(); 3425 SendTerseUpdateToAllClientsInternal();
2916
2917 // Update the "last" values
2918 m_lastPosition = OffsetPosition;
2919 m_lastRotation = RotationOffset;
2920 m_lastVelocity = Velocity;
2921 m_lastAcceleration = Acceleration;
2922 m_lastAngularVelocity = AngularVelocity;
2923 m_lastTerseSent = Environment.TickCount;
2924 } 3426 }
2925 break; 3427 break;
2926 } 3428 }
2927 case UpdateRequired.FULL: 3429 case UpdateRequired.FULL:
2928 { 3430 {
2929 ClearUpdateSchedule(); 3431 ClearUpdateSchedule();
2930 SendFullUpdateToAllClients(); 3432 SendFullUpdateToAllClientsInternal();
2931 break; 3433 break;
2932 } 3434 }
2933 } 3435 }
2934 } 3436 }
2935 3437
3438
2936 /// <summary> 3439 /// <summary>
2937 /// Send a terse update to all clients 3440 /// Send a terse update to all clients
2938 /// </summary> 3441 /// </summary>
2939 public void SendTerseUpdateToAllClients() 3442 public void SendTerseUpdateToAllClientsInternal()
2940 { 3443 {
3444 if (ParentGroup == null || ParentGroup.Scene == null)
3445 return;
3446
3447 // Update the "last" values
3448 m_lastPosition = OffsetPosition;
3449 m_lastRotation = RotationOffset;
3450 m_lastVelocity = Velocity;
3451 m_lastAcceleration = Acceleration;
3452 m_lastAngularVelocity = AngularVelocity;
3453 m_lastUpdateSentTime = Environment.TickCount;
3454
2941 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3455 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2942 { 3456 {
2943 SendTerseUpdateToClient(client); 3457 SendTerseUpdateToClient(client);
2944 }); 3458 });
2945 } 3459 }
2946 3460
3461 public void SendTerseUpdateToAllClients()
3462 {
3463 if (ParentGroup == null || ParentGroup.Scene == null)
3464 return;
3465
3466 // Update the "last" values
3467 m_lastPosition = OffsetPosition;
3468 m_lastRotation = RotationOffset;
3469 m_lastVelocity = Velocity;
3470 m_lastAcceleration = Acceleration;
3471 m_lastAngularVelocity = AngularVelocity;
3472 m_lastUpdateSentTime = Environment.TickCount;
3473
3474 if (ParentGroup.IsAttachment)
3475 {
3476 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3477 if (sp != null)
3478 {
3479 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3480 }
3481 }
3482 else
3483 {
3484 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3485 {
3486 SendTerseUpdateToClient(client);
3487 });
3488 }
3489 }
3490
2947 public void SetAxisRotation(int axis, int rotate) 3491 public void SetAxisRotation(int axis, int rotate)
2948 { 3492 {
2949 ParentGroup.SetAxisRotation(axis, rotate); 3493 ParentGroup.SetAxisRotation(axis, rotate);
@@ -2961,10 +3505,13 @@ namespace OpenSim.Region.Framework.Scenes
2961 3505
2962 public void SetBuoyancy(float fvalue) 3506 public void SetBuoyancy(float fvalue)
2963 { 3507 {
2964 PhysicsActor pa = PhysActor; 3508 Buoyancy = fvalue;
2965 3509/*
2966 if (pa != null) 3510 if (PhysActor != null)
2967 pa.Buoyancy = fvalue; 3511 {
3512 PhysActor.Buoyancy = fvalue;
3513 }
3514 */
2968 } 3515 }
2969 3516
2970 public void SetDieAtEdge(bool p) 3517 public void SetDieAtEdge(bool p)
@@ -2980,47 +3527,111 @@ namespace OpenSim.Region.Framework.Scenes
2980 PhysicsActor pa = PhysActor; 3527 PhysicsActor pa = PhysActor;
2981 3528
2982 if (pa != null) 3529 if (pa != null)
2983 pa.FloatOnWater = floatYN == 1; 3530 pa.FloatOnWater = (floatYN == 1);
2984 } 3531 }
2985 3532
2986 public void SetForce(Vector3 force) 3533 public void SetForce(Vector3 force)
2987 { 3534 {
2988 PhysicsActor pa = PhysActor; 3535 Force = force;
3536 }
2989 3537
2990 if (pa != null) 3538 public SOPVehicle VehicleParams
2991 pa.Force = force; 3539 {
3540 get
3541 {
3542 return m_vehicleParams;
3543 }
3544 set
3545 {
3546 m_vehicleParams = value;
3547 }
3548 }
3549
3550
3551 public int VehicleType
3552 {
3553 get
3554 {
3555 if (m_vehicleParams == null)
3556 return (int)Vehicle.TYPE_NONE;
3557 else
3558 return (int)m_vehicleParams.Type;
3559 }
3560 set
3561 {
3562 SetVehicleType(value);
3563 }
2992 } 3564 }
2993 3565
2994 public void SetVehicleType(int type) 3566 public void SetVehicleType(int type)
2995 { 3567 {
2996 PhysicsActor pa = PhysActor; 3568 m_vehicleParams = null;
3569
3570 if (type == (int)Vehicle.TYPE_NONE)
3571 {
3572 if (_parentID ==0 && PhysActor != null)
3573 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3574 return;
3575 }
3576 m_vehicleParams = new SOPVehicle();
3577 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3578 {
3579 if (_parentID ==0 && PhysActor != null)
3580 PhysActor.VehicleType = type;
3581 return;
3582 }
3583 }
2997 3584
2998 if (pa != null) 3585 public void SetVehicleFlags(int param, bool remove)
2999 pa.VehicleType = type; 3586 {
3587 if (m_vehicleParams == null)
3588 return;
3589
3590 m_vehicleParams.ProcessVehicleFlags(param, remove);
3591
3592 if (_parentID ==0 && PhysActor != null)
3593 {
3594 PhysActor.VehicleFlags(param, remove);
3595 }
3000 } 3596 }
3001 3597
3002 public void SetVehicleFloatParam(int param, float value) 3598 public void SetVehicleFloatParam(int param, float value)
3003 { 3599 {
3004 PhysicsActor pa = PhysActor; 3600 if (m_vehicleParams == null)
3601 return;
3005 3602
3006 if (pa != null) 3603 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
3007 pa.VehicleFloatParam(param, value); 3604
3605 if (_parentID == 0 && PhysActor != null)
3606 {
3607 PhysActor.VehicleFloatParam(param, value);
3608 }
3008 } 3609 }
3009 3610
3010 public void SetVehicleVectorParam(int param, Vector3 value) 3611 public void SetVehicleVectorParam(int param, Vector3 value)
3011 { 3612 {
3012 PhysicsActor pa = PhysActor; 3613 if (m_vehicleParams == null)
3614 return;
3013 3615
3014 if (pa != null) 3616 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
3015 pa.VehicleVectorParam(param, value); 3617
3618 if (_parentID == 0 && PhysActor != null)
3619 {
3620 PhysActor.VehicleVectorParam(param, value);
3621 }
3016 } 3622 }
3017 3623
3018 public void SetVehicleRotationParam(int param, Quaternion rotation) 3624 public void SetVehicleRotationParam(int param, Quaternion rotation)
3019 { 3625 {
3020 PhysicsActor pa = PhysActor; 3626 if (m_vehicleParams == null)
3627 return;
3021 3628
3022 if (pa != null) 3629 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
3023 pa.VehicleRotationParam(param, rotation); 3630
3631 if (_parentID == 0 && PhysActor != null)
3632 {
3633 PhysActor.VehicleRotationParam(param, rotation);
3634 }
3024 } 3635 }
3025 3636
3026 /// <summary> 3637 /// <summary>
@@ -3221,14 +3832,6 @@ namespace OpenSim.Region.Framework.Scenes
3221 hasProfileCut = hasDimple; // is it the same thing? 3832 hasProfileCut = hasDimple; // is it the same thing?
3222 } 3833 }
3223 3834
3224 public void SetVehicleFlags(int param, bool remove)
3225 {
3226 PhysicsActor pa = PhysActor;
3227
3228 if (pa != null)
3229 pa.VehicleFlags(param, remove);
3230 }
3231
3232 public void SetGroup(UUID groupID, IClientAPI client) 3835 public void SetGroup(UUID groupID, IClientAPI client)
3233 { 3836 {
3234 // Scene.AddNewPrims() calls with client == null so can't use this. 3837 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3237,8 +3840,8 @@ namespace OpenSim.Region.Framework.Scenes
3237// Name, groupID, OwnerID); 3840// Name, groupID, OwnerID);
3238 3841
3239 GroupID = groupID; 3842 GroupID = groupID;
3240 if (client != null) 3843// if (client != null)
3241 SendPropertiesToClient(client); 3844// SendPropertiesToClient(client);
3242 UpdateFlag = UpdateRequired.FULL; 3845 UpdateFlag = UpdateRequired.FULL;
3243 } 3846 }
3244 3847
@@ -3333,67 +3936,16 @@ namespace OpenSim.Region.Framework.Scenes
3333 ParentGroup.StopMoveToTarget(); 3936 ParentGroup.StopMoveToTarget();
3334 } 3937 }
3335 3938
3336 public void StoreUndoState() 3939 public void StoreUndoState(ObjectChangeType change)
3337 {
3338 StoreUndoState(false);
3339 }
3340
3341 public void StoreUndoState(bool forGroup)
3342 { 3940 {
3343 if (ParentGroup == null || ParentGroup.Scene == null) 3941 if (m_UndoRedo == null)
3344 return; 3942 m_UndoRedo = new UndoRedoState(5);
3345
3346 if (Undoing)
3347 {
3348// m_log.DebugFormat(
3349// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3350 return;
3351 }
3352
3353 if (IgnoreUndoUpdate)
3354 {
3355// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3356 return;
3357 }
3358 3943
3359 lock (m_undo) 3944 lock (m_UndoRedo)
3360 { 3945 {
3361 if (m_undo.Count > 0) 3946 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3362 { 3947 {
3363 UndoState last = m_undo[m_undo.Count - 1]; 3948 m_UndoRedo.StoreUndo(this, change);
3364 if (last != null)
3365 {
3366 // TODO: May need to fix for group comparison
3367 if (last.Compare(this))
3368 {
3369// m_log.DebugFormat(
3370// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3371// Name, LocalId, m_undo.Count);
3372
3373 return;
3374 }
3375 }
3376 }
3377
3378// m_log.DebugFormat(
3379// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3380// Name, LocalId, forGroup, m_undo.Count);
3381
3382 if (ParentGroup.Scene.MaxUndoCount > 0)
3383 {
3384 UndoState nUndo = new UndoState(this, forGroup);
3385
3386 m_undo.Add(nUndo);
3387
3388 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3389 m_undo.RemoveAt(0);
3390
3391 if (m_redo.Count > 0)
3392 m_redo.Clear();
3393
3394// m_log.DebugFormat(
3395// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3396// Name, LocalId, forGroup, m_undo.Count);
3397 } 3949 }
3398 } 3950 }
3399 } 3951 }
@@ -3405,88 +3957,46 @@ namespace OpenSim.Region.Framework.Scenes
3405 { 3957 {
3406 get 3958 get
3407 { 3959 {
3408 lock (m_undo) 3960 if (m_UndoRedo == null)
3409 return m_undo.Count; 3961 return 0;
3962 return m_UndoRedo.Count;
3410 } 3963 }
3411 } 3964 }
3412 3965
3413 public void Undo() 3966 public void Undo()
3414 { 3967 {
3415 lock (m_undo) 3968 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3416 { 3969 return;
3417// m_log.DebugFormat(
3418// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3419// Name, LocalId, m_undo.Count);
3420
3421 if (m_undo.Count > 0)
3422 {
3423 UndoState goback = m_undo[m_undo.Count - 1];
3424 m_undo.RemoveAt(m_undo.Count - 1);
3425
3426 UndoState nUndo = null;
3427
3428 if (ParentGroup.Scene.MaxUndoCount > 0)
3429 {
3430 nUndo = new UndoState(this, goback.ForGroup);
3431 }
3432
3433 goback.PlaybackState(this);
3434
3435 if (nUndo != null)
3436 {
3437 m_redo.Add(nUndo);
3438
3439 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3440 m_redo.RemoveAt(0);
3441 }
3442 }
3443 3970
3444// m_log.DebugFormat( 3971 lock (m_UndoRedo)
3445// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3972 {
3446// Name, LocalId, m_undo.Count); 3973 Undoing = true;
3974 m_UndoRedo.Undo(this);
3975 Undoing = false;
3447 } 3976 }
3448 } 3977 }
3449 3978
3450 public void Redo() 3979 public void Redo()
3451 { 3980 {
3452 lock (m_undo) 3981 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3453 { 3982 return;
3454// m_log.DebugFormat(
3455// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3456// Name, LocalId, m_redo.Count);
3457
3458 if (m_redo.Count > 0)
3459 {
3460 UndoState gofwd = m_redo[m_redo.Count - 1];
3461 m_redo.RemoveAt(m_redo.Count - 1);
3462
3463 if (ParentGroup.Scene.MaxUndoCount > 0)
3464 {
3465 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3466
3467 m_undo.Add(nUndo);
3468
3469 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3470 m_undo.RemoveAt(0);
3471 }
3472
3473 gofwd.PlayfwdState(this);
3474 3983
3475// m_log.DebugFormat( 3984 lock (m_UndoRedo)
3476// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3985 {
3477// Name, LocalId, m_redo.Count); 3986 Undoing = true;
3478 } 3987 m_UndoRedo.Redo(this);
3988 Undoing = false;
3479 } 3989 }
3480 } 3990 }
3481 3991
3482 public void ClearUndoState() 3992 public void ClearUndoState()
3483 { 3993 {
3484// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3994 if (m_UndoRedo == null || Undoing)
3995 return;
3485 3996
3486 lock (m_undo) 3997 lock (m_UndoRedo)
3487 { 3998 {
3488 m_undo.Clear(); 3999 m_UndoRedo.Clear();
3489 m_redo.Clear();
3490 } 4000 }
3491 } 4001 }
3492 4002
@@ -4038,7 +4548,7 @@ namespace OpenSim.Region.Framework.Scenes
4038 if (god) 4548 if (god)
4039 { 4549 {
4040 BaseMask = ApplyMask(BaseMask, set, mask); 4550 BaseMask = ApplyMask(BaseMask, set, mask);
4041 Inventory.ApplyGodPermissions(_baseMask); 4551 Inventory.ApplyGodPermissions(BaseMask);
4042 } 4552 }
4043 4553
4044 break; 4554 break;
@@ -4069,7 +4579,7 @@ namespace OpenSim.Region.Framework.Scenes
4069 } 4579 }
4070 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4580 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
4071 baseMask; 4581 baseMask;
4072 // Prevent the client from creating no mod, no copy 4582 // Prevent the client from creating no copy, no transfer
4073 // objects 4583 // objects
4074 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4584 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
4075 NextOwnerMask |= (uint)PermissionMask.Transfer; 4585 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -4085,22 +4595,20 @@ namespace OpenSim.Region.Framework.Scenes
4085 4595
4086 public void ClonePermissions(SceneObjectPart source) 4596 public void ClonePermissions(SceneObjectPart source)
4087 { 4597 {
4088 bool update = false; 4598 uint prevOwnerMask = OwnerMask;
4599 uint prevGroupMask = GroupMask;
4600 uint prevEveryoneMask = EveryoneMask;
4601 uint prevNextOwnerMask = NextOwnerMask;
4089 4602
4090 if (BaseMask != source.BaseMask || 4603 OwnerMask = source.OwnerMask & BaseMask;
4091 OwnerMask != source.OwnerMask || 4604 GroupMask = source.GroupMask & BaseMask;
4092 GroupMask != source.GroupMask || 4605 EveryoneMask = source.EveryoneMask & BaseMask;
4093 EveryoneMask != source.EveryoneMask || 4606 NextOwnerMask = source.NextOwnerMask & BaseMask;
4094 NextOwnerMask != source.NextOwnerMask)
4095 update = true;
4096 4607
4097 BaseMask = source.BaseMask; 4608 if (OwnerMask != prevOwnerMask ||
4098 OwnerMask = source.OwnerMask; 4609 GroupMask != prevGroupMask ||
4099 GroupMask = source.GroupMask; 4610 EveryoneMask != prevEveryoneMask ||
4100 EveryoneMask = source.EveryoneMask; 4611 NextOwnerMask != prevNextOwnerMask)
4101 NextOwnerMask = source.NextOwnerMask;
4102
4103 if (update)
4104 SendFullUpdateToAllClients(); 4612 SendFullUpdateToAllClients();
4105 } 4613 }
4106 4614
@@ -4151,6 +4659,7 @@ namespace OpenSim.Region.Framework.Scenes
4151 } 4659 }
4152 } 4660 }
4153 4661
4662
4154 public void UpdateExtraPhysics(ExtraPhysicsData physdata) 4663 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4155 { 4664 {
4156 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4665 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
@@ -4178,7 +4687,7 @@ namespace OpenSim.Region.Framework.Scenes
4178 /// <param name="SetTemporary"></param> 4687 /// <param name="SetTemporary"></param>
4179 /// <param name="SetPhantom"></param> 4688 /// <param name="SetPhantom"></param>
4180 /// <param name="SetVD"></param> 4689 /// <param name="SetVD"></param>
4181 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4690 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4182 { 4691 {
4183 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4692 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4184 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4693 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4188,99 +4697,104 @@ namespace OpenSim.Region.Framework.Scenes
4188 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4697 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4189 return; 4698 return;
4190 4699
4191 PhysicsActor pa = PhysActor; 4700 VolumeDetectActive = SetVD;
4192
4193 // Special cases for VD. VD can only be called from a script
4194 // and can't be combined with changes to other states. So we can rely
4195 // that...
4196 // ... if VD is changed, all others are not.
4197 // ... if one of the others is changed, VD is not.
4198 if (SetVD) // VD is active, special logic applies
4199 {
4200 // State machine logic for VolumeDetect
4201 // More logic below
4202 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4203
4204 if (phanReset) // Phantom changes from on to off switch VD off too
4205 {
4206 SetVD = false; // Switch it of for the course of this routine
4207 VolumeDetectActive = false; // and also permanently
4208
4209 if (pa != null)
4210 pa.SetVolumeDetect(0); // Let physics know about it too
4211 }
4212 else
4213 {
4214 // If volumedetect is active we don't want phantom to be applied.
4215 // If this is a new call to VD out of the state "phantom"
4216 // this will also cause the prim to be visible to physics
4217 SetPhantom = false;
4218 }
4219 }
4220 4701
4221 if (UsePhysics && IsJoint()) 4702 // volume detector implies phantom
4222 { 4703 if (VolumeDetectActive)
4223 SetPhantom = true; 4704 SetPhantom = true;
4224 }
4225 4705
4226 if (UsePhysics) 4706 if (UsePhysics)
4227 {
4228 AddFlag(PrimFlags.Physics); 4707 AddFlag(PrimFlags.Physics);
4229 if (!wasUsingPhysics)
4230 {
4231 DoPhysicsPropertyUpdate(UsePhysics, false);
4232 }
4233 }
4234 else 4708 else
4235 {
4236 RemFlag(PrimFlags.Physics); 4709 RemFlag(PrimFlags.Physics);
4237 if (wasUsingPhysics)
4238 {
4239 DoPhysicsPropertyUpdate(UsePhysics, false);
4240 }
4241 }
4242 4710
4243 if (SetPhantom 4711 if (SetPhantom)
4244 || ParentGroup.IsAttachment
4245 || PhysicsShapeType == (byte)PhysShapeType.none
4246 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4247 {
4248 AddFlag(PrimFlags.Phantom); 4712 AddFlag(PrimFlags.Phantom);
4713 else
4714 RemFlag(PrimFlags.Phantom);
4249 4715
4250 if (PhysActor != null) 4716 if (SetTemporary)
4717 AddFlag(PrimFlags.TemporaryOnRez);
4718 else
4719 RemFlag(PrimFlags.TemporaryOnRez);
4720
4721
4722 if (ParentGroup.Scene == null)
4723 return;
4724
4725 PhysicsActor pa = PhysActor;
4726
4727 if (pa != null && building && pa.Building != building)
4728 pa.Building = building;
4729
4730 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4731 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4732 {
4733 if (pa != null)
4251 { 4734 {
4735 if(wasUsingPhysics)
4736 ParentGroup.Scene.RemovePhysicalPrim(1);
4252 RemoveFromPhysics(); 4737 RemoveFromPhysics();
4253 pa = null;
4254 } 4738 }
4739
4740 Velocity = new Vector3(0, 0, 0);
4741 Acceleration = new Vector3(0, 0, 0);
4742 if (ParentGroup.RootPart == this)
4743 AngularVelocity = new Vector3(0, 0, 0);
4255 } 4744 }
4256 else // Not phantom 4745
4746 else
4257 { 4747 {
4258 RemFlag(PrimFlags.Phantom); 4748 if (ParentGroup.Scene.CollidablePrims)
4259
4260 if (ParentGroup.Scene == null)
4261 return;
4262
4263 if (ParentGroup.Scene.CollidablePrims && pa == null)
4264 { 4749 {
4265 AddToPhysics(UsePhysics, SetPhantom, false); 4750 if (pa == null)
4266 pa = PhysActor; 4751 {
4267 4752 AddToPhysics(UsePhysics, SetPhantom, building, false);
4268 if (pa != null) 4753 pa = PhysActor;
4754/*
4755 if (pa != null)
4756 {
4757 if (
4758// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4759// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4760// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4761// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4762// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4763// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4764 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4765 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4766 (CollisionSound != UUID.Zero)
4767 )
4768 {
4769 pa.OnCollisionUpdate += PhysicsCollision;
4770 pa.SubscribeEvents(1000);
4771 }
4772 }
4773*/
4774 if (pa != null)
4775 {
4776 pa.SetMaterial(Material);
4777 DoPhysicsPropertyUpdate(UsePhysics, true);
4778 }
4779 }
4780 else // it already has a physical representation
4269 { 4781 {
4270 pa.SetMaterial(Material);
4271 pa.Position = GetWorldPosition();
4272 pa.Orientation = GetWorldRotation();
4273 DoPhysicsPropertyUpdate(UsePhysics, true);
4274 4782
4275 SubscribeForCollisionEvents(); 4783 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4784/* moved into DoPhysicsPropertyUpdate
4785 if(VolumeDetectActive)
4786 pa.SetVolumeDetect(1);
4787 else
4788 pa.SetVolumeDetect(0);
4789*/
4790
4791 if (pa.Building != building)
4792 pa.Building = building;
4276 } 4793 }
4277 }
4278 else // it already has a physical representation
4279 {
4280 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4281 }
4282 }
4283 4794
4795 UpdatePhysicsSubscribedEvents();
4796 }
4797 }
4284 if (SetVD) 4798 if (SetVD)
4285 { 4799 {
4286 // If the above logic worked (this is urgent candidate to unit tests!) 4800 // If the above logic worked (this is urgent candidate to unit tests!)
@@ -4294,6 +4808,7 @@ namespace OpenSim.Region.Framework.Scenes
4294 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4808 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4295 VolumeDetectActive = true; 4809 VolumeDetectActive = true;
4296 } 4810 }
4811 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4297 } 4812 }
4298 else if (SetVD != wasVD) 4813 else if (SetVD != wasVD)
4299 { 4814 {
@@ -4305,105 +4820,51 @@ namespace OpenSim.Region.Framework.Scenes
4305 RemFlag(PrimFlags.Phantom); 4820 RemFlag(PrimFlags.Phantom);
4306 VolumeDetectActive = false; 4821 VolumeDetectActive = false;
4307 } 4822 }
4308 4823 // and last in case we have a new actor and not building
4309 if (SetTemporary)
4310 {
4311 AddFlag(PrimFlags.TemporaryOnRez);
4312 }
4313 else
4314 {
4315 RemFlag(PrimFlags.TemporaryOnRez);
4316 }
4317
4318 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4319 4824
4320 if (ParentGroup != null) 4825 if (ParentGroup != null)
4321 { 4826 {
4322 ParentGroup.HasGroupChanged = true; 4827 ParentGroup.HasGroupChanged = true;
4323 ScheduleFullUpdate(); 4828 ScheduleFullUpdate();
4324 } 4829 }
4325 4830
4326// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4831// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4327 } 4832 }
4328 4833
4329 /// <summary> 4834 /// <summary>
4330 /// Subscribe for physics collision events if needed for scripts and sounds
4331 /// </summary>
4332 public void SubscribeForCollisionEvents()
4333 {
4334 PhysicsActor pa = PhysActor;
4335
4336 if (pa != null)
4337 {
4338 if (
4339 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4340 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4344 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4345 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4350 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4351 (CollisionSound != UUID.Zero)
4352 )
4353 {
4354 if (!pa.SubscribedEvents())
4355 {
4356 // If not already subscribed for event, set up for a collision event.
4357 pa.OnCollisionUpdate += PhysicsCollision;
4358 pa.SubscribeEvents(1000);
4359 }
4360 }
4361 else
4362 {
4363 // There is no need to be subscribed to collisions so, if subscribed, remove subscription
4364 if (pa.SubscribedEvents())
4365 {
4366 pa.OnCollisionUpdate -= PhysicsCollision;
4367 pa.UnSubscribeEvents();
4368 }
4369 }
4370 }
4371 }
4372
4373 /// <summary>
4374 /// Adds this part to the physics scene. 4835 /// Adds this part to the physics scene.
4836 /// and sets the PhysActor property
4375 /// </summary> 4837 /// </summary>
4376 /// <remarks>This method also sets the PhysActor property.</remarks> 4838 /// <param name="isPhysical">Add this prim as physical.</param>
4377 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4839 /// <param name="isPhantom">Add this prim as phantom.</param>
4378 /// <returns> 4840 /// <param name="building">tells physics to delay full construction of object</param>
4379 /// The physics actor. null if there was a failure. 4841 /// <param name="applyDynamics">applies velocities, force and torque</param>
4380 /// </returns> 4842 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4381 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics) 4843 {
4382 {
4383 PhysicsActor pa; 4844 PhysicsActor pa;
4384 4845
4385 Vector3 velocity = Velocity; 4846 Vector3 velocity = Velocity;
4386 Vector3 rotationalVelocity = AngularVelocity;; 4847 Vector3 rotationalVelocity = AngularVelocity;;
4387 4848
4388 try 4849 try
4389 { 4850 {
4390 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4851 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4391 string.Format("{0}/{1}", Name, UUID), 4852 string.Format("{0}/{1}", Name, UUID),
4392 Shape, 4853 Shape,
4393 AbsolutePosition, 4854 AbsolutePosition,
4394 Scale, 4855 Scale,
4395 GetWorldRotation(), 4856 GetWorldRotation(),
4396 isPhysical, 4857 isPhysical,
4397 isPhantom, 4858 isPhantom,
4398 PhysicsShapeType, 4859 PhysicsShapeType,
4399 m_localId); 4860 m_localId);
4400 } 4861 }
4401 catch (Exception e) 4862 catch (Exception e)
4402 { 4863 {
4403 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e); 4864 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4404 pa = null; 4865 pa = null;
4405 } 4866 }
4406 4867
4407 if (pa != null) 4868 if (pa != null)
4408 { 4869 {
4409 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4870 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
@@ -4416,9 +4877,16 @@ namespace OpenSim.Region.Framework.Scenes
4416 4877
4417 if (VolumeDetectActive) // change if not the default only 4878 if (VolumeDetectActive) // change if not the default only
4418 pa.SetVolumeDetect(1); 4879 pa.SetVolumeDetect(1);
4880
4881 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4882 m_vehicleParams.SetVehicle(pa);
4883
4419 // we are going to tell rest of code about physics so better have this here 4884 // we are going to tell rest of code about physics so better have this here
4420 PhysActor = pa; 4885 PhysActor = pa;
4421 4886
4887 // DoPhysicsPropertyUpdate(isPhysical, true);
4888 // lets expand it here just with what it really needs to do
4889
4422 if (isPhysical) 4890 if (isPhysical)
4423 { 4891 {
4424 if (ParentGroup.RootPart.KeyframeMotion != null) 4892 if (ParentGroup.RootPart.KeyframeMotion != null)
@@ -4440,19 +4908,34 @@ namespace OpenSim.Region.Framework.Scenes
4440 } 4908 }
4441 } 4909 }
4442 4910
4443 if (applyDynamics) 4911 if (applyDynamics)
4444 // do independent of isphysical so parameters get setted (at least some) 4912 // do independent of isphysical so parameters get setted (at least some)
4445 { 4913 {
4446 Velocity = velocity; 4914 Velocity = velocity;
4447 AngularVelocity = rotationalVelocity; 4915 AngularVelocity = rotationalVelocity;
4448// pa.Velocity = velocity; 4916// pa.Velocity = velocity;
4449 pa.RotationalVelocity = rotationalVelocity; 4917 pa.RotationalVelocity = rotationalVelocity;
4918
4919 // if not vehicle and root part apply force and torque
4920 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4921 && LocalId == ParentGroup.RootPart.LocalId)
4922 {
4923 pa.Force = Force;
4924 pa.Torque = Torque;
4925 }
4450 } 4926 }
4451 4927
4452 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 4928// if (Shape.SculptEntry)
4929// CheckSculptAndLoad();
4930// else
4931 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4932
4933 if (!building)
4934 pa.Building = false;
4453 } 4935 }
4454 4936
4455 PhysActor = pa; 4937 PhysActor = pa;
4938
4456 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); 4939 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4457 } 4940 }
4458 4941
@@ -4461,14 +4944,21 @@ namespace OpenSim.Region.Framework.Scenes
4461 /// </summary> 4944 /// </summary>
4462 /// <remarks> 4945 /// <remarks>
4463 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4946 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4464 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4947 /// representation for collision detection.
4465 /// phantom.
4466 /// </remarks> 4948 /// </remarks>
4467 public void RemoveFromPhysics() 4949 public void RemoveFromPhysics()
4468 { 4950 {
4469 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); 4951 PhysicsActor pa = PhysActor;
4470 if (ParentGroup.Scene.PhysicsScene != null) 4952 if (pa != null)
4471 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4953 {
4954 pa.OnCollisionUpdate -= PhysicsCollision;
4955 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4956 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4957
4958 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4959
4960 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
4961 }
4472 PhysActor = null; 4962 PhysActor = null;
4473 } 4963 }
4474 4964
@@ -4600,6 +5090,8 @@ namespace OpenSim.Region.Framework.Scenes
4600 { 5090 {
4601// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 5091// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4602 5092
5093 return;
5094
4603 if (ParentGroup.IsDeleted) 5095 if (ParentGroup.IsDeleted)
4604 return; 5096 return;
4605 5097
@@ -4723,6 +5215,44 @@ namespace OpenSim.Region.Framework.Scenes
4723 } 5215 }
4724 } 5216 }
4725 5217
5218
5219 private void UpdatePhysicsSubscribedEvents()
5220 {
5221 PhysicsActor pa = PhysActor;
5222 if (pa == null)
5223 return;
5224
5225 pa.OnCollisionUpdate -= PhysicsCollision;
5226
5227 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5228
5229 scriptEvents CombinedEvents = AggregateScriptEvents;
5230
5231 // merge with root part
5232 if (ParentGroup != null && ParentGroup.RootPart != null)
5233 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5234
5235 // submit to this part case
5236 if (VolumeDetectActive)
5237 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5238 else if ((Flags & PrimFlags.Phantom) != 0)
5239 CombinedEvents &= PhyscicsPhantonSubsEvents;
5240 else
5241 CombinedEvents &= PhysicsNeededSubsEvents;
5242
5243 if (hassound || CombinedEvents != 0)
5244 {
5245 // subscribe to physics updates.
5246 pa.OnCollisionUpdate += PhysicsCollision;
5247 pa.SubscribeEvents(50); // 20 reports per second
5248 }
5249 else
5250 {
5251 pa.UnSubscribeEvents();
5252 }
5253 }
5254
5255
4726 public void aggregateScriptEvents() 5256 public void aggregateScriptEvents()
4727 { 5257 {
4728 if (ParentGroup == null || ParentGroup.RootPart == null) 5258 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4759,8 +5289,32 @@ namespace OpenSim.Region.Framework.Scenes
4759 { 5289 {
4760 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5290 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4761 } 5291 }
4762 5292/*
4763 SubscribeForCollisionEvents(); 5293 PhysicsActor pa = PhysActor;
5294 if (pa != null)
5295 {
5296 if (
5297// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5298// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5299// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5300// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5301// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5302// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5303 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5304 )
5305 {
5306 // subscribe to physics updates.
5307 pa.OnCollisionUpdate += PhysicsCollision;
5308 pa.SubscribeEvents(1000);
5309 }
5310 else
5311 {
5312 pa.UnSubscribeEvents();
5313 pa.OnCollisionUpdate -= PhysicsCollision;
5314 }
5315 }
5316 */
5317 UpdatePhysicsSubscribedEvents();
4764 5318
4765 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5319 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4766 //{ 5320 //{
@@ -4969,6 +5523,18 @@ namespace OpenSim.Region.Framework.Scenes
4969 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5523 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4970 } 5524 }
4971 5525
5526 public void ResetOwnerChangeFlag()
5527 {
5528 List<UUID> inv = Inventory.GetInventoryList();
5529
5530 foreach (UUID itemID in inv)
5531 {
5532 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5533 item.OwnerChanged = false;
5534 Inventory.UpdateInventoryItem(item, false, false);
5535 }
5536 }
5537
4972 /// <summary> 5538 /// <summary>
4973 /// Record an avatar sitting on this part. 5539 /// Record an avatar sitting on this part.
4974 /// </summary> 5540 /// </summary>
@@ -4977,19 +5543,19 @@ namespace OpenSim.Region.Framework.Scenes
4977 /// true if the avatar was not already recorded, false otherwise. 5543 /// true if the avatar was not already recorded, false otherwise.
4978 /// </returns> 5544 /// </returns>
4979 /// <param name='avatarId'></param> 5545 /// <param name='avatarId'></param>
4980 protected internal bool AddSittingAvatar(ScenePresence sp) 5546 protected internal bool AddSittingAvatar(UUID id)
4981 { 5547 {
4982 lock (ParentGroup.m_sittingAvatars) 5548 lock (ParentGroup.m_sittingAvatars)
4983 { 5549 {
4984 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero) 5550 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
4985 SitTargetAvatar = sp.UUID; 5551 SitTargetAvatar = id;
4986 5552
4987 if (m_sittingAvatars == null) 5553 if (m_sittingAvatars == null)
4988 m_sittingAvatars = new HashSet<ScenePresence>(); 5554 m_sittingAvatars = new HashSet<UUID>();
4989 5555
4990 if (m_sittingAvatars.Add(sp)) 5556 if (m_sittingAvatars.Add(id))
4991 { 5557 {
4992 ParentGroup.m_sittingAvatars.Add(sp); 5558 ParentGroup.m_sittingAvatars.Add(id);
4993 5559
4994 return true; 5560 return true;
4995 } 5561 }
@@ -5006,22 +5572,22 @@ namespace OpenSim.Region.Framework.Scenes
5006 /// true if the avatar was present and removed, false if it was not present. 5572 /// true if the avatar was present and removed, false if it was not present.
5007 /// </returns> 5573 /// </returns>
5008 /// <param name='avatarId'></param> 5574 /// <param name='avatarId'></param>
5009 protected internal bool RemoveSittingAvatar(ScenePresence sp) 5575 protected internal bool RemoveSittingAvatar(UUID id)
5010 { 5576 {
5011 lock (ParentGroup.m_sittingAvatars) 5577 lock (ParentGroup.m_sittingAvatars)
5012 { 5578 {
5013 if (SitTargetAvatar == sp.UUID) 5579 if (SitTargetAvatar == id)
5014 SitTargetAvatar = UUID.Zero; 5580 SitTargetAvatar = UUID.Zero;
5015 5581
5016 if (m_sittingAvatars == null) 5582 if (m_sittingAvatars == null)
5017 return false; 5583 return false;
5018 5584
5019 if (m_sittingAvatars.Remove(sp)) 5585 if (m_sittingAvatars.Remove(id))
5020 { 5586 {
5021 if (m_sittingAvatars.Count == 0) 5587 if (m_sittingAvatars.Count == 0)
5022 m_sittingAvatars = null; 5588 m_sittingAvatars = null;
5023 5589
5024 ParentGroup.m_sittingAvatars.Remove(sp); 5590 ParentGroup.m_sittingAvatars.Remove(id);
5025 5591
5026 return true; 5592 return true;
5027 } 5593 }
@@ -5035,14 +5601,14 @@ namespace OpenSim.Region.Framework.Scenes
5035 /// </summary> 5601 /// </summary>
5036 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> 5602 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
5037 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns> 5603 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
5038 public HashSet<ScenePresence> GetSittingAvatars() 5604 public HashSet<UUID> GetSittingAvatars()
5039 { 5605 {
5040 lock (ParentGroup.m_sittingAvatars) 5606 lock (ParentGroup.m_sittingAvatars)
5041 { 5607 {
5042 if (m_sittingAvatars == null) 5608 if (m_sittingAvatars == null)
5043 return null; 5609 return null;
5044 else 5610 else
5045 return new HashSet<ScenePresence>(m_sittingAvatars); 5611 return new HashSet<UUID>(m_sittingAvatars);
5046 } 5612 }
5047 } 5613 }
5048 5614
@@ -5062,4 +5628,4 @@ namespace OpenSim.Region.Framework.Scenes
5062 } 5628 }
5063 } 5629 }
5064 } 5630 }
5065} \ No newline at end of file 5631}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index ec39726..5811ed9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -46,9 +46,12 @@ 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;
51 private bool m_inventoryPrivileged = false;
52 private object m_inventoryFileLock = new object();
53
54 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
52 55
53 /// <value> 56 /// <value>
54 /// The part to which the inventory belongs. 57 /// The part to which the inventory belongs.
@@ -85,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
85 /// </value> 88 /// </value>
86 protected internal TaskInventoryDictionary Items 89 protected internal TaskInventoryDictionary Items
87 { 90 {
88 get { return m_items; } 91 get {
92 return m_items;
93 }
89 set 94 set
90 { 95 {
91 m_items = value; 96 m_items = value;
@@ -134,38 +139,45 @@ namespace OpenSim.Region.Framework.Scenes
134 public void ResetInventoryIDs() 139 public void ResetInventoryIDs()
135 { 140 {
136 if (null == m_part) 141 if (null == m_part)
137 return; 142 m_items.LockItemsForWrite(true);
138 143
139 lock (m_items) 144 if (Items.Count == 0)
140 { 145 {
141 if (0 == m_items.Count) 146 m_items.LockItemsForWrite(false);
142 return; 147 return;
148 }
143 149
144 IList<TaskInventoryItem> items = GetInventoryItems(); 150 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
145 m_items.Clear(); 151 Items.Clear();
146 152
147 foreach (TaskInventoryItem item in items) 153 foreach (TaskInventoryItem item in items)
148 { 154 {
149 item.ResetIDs(m_part.UUID); 155 item.ResetIDs(m_part.UUID);
150 m_items.Add(item.ItemID, item); 156 Items.Add(item.ItemID, item);
151 }
152 } 157 }
158 m_items.LockItemsForWrite(false);
153 } 159 }
154 160
155 public void ResetObjectID() 161 public void ResetObjectID()
156 { 162 {
157 lock (Items) 163 m_items.LockItemsForWrite(true);
164
165 if (Items.Count == 0)
158 { 166 {
159 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 167 m_items.LockItemsForWrite(false);
160 Items.Clear(); 168 return;
161
162 foreach (TaskInventoryItem item in items)
163 {
164 item.ParentPartID = m_part.UUID;
165 item.ParentID = m_part.UUID;
166 Items.Add(item.ItemID, item);
167 }
168 } 169 }
170
171 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
172 Items.Clear();
173
174 foreach (TaskInventoryItem item in items)
175 {
176 item.ParentPartID = m_part.UUID;
177 item.ParentID = m_part.UUID;
178 Items.Add(item.ItemID, item);
179 }
180 m_items.LockItemsForWrite(false);
169 } 181 }
170 182
171 /// <summary> 183 /// <summary>
@@ -174,17 +186,14 @@ namespace OpenSim.Region.Framework.Scenes
174 /// <param name="ownerId"></param> 186 /// <param name="ownerId"></param>
175 public void ChangeInventoryOwner(UUID ownerId) 187 public void ChangeInventoryOwner(UUID ownerId)
176 { 188 {
177 lock (Items) 189 List<TaskInventoryItem> items = GetInventoryItems();
178 {
179 if (0 == Items.Count)
180 {
181 return;
182 }
183 }
184 190
191 if (items.Count == 0)
192 return;
193
194 m_items.LockItemsForWrite(true);
185 HasInventoryChanged = true; 195 HasInventoryChanged = true;
186 m_part.ParentGroup.HasGroupChanged = true; 196 m_part.ParentGroup.HasGroupChanged = true;
187 List<TaskInventoryItem> items = GetInventoryItems();
188 foreach (TaskInventoryItem item in items) 197 foreach (TaskInventoryItem item in items)
189 { 198 {
190 if (ownerId != item.OwnerID) 199 if (ownerId != item.OwnerID)
@@ -195,6 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
195 item.PermsGranter = UUID.Zero; 204 item.PermsGranter = UUID.Zero;
196 item.OwnerChanged = true; 205 item.OwnerChanged = true;
197 } 206 }
207 m_items.LockItemsForWrite(false);
198 } 208 }
199 209
200 /// <summary> 210 /// <summary>
@@ -203,12 +213,11 @@ namespace OpenSim.Region.Framework.Scenes
203 /// <param name="groupID"></param> 213 /// <param name="groupID"></param>
204 public void ChangeInventoryGroup(UUID groupID) 214 public void ChangeInventoryGroup(UUID groupID)
205 { 215 {
206 lock (Items) 216 m_items.LockItemsForWrite(true);
217 if (0 == Items.Count)
207 { 218 {
208 if (0 == Items.Count) 219 m_items.LockItemsForWrite(false);
209 { 220 return;
210 return;
211 }
212 } 221 }
213 222
214 // Don't let this set the HasGroupChanged flag for attachments 223 // Don't let this set the HasGroupChanged flag for attachments
@@ -220,12 +229,15 @@ namespace OpenSim.Region.Framework.Scenes
220 m_part.ParentGroup.HasGroupChanged = true; 229 m_part.ParentGroup.HasGroupChanged = true;
221 } 230 }
222 231
223 List<TaskInventoryItem> items = GetInventoryItems(); 232 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
224 foreach (TaskInventoryItem item in items) 233 foreach (TaskInventoryItem item in items)
225 { 234 {
226 if (groupID != item.GroupID) 235 if (groupID != item.GroupID)
236 {
227 item.GroupID = groupID; 237 item.GroupID = groupID;
238 }
228 } 239 }
240 m_items.LockItemsForWrite(false);
229 } 241 }
230 242
231 private void QueryScriptStates() 243 private void QueryScriptStates()
@@ -233,15 +245,18 @@ namespace OpenSim.Region.Framework.Scenes
233 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 245 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
234 return; 246 return;
235 247
236 lock (Items) 248 Items.LockItemsForRead(true);
249 foreach (TaskInventoryItem item in Items.Values)
237 { 250 {
238 foreach (TaskInventoryItem item in Items.Values) 251 if (item.InvType == (int)InventoryType.LSL)
239 { 252 {
240 bool running; 253 bool running;
241 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) 254 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
242 item.ScriptRunning = running; 255 item.ScriptRunning = running;
243 } 256 }
244 } 257 }
258
259 Items.LockItemsForRead(false);
245 } 260 }
246 261
247 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) 262 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
@@ -318,7 +333,10 @@ namespace OpenSim.Region.Framework.Scenes
318 { 333 {
319 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 334 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
320 foreach (TaskInventoryItem item in scripts) 335 foreach (TaskInventoryItem item in scripts)
336 {
321 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 337 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
338 m_part.RemoveScriptEvents(item.ItemID);
339 }
322 } 340 }
323 341
324 /// <summary> 342 /// <summary>
@@ -340,7 +358,10 @@ namespace OpenSim.Region.Framework.Scenes
340// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 358// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
341 359
342 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 360 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
361 {
362 StoreScriptError(item.ItemID, "no permission");
343 return false; 363 return false;
364 }
344 365
345 m_part.AddFlag(PrimFlags.Scripted); 366 m_part.AddFlag(PrimFlags.Scripted);
346 367
@@ -350,14 +371,13 @@ namespace OpenSim.Region.Framework.Scenes
350 if (stateSource == 2 && // Prim crossing 371 if (stateSource == 2 && // Prim crossing
351 m_part.ParentGroup.Scene.m_trustBinaries) 372 m_part.ParentGroup.Scene.m_trustBinaries)
352 { 373 {
353 lock (m_items) 374 m_items.LockItemsForWrite(true);
354 { 375 m_items[item.ItemID].PermsMask = 0;
355 m_items[item.ItemID].PermsMask = 0; 376 m_items[item.ItemID].PermsGranter = UUID.Zero;
356 m_items[item.ItemID].PermsGranter = UUID.Zero; 377 m_items.LockItemsForWrite(false);
357 }
358
359 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 378 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
360 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 379 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
380 StoreScriptErrors(item.ItemID, null);
361 m_part.ParentGroup.AddActiveScriptCount(1); 381 m_part.ParentGroup.AddActiveScriptCount(1);
362 m_part.ScheduleFullUpdate(); 382 m_part.ScheduleFullUpdate();
363 return true; 383 return true;
@@ -366,6 +386,8 @@ namespace OpenSim.Region.Framework.Scenes
366 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 386 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
367 if (null == asset) 387 if (null == asset)
368 { 388 {
389 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
390 StoreScriptError(item.ItemID, msg);
369 m_log.ErrorFormat( 391 m_log.ErrorFormat(
370 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 392 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
371 item.Name, item.ItemID, m_part.AbsolutePosition, 393 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -378,16 +400,18 @@ namespace OpenSim.Region.Framework.Scenes
378 if (m_part.ParentGroup.m_savedScriptState != null) 400 if (m_part.ParentGroup.m_savedScriptState != null)
379 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 401 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
380 402
381 lock (m_items) 403 m_items.LockItemsForWrite(true);
382 {
383 m_items[item.ItemID].OldItemID = item.OldItemID;
384 m_items[item.ItemID].PermsMask = 0;
385 m_items[item.ItemID].PermsGranter = UUID.Zero;
386 }
387 404
405 m_items[item.ItemID].OldItemID = item.OldItemID;
406 m_items[item.ItemID].PermsMask = 0;
407 m_items[item.ItemID].PermsGranter = UUID.Zero;
408
409 m_items.LockItemsForWrite(false);
410
388 string script = Utils.BytesToString(asset.Data); 411 string script = Utils.BytesToString(asset.Data);
389 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 412 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
390 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 413 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
414 StoreScriptErrors(item.ItemID, null);
391 if (!item.ScriptRunning) 415 if (!item.ScriptRunning)
392 m_part.ParentGroup.Scene.EventManager.TriggerStopScript( 416 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
393 m_part.LocalId, item.ItemID); 417 m_part.LocalId, item.ItemID);
@@ -466,22 +490,138 @@ namespace OpenSim.Region.Framework.Scenes
466 return stateID; 490 return stateID;
467 } 491 }
468 492
493 /// <summary>
494 /// Start a script which is in this prim's inventory.
495 /// Some processing may occur in the background, but this routine returns asap.
496 /// </summary>
497 /// <param name="itemId">
498 /// A <see cref="UUID"/>
499 /// </param>
469 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 500 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 { 501 {
471 TaskInventoryItem item = GetInventoryItem(itemId); 502 lock (m_scriptErrors)
472 if (item != null) 503 {
504 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
505 m_scriptErrors.Remove(itemId);
506 }
507 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
508 return true;
509 }
510
511 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
512 {
513 m_items.LockItemsForRead(true);
514
515 if (m_items.ContainsKey(itemId))
473 { 516 {
474 return CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 517 TaskInventoryItem it = m_items[itemId];
518 m_items.LockItemsForRead(false);
519
520 CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
475 } 521 }
476 else 522 else
477 { 523 {
478 m_log.ErrorFormat( 524 m_items.LockItemsForRead(false);
479 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 525 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
480 itemId, m_part.Name, m_part.UUID,
481 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 526 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
527 StoreScriptError(itemId, msg);
528 m_log.ErrorFormat(
529 "[PRIM INVENTORY]: " +
530 "Couldn't start script with ID {0} since it {1}", itemId, msg);
531 }
532 }
482 533
483 return false; 534 /// <summary>
535 /// Start a script which is in this prim's inventory and return any compilation error messages.
536 /// </summary>
537 /// <param name="itemId">
538 /// A <see cref="UUID"/>
539 /// </param>
540 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
541 {
542 ArrayList errors;
543
544 // Indicate to CreateScriptInstanceInternal() we want it to
545 // post any compilation/loading error messages
546 lock (m_scriptErrors)
547 {
548 m_scriptErrors[itemId] = null;
484 } 549 }
550
551 // Perform compilation/loading
552 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
553
554 // Wait for and retrieve any errors
555 lock (m_scriptErrors)
556 {
557 while ((errors = m_scriptErrors[itemId]) == null)
558 {
559 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
560 {
561 m_log.ErrorFormat(
562 "[PRIM INVENTORY]: " +
563 "timedout waiting for script {0} errors", itemId);
564 errors = m_scriptErrors[itemId];
565 if (errors == null)
566 {
567 errors = new ArrayList(1);
568 errors.Add("timedout waiting for errors");
569 }
570 break;
571 }
572 }
573 m_scriptErrors.Remove(itemId);
574 }
575 return errors;
576 }
577
578 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
579 private void StoreScriptErrors(UUID itemId, ArrayList errors)
580 {
581 lock (m_scriptErrors)
582 {
583 // If compilation/loading initiated via CreateScriptInstance(),
584 // it does not want the errors, so just get out
585 if (!m_scriptErrors.ContainsKey(itemId))
586 {
587 return;
588 }
589
590 // Initiated via CreateScriptInstanceEr(), if we know what the
591 // errors are, save them and wake CreateScriptInstanceEr().
592 if (errors != null)
593 {
594 m_scriptErrors[itemId] = errors;
595 System.Threading.Monitor.PulseAll(m_scriptErrors);
596 return;
597 }
598 }
599
600 // Initiated via CreateScriptInstanceEr() but we don't know what
601 // the errors are yet, so retrieve them from the script engine.
602 // This may involve some waiting internal to GetScriptErrors().
603 errors = GetScriptErrors(itemId);
604
605 // Get a default non-null value to indicate success.
606 if (errors == null)
607 {
608 errors = new ArrayList();
609 }
610
611 // Post to CreateScriptInstanceEr() and wake it up
612 lock (m_scriptErrors)
613 {
614 m_scriptErrors[itemId] = errors;
615 System.Threading.Monitor.PulseAll(m_scriptErrors);
616 }
617 }
618
619 // Like StoreScriptErrors(), but just posts a single string message
620 private void StoreScriptError(UUID itemId, string message)
621 {
622 ArrayList errors = new ArrayList(1);
623 errors.Add(message);
624 StoreScriptErrors(itemId, errors);
485 } 625 }
486 626
487 /// <summary> 627 /// <summary>
@@ -494,15 +634,7 @@ namespace OpenSim.Region.Framework.Scenes
494 /// </param> 634 /// </param>
495 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 635 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
496 { 636 {
497 bool scriptPresent = false; 637 if (m_items.ContainsKey(itemId))
498
499 lock (m_items)
500 {
501 if (m_items.ContainsKey(itemId))
502 scriptPresent = true;
503 }
504
505 if (scriptPresent)
506 { 638 {
507 if (!sceneObjectBeingDeleted) 639 if (!sceneObjectBeingDeleted)
508 m_part.RemoveScriptEvents(itemId); 640 m_part.RemoveScriptEvents(itemId);
@@ -573,14 +705,16 @@ namespace OpenSim.Region.Framework.Scenes
573 /// <returns></returns> 705 /// <returns></returns>
574 private bool InventoryContainsName(string name) 706 private bool InventoryContainsName(string name)
575 { 707 {
576 lock (m_items) 708 m_items.LockItemsForRead(true);
709 foreach (TaskInventoryItem item in m_items.Values)
577 { 710 {
578 foreach (TaskInventoryItem item in m_items.Values) 711 if (item.Name == name)
579 { 712 {
580 if (item.Name == name) 713 m_items.LockItemsForRead(false);
581 return true; 714 return true;
582 } 715 }
583 } 716 }
717 m_items.LockItemsForRead(false);
584 return false; 718 return false;
585 } 719 }
586 720
@@ -622,8 +756,9 @@ namespace OpenSim.Region.Framework.Scenes
622 /// <param name="item"></param> 756 /// <param name="item"></param>
623 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 757 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
624 { 758 {
625 List<TaskInventoryItem> il = GetInventoryItems(); 759 m_items.LockItemsForRead(true);
626 760 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
761 m_items.LockItemsForRead(false);
627 foreach (TaskInventoryItem i in il) 762 foreach (TaskInventoryItem i in il)
628 { 763 {
629 if (i.Name == item.Name) 764 if (i.Name == item.Name)
@@ -661,14 +796,14 @@ namespace OpenSim.Region.Framework.Scenes
661 item.Name = name; 796 item.Name = name;
662 item.GroupID = m_part.GroupID; 797 item.GroupID = m_part.GroupID;
663 798
664 lock (m_items) 799 m_items.LockItemsForWrite(true);
665 m_items.Add(item.ItemID, item); 800 m_items.Add(item.ItemID, item);
666 801 m_items.LockItemsForWrite(false);
667 if (allowedDrop) 802 if (allowedDrop)
668 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 803 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
669 else 804 else
670 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 805 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
671 806
672 m_inventorySerial++; 807 m_inventorySerial++;
673 //m_inventorySerial += 2; 808 //m_inventorySerial += 2;
674 HasInventoryChanged = true; 809 HasInventoryChanged = true;
@@ -684,15 +819,15 @@ namespace OpenSim.Region.Framework.Scenes
684 /// <param name="items"></param> 819 /// <param name="items"></param>
685 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 820 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
686 { 821 {
687 lock (m_items) 822 m_items.LockItemsForWrite(true);
823 foreach (TaskInventoryItem item in items)
688 { 824 {
689 foreach (TaskInventoryItem item in items) 825 m_items.Add(item.ItemID, item);
690 { 826// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
691 m_items.Add(item.ItemID, item);
692// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
693 }
694 m_inventorySerial++;
695 } 827 }
828 m_items.LockItemsForWrite(false);
829
830 m_inventorySerial++;
696 } 831 }
697 832
698 /// <summary> 833 /// <summary>
@@ -703,23 +838,24 @@ namespace OpenSim.Region.Framework.Scenes
703 public TaskInventoryItem GetInventoryItem(UUID itemId) 838 public TaskInventoryItem GetInventoryItem(UUID itemId)
704 { 839 {
705 TaskInventoryItem item; 840 TaskInventoryItem item;
706 841 m_items.LockItemsForRead(true);
707 lock (m_items) 842 m_items.TryGetValue(itemId, out item);
708 m_items.TryGetValue(itemId, out item); 843 m_items.LockItemsForRead(false);
709
710 return item; 844 return item;
711 } 845 }
712 846
713 public TaskInventoryItem GetInventoryItem(string name) 847 public TaskInventoryItem GetInventoryItem(string name)
714 { 848 {
715 lock (m_items) 849 m_items.LockItemsForRead(true);
850 foreach (TaskInventoryItem item in m_items.Values)
716 { 851 {
717 foreach (TaskInventoryItem item in m_items.Values) 852 if (item.Name == name)
718 { 853 {
719 if (item.Name == name) 854 m_items.LockItemsForRead(false);
720 return item; 855 return item;
721 } 856 }
722 } 857 }
858 m_items.LockItemsForRead(false);
723 859
724 return null; 860 return null;
725 } 861 }
@@ -728,19 +864,20 @@ namespace OpenSim.Region.Framework.Scenes
728 { 864 {
729 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 865 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
730 866
731 lock (m_items) 867 m_items.LockItemsForRead(true);
868
869 foreach (TaskInventoryItem item in m_items.Values)
732 { 870 {
733 foreach (TaskInventoryItem item in m_items.Values) 871 if (item.Name == name)
734 { 872 items.Add(item);
735 if (item.Name == name)
736 items.Add(item);
737 }
738 } 873 }
739 874
875 m_items.LockItemsForRead(false);
876
740 return items; 877 return items;
741 } 878 }
742 879
743 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist) 880 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
744 { 881 {
745 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 882 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
746 883
@@ -751,18 +888,21 @@ namespace OpenSim.Region.Framework.Scenes
751 item.AssetID, item.Name, m_part.Name); 888 item.AssetID, item.Name, m_part.Name);
752 objlist = null; 889 objlist = null;
753 veclist = null; 890 veclist = null;
891 bbox = Vector3.Zero;
892 offsetHeight = 0;
754 return false; 893 return false;
755 } 894 }
756 895
757 Vector3 bbox; 896 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
758 float offsetHeight;
759
760 m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
761 897
762 for (int i = 0; i < objlist.Count; i++) 898 for (int i = 0; i < objlist.Count; i++)
763 { 899 {
764 SceneObjectGroup group = objlist[i]; 900 SceneObjectGroup group = objlist[i];
765 901/*
902 group.RootPart.AttachPoint = group.RootPart.Shape.State;
903 group.RootPart.AttachedPos = group.AbsolutePosition;
904 group.RootPart.AttachRotation = group.GroupRotation;
905*/
766 group.ResetIDs(); 906 group.ResetIDs();
767 907
768 SceneObjectPart rootPart = group.GetPart(group.UUID); 908 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -771,12 +911,14 @@ namespace OpenSim.Region.Framework.Scenes
771 // in the serialization, transfer the correct name from the inventory to the 911 // in the serialization, transfer the correct name from the inventory to the
772 // object itself before we rez. 912 // object itself before we rez.
773 // Only do these for the first object if we are rezzing a coalescence. 913 // Only do these for the first object if we are rezzing a coalescence.
774 if (i == 0) 914 // nahh dont mess with coalescence objects,
915 // the name in inventory can be change for inventory purpuses only
916 if (objlist.Count == 1)
775 { 917 {
776 rootPart.Name = item.Name; 918 rootPart.Name = item.Name;
777 rootPart.Description = item.Description; 919 rootPart.Description = item.Description;
778 } 920 }
779 921/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed
780 group.SetGroup(m_part.GroupID, null); 922 group.SetGroup(m_part.GroupID, null);
781 923
782 foreach (SceneObjectPart part in group.Parts) 924 foreach (SceneObjectPart part in group.Parts)
@@ -792,7 +934,49 @@ namespace OpenSim.Region.Framework.Scenes
792 934
793 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); 935 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
794 } 936 }
937*/
938// old code start
939 SceneObjectPart[] partList = group.Parts;
940
941 group.SetGroup(m_part.GroupID, null);
942
943 // TODO: Remove magic number badness
944 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
945 {
946 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
947 {
948 foreach (SceneObjectPart part in partList)
949 {
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
951 part.EveryoneMask = item.EveryonePermissions;
952 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
953 part.NextOwnerMask = item.NextPermissions;
954 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
955 part.GroupMask = item.GroupPermissions;
956 }
957
958 group.ApplyNextOwnerPermissions();
959 }
960 }
961
962 foreach (SceneObjectPart part in partList)
963 {
964 // TODO: Remove magic number badness
965 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
966 {
967 part.LastOwnerID = part.OwnerID;
968 part.OwnerID = item.OwnerID;
969 part.Inventory.ChangeInventoryOwner(item.OwnerID);
970 }
795 971
972 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
973 part.EveryoneMask = item.EveryonePermissions;
974 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
975 part.NextOwnerMask = item.NextPermissions;
976 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
977 part.GroupMask = item.GroupPermissions;
978 }
979// old code end
796 rootPart.TrimPermissions(); 980 rootPart.TrimPermissions();
797 } 981 }
798 982
@@ -817,8 +1001,9 @@ namespace OpenSim.Region.Framework.Scenes
817 1001
818 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 1002 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
819 { 1003 {
820 TaskInventoryItem it = GetInventoryItem(item.ItemID); 1004 m_items.LockItemsForWrite(true);
821 if (it != null) 1005
1006 if (m_items.ContainsKey(item.ItemID))
822 { 1007 {
823// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 1008// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
824 1009
@@ -831,14 +1016,10 @@ namespace OpenSim.Region.Framework.Scenes
831 item.GroupID = m_part.GroupID; 1016 item.GroupID = m_part.GroupID;
832 1017
833 if (item.AssetID == UUID.Zero) 1018 if (item.AssetID == UUID.Zero)
834 item.AssetID = it.AssetID; 1019 item.AssetID = m_items[item.ItemID].AssetID;
835 1020
836 lock (m_items) 1021 m_items[item.ItemID] = item;
837 { 1022 m_inventorySerial++;
838 m_items[item.ItemID] = item;
839 m_inventorySerial++;
840 }
841
842 if (fireScriptEvents) 1023 if (fireScriptEvents)
843 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1024 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
844 1025
@@ -847,7 +1028,7 @@ namespace OpenSim.Region.Framework.Scenes
847 HasInventoryChanged = true; 1028 HasInventoryChanged = true;
848 m_part.ParentGroup.HasGroupChanged = true; 1029 m_part.ParentGroup.HasGroupChanged = true;
849 } 1030 }
850 1031 m_items.LockItemsForWrite(false);
851 return true; 1032 return true;
852 } 1033 }
853 else 1034 else
@@ -858,8 +1039,9 @@ namespace OpenSim.Region.Framework.Scenes
858 item.ItemID, m_part.Name, m_part.UUID, 1039 item.ItemID, m_part.Name, m_part.UUID,
859 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 1040 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
860 } 1041 }
861 return false; 1042 m_items.LockItemsForWrite(false);
862 1043
1044 return false;
863 } 1045 }
864 1046
865 /// <summary> 1047 /// <summary>
@@ -870,160 +1052,182 @@ namespace OpenSim.Region.Framework.Scenes
870 /// in this prim's inventory.</returns> 1052 /// in this prim's inventory.</returns>
871 public int RemoveInventoryItem(UUID itemID) 1053 public int RemoveInventoryItem(UUID itemID)
872 { 1054 {
873 TaskInventoryItem item = GetInventoryItem(itemID); 1055 m_items.LockItemsForRead(true);
874 if (item != null) 1056
1057 if (m_items.ContainsKey(itemID))
875 { 1058 {
876 int type = m_items[itemID].InvType; 1059 int type = m_items[itemID].InvType;
1060 m_items.LockItemsForRead(false);
877 if (type == 10) // Script 1061 if (type == 10) // Script
878 { 1062 {
879 // route it through here, to handle script cleanup tasks 1063 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
880 RemoveScriptInstance(itemID, false);
881 } 1064 }
1065 m_items.LockItemsForWrite(true);
882 m_items.Remove(itemID); 1066 m_items.Remove(itemID);
1067 m_items.LockItemsForWrite(false);
883 m_inventorySerial++; 1068 m_inventorySerial++;
884 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1069 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
885 1070
886 HasInventoryChanged = true; 1071 HasInventoryChanged = true;
887 m_part.ParentGroup.HasGroupChanged = true; 1072 m_part.ParentGroup.HasGroupChanged = true;
888 1073
889 if (!ContainsScripts()) 1074 int scriptcount = 0;
1075 m_items.LockItemsForRead(true);
1076 foreach (TaskInventoryItem item in m_items.Values)
1077 {
1078 if (item.Type == 10)
1079 {
1080 scriptcount++;
1081 }
1082 }
1083 m_items.LockItemsForRead(false);
1084
1085
1086 if (scriptcount <= 0)
1087 {
890 m_part.RemFlag(PrimFlags.Scripted); 1088 m_part.RemFlag(PrimFlags.Scripted);
1089 }
891 1090
892 m_part.ScheduleFullUpdate(); 1091 m_part.ScheduleFullUpdate();
893 1092
894 return type; 1093 return type;
895
896 } 1094 }
897 else 1095 else
898 { 1096 {
1097 m_items.LockItemsForRead(false);
899 m_log.ErrorFormat( 1098 m_log.ErrorFormat(
900 "[PRIM INVENTORY]: " + 1099 "[PRIM INVENTORY]: " +
901 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 1100 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
902 itemID, m_part.Name, m_part.UUID, 1101 itemID, m_part.Name, m_part.UUID);
903 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
904 } 1102 }
905 1103
906 return -1; 1104 return -1;
907 } 1105 }
908 1106
909 private bool CreateInventoryFile() 1107
1108 /// <summary>
1109 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1110 /// </summary>
1111 /// <param name="xferManager"></param>
1112 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
910 { 1113 {
911// m_log.DebugFormat(
912// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
913// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial);
914 1114
915 if (m_inventoryFileName == String.Empty || 1115 lock (m_inventoryFileLock)
916 m_inventoryFileNameSerial < m_inventorySerial)
917 { 1116 {
918 // Something changed, we need to create a new file 1117 string filename = "inventory_" + UUID.Random().ToString() + ".tmp";
919 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
920 m_inventoryFileNameSerial = m_inventorySerial;
921
922 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
923 1118
924 lock (m_items) 1119 bool changed = false;
1120 if (m_inventoryFileNameSerial < m_inventorySerial)
925 { 1121 {
926 foreach (TaskInventoryItem item in m_items.Values) 1122 m_inventoryFileNameSerial = m_inventorySerial;
927 { 1123 changed = true;
928// m_log.DebugFormat( 1124 }
929// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}",
930// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
931
932 UUID ownerID = item.OwnerID;
933 uint everyoneMask = 0;
934 uint baseMask = item.BasePermissions;
935 uint ownerMask = item.CurrentPermissions;
936 uint groupMask = item.GroupPermissions;
937 1125
938 invString.AddItemStart(); 1126 if (m_inventoryFileData.Length < 2)
939 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 1127 changed = true;
940 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
941 1128
942 invString.AddPermissionsStart(); 1129 bool includeAssets = false;
1130 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1131 includeAssets = true;
943 1132
944 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1133 if (m_inventoryPrivileged != includeAssets)
945 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1134 changed = true;
946 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
947 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
948 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
949 1135
950 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
951 invString.AddNameValueLine("owner_id", ownerID.ToString());
952 1136
953 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1137 Items.LockItemsForRead(true);
954 1138
955 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1139 if (m_inventorySerial == 0) // No inventory
956 invString.AddSectionEnd(); 1140 {
1141 Items.LockItemsForRead(false);
1142 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1143
1144 return;
1145 }
957 1146
958 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1147 if (m_items.Count == 0) // No inventory
959 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); 1148 {
960 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); 1149 Items.LockItemsForRead(false);
961 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 1150 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1151 return;
1152 }
962 1153
963 invString.AddSaleStart(); 1154 if (!changed)
964 invString.AddNameValueLine("sale_type", "not"); 1155 {
965 invString.AddNameValueLine("sale_price", "0"); 1156 Items.LockItemsForRead(false);
966 invString.AddSectionEnd();
967 1157
968 invString.AddNameValueLine("name", item.Name + "|"); 1158 xferManager.AddNewFile(filename,
969 invString.AddNameValueLine("desc", item.Description + "|"); 1159 m_inventoryFileData);
1160 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1161 Util.StringToBytes256(filename));
970 1162
971 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1163 return;
972 invString.AddSectionEnd();
973 }
974 } 1164 }
975 1165
976 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1166 m_inventoryPrivileged = includeAssets;
977 1167
978 return true; 1168 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
979 }
980
981 // No need to recreate, the existing file is fine
982 return false;
983 }
984 1169
985 /// <summary> 1170 foreach (TaskInventoryItem item in m_items.Values)
986 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
987 /// </summary>
988 /// <param name="xferManager"></param>
989 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
990 {
991 lock (m_items)
992 {
993 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
994 // a new script if any previous deletion has left the prim inventory empty.
995 if (m_items.Count == 0) // No inventory
996 { 1171 {
997// m_log.DebugFormat( 1172 UUID ownerID = item.OwnerID;
998// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items", 1173 uint everyoneMask = 0;
999// m_part.Name, m_part.LocalId, m_part.UUID, client.Name); 1174 uint baseMask = item.BasePermissions;
1175 uint ownerMask = item.CurrentPermissions;
1176 uint groupMask = item.GroupPermissions;
1000 1177
1001 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1178 invString.AddItemStart();
1002 return; 1179 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1180 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1181
1182 invString.AddPermissionsStart();
1183
1184 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1185 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1186 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1187 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1188 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1189
1190 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1191 invString.AddNameValueLine("owner_id", ownerID.ToString());
1192
1193 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1194
1195 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1196 invString.AddSectionEnd();
1197
1198 if (includeAssets)
1199 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1200 else
1201 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1202 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1203 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1204 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1205
1206 invString.AddSaleStart();
1207 invString.AddNameValueLine("sale_type", "not");
1208 invString.AddNameValueLine("sale_price", "0");
1209 invString.AddSectionEnd();
1210
1211 invString.AddNameValueLine("name", item.Name + "|");
1212 invString.AddNameValueLine("desc", item.Description + "|");
1213
1214 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1215 invString.AddSectionEnd();
1003 } 1216 }
1004 1217
1005 CreateInventoryFile(); 1218 Items.LockItemsForRead(false);
1006 1219
1007 // In principle, we should only do the rest if the inventory changed; 1220 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
1008 // by sending m_inventorySerial to the client, it ought to know 1221
1009 // that nothing changed and that it doesn't need to request the file.
1010 // Unfortunately, it doesn't look like the client optimizes this;
1011 // the client seems to always come back and request the Xfer,
1012 // no matter what value m_inventorySerial has.
1013 // FIXME: Could probably be > 0 here rather than > 2
1014 if (m_inventoryFileData.Length > 2) 1222 if (m_inventoryFileData.Length > 2)
1015 { 1223 {
1016 // Add the file for Xfer 1224 xferManager.AddNewFile(filename, m_inventoryFileData);
1017 // m_log.DebugFormat( 1225 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1018 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", 1226 Util.StringToBytes256(filename));
1019 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); 1227 return;
1020
1021 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1022 } 1228 }
1023 1229
1024 // Tell the client we're ready to Xfer the file 1230 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1025 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1026 Util.StringToBytes256(m_inventoryFileName));
1027 } 1231 }
1028 } 1232 }
1029 1233
@@ -1033,13 +1237,26 @@ namespace OpenSim.Region.Framework.Scenes
1033 /// <param name="datastore"></param> 1237 /// <param name="datastore"></param>
1034 public void ProcessInventoryBackup(ISimulationDataService datastore) 1238 public void ProcessInventoryBackup(ISimulationDataService datastore)
1035 { 1239 {
1036 if (HasInventoryChanged) 1240// Removed this because linking will cause an immediate delete of the new
1037 { 1241// child prim from the database and the subsequent storing of the prim sees
1242// the inventory of it as unchanged and doesn't store it at all. The overhead
1243// of storing prim inventory needlessly is much less than the aggravation
1244// of prim inventory loss.
1245// if (HasInventoryChanged)
1246// {
1247 Items.LockItemsForRead(true);
1248 try
1249 {
1250 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1251 }
1252 catch {}
1253
1038 HasInventoryChanged = false; 1254 HasInventoryChanged = false;
1039 List<TaskInventoryItem> items = GetInventoryItems();
1040 datastore.StorePrimInventory(m_part.UUID, items);
1041 1255
1042 } 1256 Items.LockItemsForRead(false);
1257
1258
1259// }
1043 } 1260 }
1044 1261
1045 public class InventoryStringBuilder 1262 public class InventoryStringBuilder
@@ -1105,65 +1322,63 @@ namespace OpenSim.Region.Framework.Scenes
1105 { 1322 {
1106 uint mask=0x7fffffff; 1323 uint mask=0x7fffffff;
1107 1324
1108 lock (m_items) 1325 foreach (TaskInventoryItem item in m_items.Values)
1109 { 1326 {
1110 foreach (TaskInventoryItem item in m_items.Values) 1327 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1328 mask &= ~((uint)PermissionMask.Copy >> 13);
1329 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1330 mask &= ~((uint)PermissionMask.Transfer >> 13);
1331 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1332 mask &= ~((uint)PermissionMask.Modify >> 13);
1333
1334 if (item.InvType == (int)InventoryType.Object)
1111 { 1335 {
1112 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1336 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1113 mask &= ~((uint)PermissionMask.Copy >> 13); 1337 mask &= ~((uint)PermissionMask.Copy >> 13);
1114 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1338 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1115 mask &= ~((uint)PermissionMask.Transfer >> 13); 1339 mask &= ~((uint)PermissionMask.Transfer >> 13);
1116 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1340 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1117 mask &= ~((uint)PermissionMask.Modify >> 13); 1341 mask &= ~((uint)PermissionMask.Modify >> 13);
1118
1119 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1120 mask &= ~(uint)PermissionMask.Copy;
1121 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1122 mask &= ~(uint)PermissionMask.Transfer;
1123 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1124 mask &= ~(uint)PermissionMask.Modify;
1125 } 1342 }
1343
1344 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1345 mask &= ~(uint)PermissionMask.Copy;
1346 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1347 mask &= ~(uint)PermissionMask.Transfer;
1348 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1349 mask &= ~(uint)PermissionMask.Modify;
1126 } 1350 }
1127
1128 return mask; 1351 return mask;
1129 } 1352 }
1130 1353
1131 public void ApplyNextOwnerPermissions() 1354 public void ApplyNextOwnerPermissions()
1132 { 1355 {
1133 lock (m_items) 1356 foreach (TaskInventoryItem item in m_items.Values)
1134 { 1357 {
1135 foreach (TaskInventoryItem item in m_items.Values) 1358 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1136 { 1359 {
1137// m_log.DebugFormat ( 1360 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1138// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", 1361 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1139// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1362 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1140 1363 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1141 if (item.InvType == (int)InventoryType.Object) 1364 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1142 { 1365 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1143 uint perms = item.CurrentPermissions;
1144 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
1145 item.CurrentPermissions = perms;
1146 }
1147
1148 item.CurrentPermissions &= item.NextPermissions;
1149 item.BasePermissions &= item.NextPermissions;
1150 item.EveryonePermissions &= item.NextPermissions;
1151 item.OwnerChanged = true;
1152 item.PermsMask = 0;
1153 item.PermsGranter = UUID.Zero;
1154 } 1366 }
1367 item.CurrentPermissions &= item.NextPermissions;
1368 item.BasePermissions &= item.NextPermissions;
1369 item.EveryonePermissions &= item.NextPermissions;
1370 item.OwnerChanged = true;
1371 item.PermsMask = 0;
1372 item.PermsGranter = UUID.Zero;
1155 } 1373 }
1156 } 1374 }
1157 1375
1158 public void ApplyGodPermissions(uint perms) 1376 public void ApplyGodPermissions(uint perms)
1159 { 1377 {
1160 lock (m_items) 1378 foreach (TaskInventoryItem item in m_items.Values)
1161 { 1379 {
1162 foreach (TaskInventoryItem item in m_items.Values) 1380 item.CurrentPermissions = perms;
1163 { 1381 item.BasePermissions = perms;
1164 item.CurrentPermissions = perms;
1165 item.BasePermissions = perms;
1166 }
1167 } 1382 }
1168 1383
1169 m_inventorySerial++; 1384 m_inventorySerial++;
@@ -1176,14 +1391,11 @@ namespace OpenSim.Region.Framework.Scenes
1176 /// <returns></returns> 1391 /// <returns></returns>
1177 public bool ContainsScripts() 1392 public bool ContainsScripts()
1178 { 1393 {
1179 lock (m_items) 1394 foreach (TaskInventoryItem item in m_items.Values)
1180 { 1395 {
1181 foreach (TaskInventoryItem item in m_items.Values) 1396 if (item.InvType == (int)InventoryType.LSL)
1182 { 1397 {
1183 if (item.InvType == (int)InventoryType.LSL) 1398 return true;
1184 {
1185 return true;
1186 }
1187 } 1399 }
1188 } 1400 }
1189 1401
@@ -1197,17 +1409,15 @@ namespace OpenSim.Region.Framework.Scenes
1197 public int ScriptCount() 1409 public int ScriptCount()
1198 { 1410 {
1199 int count = 0; 1411 int count = 0;
1200 lock (m_items) 1412 Items.LockItemsForRead(true);
1413 foreach (TaskInventoryItem item in m_items.Values)
1201 { 1414 {
1202 foreach (TaskInventoryItem item in m_items.Values) 1415 if (item.InvType == (int)InventoryType.LSL)
1203 { 1416 {
1204 if (item.InvType == (int)InventoryType.LSL) 1417 count++;
1205 {
1206 count++;
1207 }
1208 } 1418 }
1209 } 1419 }
1210 1420 Items.LockItemsForRead(false);
1211 return count; 1421 return count;
1212 } 1422 }
1213 /// <summary> 1423 /// <summary>
@@ -1243,11 +1453,8 @@ namespace OpenSim.Region.Framework.Scenes
1243 { 1453 {
1244 List<UUID> ret = new List<UUID>(); 1454 List<UUID> ret = new List<UUID>();
1245 1455
1246 lock (m_items) 1456 foreach (TaskInventoryItem item in m_items.Values)
1247 { 1457 ret.Add(item.ItemID);
1248 foreach (TaskInventoryItem item in m_items.Values)
1249 ret.Add(item.ItemID);
1250 }
1251 1458
1252 return ret; 1459 return ret;
1253 } 1460 }
@@ -1256,8 +1463,9 @@ namespace OpenSim.Region.Framework.Scenes
1256 { 1463 {
1257 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1464 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1258 1465
1259 lock (m_items) 1466 Items.LockItemsForRead(true);
1260 ret = new List<TaskInventoryItem>(m_items.Values); 1467 ret = new List<TaskInventoryItem>(m_items.Values);
1468 Items.LockItemsForRead(false);
1261 1469
1262 return ret; 1470 return ret;
1263 } 1471 }
@@ -1266,18 +1474,24 @@ namespace OpenSim.Region.Framework.Scenes
1266 { 1474 {
1267 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1475 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1268 1476
1269 lock (m_items) 1477 Items.LockItemsForRead(true);
1270 { 1478
1271 foreach (TaskInventoryItem item in m_items.Values) 1479 foreach (TaskInventoryItem item in m_items.Values)
1272 if (item.InvType == (int)type) 1480 if (item.InvType == (int)type)
1273 ret.Add(item); 1481 ret.Add(item);
1274 } 1482
1483 Items.LockItemsForRead(false);
1275 1484
1276 return ret; 1485 return ret;
1277 } 1486 }
1278 1487
1279 public Dictionary<UUID, string> GetScriptStates() 1488 public Dictionary<UUID, string> GetScriptStates()
1280 { 1489 {
1490 return GetScriptStates(false);
1491 }
1492
1493 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1494 {
1281 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1495 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1282 1496
1283 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1497 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1303,14 +1517,21 @@ namespace OpenSim.Region.Framework.Scenes
1303 string n = e.GetXMLState(item.ItemID); 1517 string n = e.GetXMLState(item.ItemID);
1304 if (n != String.Empty) 1518 if (n != String.Empty)
1305 { 1519 {
1306 if (!ret.ContainsKey(item.ItemID)) 1520 if (oldIDs)
1307 ret[item.ItemID] = n; 1521 {
1522 if (!ret.ContainsKey(item.OldItemID))
1523 ret[item.OldItemID] = n;
1524 }
1525 else
1526 {
1527 if (!ret.ContainsKey(item.ItemID))
1528 ret[item.ItemID] = n;
1529 }
1308 break; 1530 break;
1309 } 1531 }
1310 } 1532 }
1311 } 1533 }
1312 } 1534 }
1313
1314 return ret; 1535 return ret;
1315 } 1536 }
1316 1537
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1fddd91..29362d7 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -90,7 +90,17 @@ namespace OpenSim.Region.Framework.Scenes
90 m_scene.EventManager.TriggerScenePresenceUpdated(this); 90 m_scene.EventManager.TriggerScenePresenceUpdated(this);
91 } 91 }
92 92
93 public PresenceType PresenceType { get; private set; } 93 public bool isNPC { get; private set; }
94
95 private PresenceType m_presenceType;
96 public PresenceType PresenceType {
97 get {return m_presenceType;}
98 private set
99 {
100 m_presenceType = value;
101 isNPC = (m_presenceType == PresenceType.Npc);
102 }
103 }
94 104
95 private ScenePresenceStateMachine m_stateMachine; 105 private ScenePresenceStateMachine m_stateMachine;
96 106
@@ -142,13 +152,100 @@ namespace OpenSim.Region.Framework.Scenes
142 /// </summary> 152 /// </summary>
143 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 153 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f;
144 154
145 public UUID currentParcelUUID = UUID.Zero; 155 private UUID m_previusParcelUUID = UUID.Zero;
156 private UUID m_currentParcelUUID = UUID.Zero;
157 private bool m_previusParcelHide = false;
158 private bool m_currentParcelHide = false;
159 private object parcelLock = new Object();
160
161 public UUID currentParcelUUID
162 {
163 get { return m_currentParcelUUID; }
164 set
165 {
166 lock (parcelLock)
167 {
168 bool oldhide = m_currentParcelHide;
169 bool checksame = true;
170 if (value != m_currentParcelUUID)
171 {
172 m_previusParcelHide = m_currentParcelHide;
173 m_previusParcelUUID = m_currentParcelUUID;
174 checksame = false;
175 }
176 m_currentParcelUUID = value;
177 m_currentParcelHide = false;
178
179 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
180 if (land != null && !land.LandData.SeeAVs)
181 m_currentParcelHide = true;
182
183 if (m_previusParcelUUID != UUID.Zero || checksame)
184 ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
185 }
186 }
187 }
188
189 public void sitSOGmoved()
190 {
191 if (IsDeleted || !IsSatOnObject)
192 //what me? nahh
193 return;
194 if (IsInTransit)
195 return;
196
197 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
198 if (land == null)
199 return; //??
200 UUID parcelID = land.LandData.GlobalID;
201 if (m_currentParcelUUID != parcelID)
202 currentParcelUUID = parcelID;
203 }
204
205
206 public bool ParcelAllowThisAvatarSounds
207 {
208 get
209 {
210 try
211 {
212 lock (parcelLock)
213 {
214 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
215 if (land == null)
216 return true;
217 if (land.LandData.AnyAVSounds)
218 return true;
219 if (!land.LandData.GroupAVSounds)
220 return false;
221 return land.LandData.GroupID == ControllingClient.ActiveGroupId;
222 }
223 }
224 catch
225 {
226 return true;
227 }
228 }
229 }
146 230
231 public bool ParcelHideThisAvatar
232 {
233 get
234 {
235 return m_currentParcelHide;
236 }
237 }
238
147 /// <value> 239 /// <value>
148 /// The animator for this avatar 240 /// The animator for this avatar
149 /// </value> 241 /// </value>
150 public ScenePresenceAnimator Animator { get; private set; } 242 public ScenePresenceAnimator Animator { get; private set; }
151 243
244 /// <value>
245 /// Server Side Animation Override
246 /// </value>
247 public MovementAnimationOverrides Overrides { get; private set; }
248 public String sitAnimation = "SIT";
152 /// <summary> 249 /// <summary>
153 /// Attachments recorded on this avatar. 250 /// Attachments recorded on this avatar.
154 /// </summary> 251 /// </summary>
@@ -192,14 +289,7 @@ namespace OpenSim.Region.Framework.Scenes
192 set { PhysicsActor.Flying = value; } 289 set { PhysicsActor.Flying = value; }
193 } 290 }
194 291
195 // add for fly velocity control 292 public bool IsColliding
196 private bool FlyingOld {get; set;}
197 public bool WasFlying
198 {
199 get; private set;
200 }
201
202 public bool IsColliding
203 { 293 {
204 get { return PhysicsActor != null && PhysicsActor.IsColliding; } 294 get { return PhysicsActor != null && PhysicsActor.IsColliding; }
205 // We would expect setting IsColliding to be private but it's used by a hack in Scene 295 // We would expect setting IsColliding to be private but it's used by a hack in Scene
@@ -209,6 +299,7 @@ namespace OpenSim.Region.Framework.Scenes
209// private int m_lastColCount = -1; //KF: Look for Collision chnages 299// private int m_lastColCount = -1; //KF: Look for Collision chnages
210// private int m_updateCount = 0; //KF: Update Anims for a while 300// private int m_updateCount = 0; //KF: Update Anims for a while
211// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 301// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
302 private List<uint> m_lastColliders = new List<uint>();
212 303
213 private TeleportFlags m_teleportFlags; 304 private TeleportFlags m_teleportFlags;
214 public TeleportFlags TeleportFlags 305 public TeleportFlags TeleportFlags
@@ -247,7 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
247 338
248 protected ulong crossingFromRegion; 339 protected ulong crossingFromRegion;
249 340
250 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 341 private readonly Vector3[] Dir_Vectors = new Vector3[12];
251 342
252 protected Timer m_reprioritization_timer; 343 protected Timer m_reprioritization_timer;
253 protected bool m_reprioritizing; 344 protected bool m_reprioritizing;
@@ -271,6 +362,9 @@ namespace OpenSim.Region.Framework.Scenes
271 //private int m_moveToPositionStateStatus; 362 //private int m_moveToPositionStateStatus;
272 //***************************************************** 363 //*****************************************************
273 364
365 private bool m_collisionEventFlag = false;
366 private object m_collisionEventLock = new Object();
367
274 private int m_movementAnimationUpdateCounter = 0; 368 private int m_movementAnimationUpdateCounter = 0;
275 369
276 public Vector3 PrevSitOffset { get; set; } 370 public Vector3 PrevSitOffset { get; set; }
@@ -287,7 +381,6 @@ namespace OpenSim.Region.Framework.Scenes
287 } 381 }
288 } 382 }
289 383
290 public bool SentInitialDataToClient { get; private set; }
291 384
292 /// <summary> 385 /// <summary>
293 /// Copy of the script states while the agent is in transit. This state may 386 /// Copy of the script states while the agent is in transit. This state may
@@ -303,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes
303 /// <summary> 396 /// <summary>
304 /// Implemented Control Flags 397 /// Implemented Control Flags
305 /// </summary> 398 /// </summary>
306 private enum Dir_ControlFlags 399 private enum Dir_ControlFlags:uint
307 { 400 {
308 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, 401 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
309 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, 402 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
@@ -315,6 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
315 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 408 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
316 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, 409 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
317 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, 410 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
411 DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS,
318 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 412 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
319 } 413 }
320 414
@@ -347,12 +441,6 @@ namespace OpenSim.Region.Framework.Scenes
347 private object m_originRegionIDAccessLock = new object(); 441 private object m_originRegionIDAccessLock = new object();
348 442
349 /// <summary> 443 /// <summary>
350 /// Triggered on entity transfer after to allow CompleteMovement() to proceed after we have received an
351 /// UpdateAgent from the originating region.ddkjjkj
352 /// </summary>
353 private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false);
354
355 /// <summary>
356 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent 444 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
357 /// teleport is reusing the connection. 445 /// teleport is reusing the connection.
358 /// </summary> 446 /// </summary>
@@ -379,11 +467,6 @@ namespace OpenSim.Region.Framework.Scenes
379 public uint MovementFlag { get; private set; } 467 public uint MovementFlag { get; private set; }
380 468
381 /// <summary> 469 /// <summary>
382 /// Set this if we need to force a movement update on the next received AgentUpdate from the viewer.
383 /// </summary>
384 private const uint ForceUpdateMovementFlagValue = uint.MaxValue;
385
386 /// <summary>
387 /// Is the agent stop control flag currently active? 470 /// Is the agent stop control flag currently active?
388 /// </summary> 471 /// </summary>
389 public bool AgentControlStopActive { get; private set; } 472 public bool AgentControlStopActive { get; private set; }
@@ -413,11 +496,18 @@ namespace OpenSim.Region.Framework.Scenes
413 } 496 }
414 497
415 private ulong m_rootRegionHandle; 498 private ulong m_rootRegionHandle;
499 private Vector3 m_rootRegionPosition = new Vector3();
416 500
417 public ulong RegionHandle 501 public ulong RegionHandle
418 { 502 {
419 get { return m_rootRegionHandle; } 503 get { return m_rootRegionHandle; }
420 private set { m_rootRegionHandle = value; } 504 private set
505 {
506 m_rootRegionHandle = value;
507 // position rounded to lower multiple of 256m
508 m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
509 m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
510 }
421 } 511 }
422 512
423 #region Client Camera 513 #region Client Camera
@@ -449,11 +539,8 @@ namespace OpenSim.Region.Framework.Scenes
449 get 539 get
450 { 540 {
451 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 541 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
452 542 a.Normalize();
453 if (a == Vector3.Zero) 543 return a;
454 return a;
455
456 return Util.GetNormalizedVector(a);
457 } 544 }
458 } 545 }
459 #endregion 546 #endregion
@@ -505,6 +592,7 @@ namespace OpenSim.Region.Framework.Scenes
505 } 592 }
506 } 593 }
507 594
595
508 public byte State { get; set; } 596 public byte State { get; set; }
509 597
510 private AgentManager.ControlFlags m_AgentControlFlags; 598 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -557,10 +645,14 @@ namespace OpenSim.Region.Framework.Scenes
557 // in the sim unless the avatar is on a sit target. While 645 // in the sim unless the avatar is on a sit target. While
558 // on a sit target, m_pos will contain the desired offset 646 // on a sit target, m_pos will contain the desired offset
559 // without the parent rotation applied. 647 // without the parent rotation applied.
560 SceneObjectPart sitPart = ParentPart; 648 if (ParentPart != null)
561 649 {
562 if (sitPart != null) 650 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
563 return sitPart.ParentGroup.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 651 // if (sitPart != null)
652 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
653 if (rootPart != null)
654 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
655 }
564 } 656 }
565 657
566 return m_pos; 658 return m_pos;
@@ -614,11 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
614 } 706 }
615 707
616 /// <summary> 708 /// <summary>
617 /// Velocity of the avatar with respect to its local reference frame. 709 /// Current velocity of the avatar.
618 /// </summary> 710 /// </summary>
619 /// <remarks>
620 /// So when sat on a vehicle this will be 0. To get velocity with respect to the world use GetWorldVelocity()
621 /// </remarks>
622 public override Vector3 Velocity 711 public override Vector3 Velocity
623 { 712 {
624 get 713 get
@@ -631,21 +720,12 @@ namespace OpenSim.Region.Framework.Scenes
631// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", 720// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
632// m_velocity, Name, Scene.RegionInfo.RegionName); 721// m_velocity, Name, Scene.RegionInfo.RegionName);
633 } 722 }
634// else if (ParentPart != null)
635// {
636// return ParentPart.ParentGroup.Velocity;
637// }
638 723
639 return m_velocity; 724 return m_velocity;
640 } 725 }
641 726
642 set 727 set
643 { 728 {
644// Util.PrintCallStack();
645// m_log.DebugFormat(
646// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
647// Scene.RegionInfo.RegionName, Name, value);
648
649 if (PhysicsActor != null) 729 if (PhysicsActor != null)
650 { 730 {
651 try 731 try
@@ -658,27 +738,14 @@ namespace OpenSim.Region.Framework.Scenes
658 } 738 }
659 } 739 }
660 740
661 m_velocity = value; 741 m_velocity = value;
662 }
663 }
664/*
665 public override Vector3 AngularVelocity
666 {
667 get
668 {
669 if (PhysicsActor != null)
670 {
671 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
672
673 // m_log.DebugFormat(
674 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
675 // m_velocity, Name, Scene.RegionInfo.RegionName);
676 }
677 742
678 return m_rotationalvelocity; 743// m_log.DebugFormat(
744// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
745// Scene.RegionInfo.RegionName, Name, m_velocity);
679 } 746 }
680 } 747 }
681*/ 748
682 private Quaternion m_bodyRot = Quaternion.Identity; 749 private Quaternion m_bodyRot = Quaternion.Identity;
683 750
684 /// <summary> 751 /// <summary>
@@ -759,15 +826,21 @@ namespace OpenSim.Region.Framework.Scenes
759 } 826 }
760 827
761 /// <summary> 828 /// <summary>
762 /// Get rotation relative to the world. 829 /// Gets the world rotation of this presence.
763 /// </summary> 830 /// </summary>
831 /// <remarks>
832 /// Unlike Rotation, this returns the world rotation no matter whether the avatar is sitting on a prim or not.
833 /// </remarks>
764 /// <returns></returns> 834 /// <returns></returns>
765 public Quaternion GetWorldRotation() 835 public Quaternion GetWorldRotation()
766 { 836 {
767 SceneObjectPart sitPart = ParentPart; 837 if (IsSatOnObject)
838 {
839 SceneObjectPart sitPart = ParentPart;
768 840
769 if (sitPart != null) 841 if (sitPart != null)
770 return sitPart.GetWorldRotation() * Rotation; 842 return sitPart.GetWorldRotation() * Rotation;
843 }
771 844
772 return Rotation; 845 return Rotation;
773 } 846 }
@@ -794,22 +867,23 @@ namespace OpenSim.Region.Framework.Scenes
794 else 867 else
795 seeds = new Dictionary<ulong, string>(); 868 seeds = new Dictionary<ulong, string>();
796 869
870/* we can't do this anymore
797 List<ulong> old = new List<ulong>(); 871 List<ulong> old = new List<ulong>();
798 foreach (ulong handle in seeds.Keys) 872 foreach (ulong handle in seeds.Keys)
799 { 873 {
800 uint x, y; 874 uint x, y;
801 Util.RegionHandleToRegionLoc(handle, out x, out y); 875 Util.RegionHandleToRegionLoc(handle, out x, out y);
802 876// if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY,))
803 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
804 { 877 {
805 old.Add(handle); 878 old.Add(handle);
806 } 879 }
807 } 880 }
881
808 DropOldNeighbours(old); 882 DropOldNeighbours(old);
809 883
810 if (Scene.CapsModule != null) 884 if (Scene.CapsModule != null)
811 Scene.CapsModule.SetChildrenSeed(UUID, seeds); 885 Scene.CapsModule.SetChildrenSeed(UUID, seeds);
812 886*/
813 KnownRegions = seeds; 887 KnownRegions = seeds;
814 //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); 888 //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
815 //DumpKnownRegions(); 889 //DumpKnownRegions();
@@ -827,7 +901,7 @@ namespace OpenSim.Region.Framework.Scenes
827 } 901 }
828 902
829 private bool m_mouseLook; 903 private bool m_mouseLook;
830// private bool m_leftButtonDown; 904 private bool m_leftButtonDown;
831 905
832 private bool m_inTransit; 906 private bool m_inTransit;
833 907
@@ -852,13 +926,6 @@ namespace OpenSim.Region.Framework.Scenes
852 } 926 }
853 } 927 }
854 928
855 private float m_speedModifier = 1.0f;
856
857 public float SpeedModifier
858 {
859 get { return m_speedModifier; }
860 set { m_speedModifier = value; }
861 }
862 929
863 /// <summary> 930 /// <summary>
864 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running 931 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
@@ -866,7 +933,20 @@ namespace OpenSim.Region.Framework.Scenes
866 /// <remarks> 933 /// <remarks>
867 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. 934 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
868 /// </remarks> 935 /// </remarks>
869 private float AgentControlStopSlowWhilstMoving = 0.5f; 936 private const float AgentControlStopSlowVel = 0.2f;
937 // velocities
938 public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
939 public const float AgentControlNormalVel = 1.0f;
940
941 // old normal speed was tuned to match sl normal plus Fast modifiers
942 // so we need to rescale it
943 private float m_speedModifier = 1.0f;
944
945 public float SpeedModifier
946 {
947 get { return m_speedModifier; }
948 set { m_speedModifier = value; }
949 }
870 950
871 private bool m_forceFly; 951 private bool m_forceFly;
872 952
@@ -888,12 +968,7 @@ namespace OpenSim.Region.Framework.Scenes
888 { 968 {
889 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } 969 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); }
890 } 970 }
891 971
892 /// <summary>
893 /// Count of how many terse updates we have sent out. It doesn't matter if this overflows.
894 /// </summary>
895 private int m_terseUpdateCount;
896
897 #endregion 972 #endregion
898 973
899 #region Constructor(s) 974 #region Constructor(s)
@@ -907,9 +982,9 @@ namespace OpenSim.Region.Framework.Scenes
907 IsLoggingIn = false; 982 IsLoggingIn = false;
908 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 983 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
909 Animator = new ScenePresenceAnimator(this); 984 Animator = new ScenePresenceAnimator(this);
985 Overrides = new MovementAnimationOverrides();
910 PresenceType = type; 986 PresenceType = type;
911 // DrawDistance = world.DefaultDrawDistance; 987 DrawDistance = world.DefaultDrawDistance;
912 DrawDistance = Constants.RegionSize;
913 RegionHandle = world.RegionInfo.RegionHandle; 988 RegionHandle = world.RegionInfo.RegionHandle;
914 ControllingClient = client; 989 ControllingClient = client;
915 Firstname = ControllingClient.FirstName; 990 Firstname = ControllingClient.FirstName;
@@ -930,7 +1005,7 @@ namespace OpenSim.Region.Framework.Scenes
930 1005
931 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1006 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
932 if (gm != null) 1007 if (gm != null)
933 Grouptitle = gm.GetGroupTitle(m_uuid); 1008 Grouptitle = gm.GetGroupTitle(m_uuid);
934 1009
935 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 1010 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
936 1011
@@ -988,8 +1063,10 @@ namespace OpenSim.Region.Framework.Scenes
988 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1063 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
989 ControllingClient.OnStartAnim += HandleStartAnim; 1064 ControllingClient.OnStartAnim += HandleStartAnim;
990 ControllingClient.OnStopAnim += HandleStopAnim; 1065 ControllingClient.OnStopAnim += HandleStopAnim;
1066 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
991 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 1067 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
992 ControllingClient.OnAutoPilotGo += MoveToTarget; 1068 ControllingClient.OnAutoPilotGo += MoveToTarget;
1069 ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
993 1070
994 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); 1071 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
995 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); 1072 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
@@ -997,19 +1074,19 @@ namespace OpenSim.Region.Framework.Scenes
997 1074
998 private void SetDirectionVectors() 1075 private void SetDirectionVectors()
999 { 1076 {
1000 Dir_Vectors[0] = Vector3.UnitX; //FORWARD 1077 Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
1001 Dir_Vectors[1] = -Vector3.UnitX; //BACK 1078 Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
1002 Dir_Vectors[2] = Vector3.UnitY; //LEFT 1079 Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
1003 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 1080 Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
1004 Dir_Vectors[4] = Vector3.UnitZ; //UP 1081 Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
1005 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 1082 Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
1006 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE 1083 Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
1007 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE 1084 Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
1008 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE 1085 Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
1009 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE 1086 Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
1010 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1087 Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
1088 Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
1011 } 1089 }
1012
1013 #endregion 1090 #endregion
1014 1091
1015 #region Status Methods 1092 #region Status Methods
@@ -1026,18 +1103,25 @@ namespace OpenSim.Region.Framework.Scenes
1026 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1103 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
1027 /// delays that crossing. 1104 /// delays that crossing.
1028 /// </remarks> 1105 /// </remarks>
1106
1107
1108 // only in use as part of completemovement
1109 // other uses need fix
1029 private bool MakeRootAgent(Vector3 pos, bool isFlying) 1110 private bool MakeRootAgent(Vector3 pos, bool isFlying)
1030 { 1111 {
1112 int ts = Util.EnvironmentTickCount();
1113
1031 lock (m_completeMovementLock) 1114 lock (m_completeMovementLock)
1032 { 1115 {
1033 if (!IsChildAgent) 1116 if (!IsChildAgent)
1034 return false; 1117 return false;
1035 1118
1119 m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1036 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1120 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1037 1121
1038 // m_log.InfoFormat( 1122 // m_log.InfoFormat(
1039 // "[SCENE]: Upgrading child to root agent for {0} in {1}", 1123 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1040 // Name, m_scene.RegionInfo.RegionName); 1124 // Name, m_scene.RegionInfo.RegionName);
1041 1125
1042 if (ParentUUID != UUID.Zero) 1126 if (ParentUUID != UUID.Zero)
1043 { 1127 {
@@ -1046,20 +1130,23 @@ namespace OpenSim.Region.Framework.Scenes
1046 if (part == null) 1130 if (part == null)
1047 { 1131 {
1048 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1132 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1133 ParentID = 0;
1134 ParentPart = null;
1135 PrevSitOffset = Vector3.Zero;
1136 HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1137 IsLoggingIn = false;
1049 } 1138 }
1050 else 1139 else
1051 { 1140 {
1052 part.AddSittingAvatar(this); 1141 part.ParentGroup.AddAvatar(UUID);
1053 // ParentPosition = part.GetWorldPosition(); 1142 if (part.SitTargetPosition != Vector3.Zero)
1143 part.SitTargetAvatar = UUID;
1054 ParentID = part.LocalId; 1144 ParentID = part.LocalId;
1055 ParentPart = part; 1145 ParentPart = part;
1056 m_pos = PrevSitOffset; 1146 m_pos = PrevSitOffset;
1057 // pos = ParentPosition;
1058 pos = part.GetWorldPosition(); 1147 pos = part.GetWorldPosition();
1059 } 1148 }
1060 ParentUUID = UUID.Zero; 1149 ParentUUID = UUID.Zero;
1061
1062 // Animator.TrySetMovementAnimation("SIT");
1063 } 1150 }
1064 else 1151 else
1065 { 1152 {
@@ -1069,82 +1156,36 @@ namespace OpenSim.Region.Framework.Scenes
1069 IsChildAgent = false; 1156 IsChildAgent = false;
1070 } 1157 }
1071 1158
1159 m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1160
1072 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag 1161 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1073 // set and prevent the close of the connection on a subsequent re-teleport. 1162 // set and prevent the close of the connection on a subsequent re-teleport.
1074 // Should not be needed if we are not trying to tell this region to close 1163 // Should not be needed if we are not trying to tell this region to close
1075// DoNotCloseAfterTeleport = false; 1164 // DoNotCloseAfterTeleport = false;
1076 1165
1077 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1166 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1078 if (gm != null) 1167 if (gm != null)
1079 Grouptitle = gm.GetGroupTitle(m_uuid); 1168 Grouptitle = gm.GetGroupTitle(m_uuid);
1080 1169
1081 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode); 1170
1082 uint teleportFlags = (aCircuit == null) ? 0 : aCircuit.teleportFlags; 1171 if ((m_teleportFlags & TeleportFlags.ViaHGLogin) != 0)
1083 if ((teleportFlags & (uint)TeleportFlags.ViaHGLogin) != 0)
1084 { 1172 {
1085 // The avatar is arriving from another grid. This means that we may have changed the 1173 // The avatar is arriving from another grid. This means that we may have changed the
1086 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com"). 1174 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com").
1087 // Unfortunately, due to a viewer bug, viewers don't always show the new name. 1175 // Unfortunately, due to a viewer bug, viewers don't always show the new name.
1088 // But we have a trick that can force them to update the name anyway. 1176 // But we have a trick that can force them to update the name anyway.
1089 ForceViewersUpdateName(); 1177// ForceViewersUpdateName();
1090 } 1178 }
1091 1179
1180 m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1181
1092 RegionHandle = m_scene.RegionInfo.RegionHandle; 1182 RegionHandle = m_scene.RegionInfo.RegionHandle;
1093 1183
1094 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1184 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1095 1185 m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1096 UUID groupUUID = ControllingClient.ActiveGroupId;
1097 string groupName = string.Empty;
1098 ulong groupPowers = 0;
1099
1100 // ----------------------------------
1101 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
1102 try
1103 {
1104 if (groupUUID != UUID.Zero && gm != null)
1105 {
1106 GroupRecord record = gm.GetGroupRecord(groupUUID);
1107 if (record != null)
1108 groupName = record.GroupName;
1109
1110 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1111
1112 if (groupMembershipData != null)
1113 groupPowers = groupMembershipData.GroupPowers;
1114 }
1115
1116 ControllingClient.SendAgentDataUpdate(
1117 m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle);
1118 }
1119 catch (Exception e)
1120 {
1121 m_log.Error("[AGENTUPDATE]: Error ", e);
1122 }
1123 // ------------------------------------
1124 1186
1125 if (ParentID == 0) 1187 if (ParentID == 0)
1126 { 1188 {
1127 // Moved this from SendInitialData to ensure that Appearance is initialized
1128 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1129 // related to the handling of attachments
1130 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1131
1132 /* RA 20140111: Commented out these TestBorderCross's.
1133 * Not sure why this code is here. It is not checking all the borders
1134 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
1135 if (m_scene.TestBorderCross(pos, Cardinals.E))
1136 {
1137 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
1138 pos.X = crossedBorder.BorderLine.Z - 1;
1139 }
1140
1141 if (m_scene.TestBorderCross(pos, Cardinals.N))
1142 {
1143 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
1144 pos.Y = crossedBorder.BorderLine.Z - 1;
1145 }
1146 */
1147
1148 CheckAndAdjustLandingPoint(ref pos); 1189 CheckAndAdjustLandingPoint(ref pos);
1149 1190
1150 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1191 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -1166,7 +1207,7 @@ namespace OpenSim.Region.Framework.Scenes
1166 1207
1167 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY) 1208 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
1168 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1209 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1169 1210
1170 float newPosZ = posZLimit + localAVHeight / 2; 1211 float newPosZ = posZLimit + localAVHeight / 2;
1171 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1212 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1172 { 1213 {
@@ -1180,24 +1221,18 @@ namespace OpenSim.Region.Framework.Scenes
1180// 1221//
1181 if (m_teleportFlags == TeleportFlags.Default) 1222 if (m_teleportFlags == TeleportFlags.Default)
1182 { 1223 {
1224 Vector3 vel = Velocity;
1183 AddToPhysicalScene(isFlying); 1225 AddToPhysicalScene(isFlying);
1184// 1226 if (PhysicsActor != null)
1185// Console.WriteLine( 1227 PhysicsActor.SetMomentum(vel);
1186// "Set velocity of {0} in {1} to {2} from input velocity of {3} on MakeRootAgent",
1187// Name, Scene.Name, PhysicsActor.Velocity, vel);
1188// }
1189 } 1228 }
1190 else 1229 else
1191 { 1230 {
1192 AddToPhysicalScene(isFlying); 1231 AddToPhysicalScene(isFlying);
1193 }
1194 1232
1195 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a 1233 // reset camera to avatar pos
1196 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it 1234 CameraPosition = pos;
1197 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset 1235 }
1198 // the value to a negative position which does not trigger the border cross.
1199 // This may not be the best location for this.
1200 CheckForBorderCrossing();
1201 1236
1202 if (ForceFly) 1237 if (ForceFly)
1203 { 1238 {
@@ -1207,55 +1242,29 @@ namespace OpenSim.Region.Framework.Scenes
1207 { 1242 {
1208 Flying = false; 1243 Flying = false;
1209 } 1244 }
1210 }
1211 1245
1212 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 1246 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1213 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 1247 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1214 // elsewhere anyway 1248 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1215 // Animator.SendAnimPack(); 1249 // the value to a negative position which does not trigger the border cross.
1250 // This may not be the best location for this.
1216 1251
1217 m_scene.SwapRootAgentCount(false);
1218 1252
1219 if (Scene.AttachmentsModule != null) 1253 // its not
1220 { 1254// CheckForBorderCrossing();
1221 // The initial login scene presence is already root when it gets here
1222 // and it has already rezzed the attachments and started their scripts.
1223 // We do the following only for non-login agents, because their scripts
1224 // haven't started yet.
1225 if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
1226 {
1227 WorkManager.RunJob(
1228 "RezAttachments",
1229 o => Scene.AttachmentsModule.RezAttachments(this),
1230 null,
1231 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name));
1232 }
1233 else
1234 {
1235 WorkManager.RunJob(
1236 "StartAttachmentScripts",
1237 o => RestartAttachmentScripts(),
1238 null,
1239 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
1240 true);
1241 }
1242 } 1255 }
1243 1256
1244 SendAvatarDataToAllClients(); 1257
1245 1258 m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1246 // send the animations of the other presences to me 1259 m_scene.SwapRootAgentCount(false);
1247 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1248 {
1249 if (presence != this)
1250 presence.Animator.SendAnimPackToClient(ControllingClient);
1251 });
1252 1260
1253 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1261 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1254 // stall on the border crossing since the existing child agent will still have the last movement 1262 // stall on the border crossing since the existing child agent will still have the last movement
1255 // recorded, which stops the input from being processed. 1263 // recorded, which stops the input from being processed.
1256 MovementFlag = ForceUpdateMovementFlagValue; 1264 MovementFlag = 0;
1257 1265
1258 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1266 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1267 m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1259 1268
1260 return true; 1269 return true;
1261 } 1270 }
@@ -1304,12 +1313,13 @@ namespace OpenSim.Region.Framework.Scenes
1304 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing 1313 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing
1305 /// the group title (to "(Loading)"), and then restoring it. 1314 /// the group title (to "(Loading)"), and then restoring it.
1306 /// </remarks> 1315 /// </remarks>
1316/*
1307 public void ForceViewersUpdateName() 1317 public void ForceViewersUpdateName()
1308 { 1318 {
1309 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name); 1319 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
1310 1320
1311 UseFakeGroupTitle = true; 1321 UseFakeGroupTitle = true;
1312 SendAvatarDataToAllClients(false); 1322
1313 1323
1314 Util.FireAndForget(o => 1324 Util.FireAndForget(o =>
1315 { 1325 {
@@ -1323,7 +1333,7 @@ namespace OpenSim.Region.Framework.Scenes
1323 SendAvatarDataToAllClients(false); 1333 SendAvatarDataToAllClients(false);
1324 }, null, "Scenepresence.ForceViewersUpdateName"); 1334 }, null, "Scenepresence.ForceViewersUpdateName");
1325 } 1335 }
1326 1336*/
1327 public int GetStateSource() 1337 public int GetStateSource()
1328 { 1338 {
1329 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); 1339 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID);
@@ -1347,11 +1357,14 @@ namespace OpenSim.Region.Framework.Scenes
1347 /// It doesn't get called for a teleport. Reason being, an agent that 1357 /// It doesn't get called for a teleport. Reason being, an agent that
1348 /// teleports out may not end up anywhere near this region 1358 /// teleports out may not end up anywhere near this region
1349 /// </remarks> 1359 /// </remarks>
1350 public void MakeChildAgent() 1360 public void MakeChildAgent(ulong newRegionHandle)
1351 { 1361 {
1352 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1362 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1353 1363
1354 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1364 RegionHandle = newRegionHandle;
1365
1366 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1367 Name, Scene.RegionInfo.RegionName, newRegionHandle);
1355 1368
1356 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating 1369 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1357 // from the source simulator has completed on a V2 teleport. 1370 // from the source simulator has completed on a V2 teleport.
@@ -1371,7 +1384,7 @@ namespace OpenSim.Region.Framework.Scenes
1371 else 1384 else
1372 Animator.ResetAnimations(); 1385 Animator.ResetAnimations();
1373 1386
1374 1387
1375// m_log.DebugFormat( 1388// m_log.DebugFormat(
1376// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1389// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1377// Name, UUID, m_scene.RegionInfo.RegionName); 1390// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1385,8 +1398,15 @@ namespace OpenSim.Region.Framework.Scenes
1385 RemoveFromPhysicalScene(); 1398 RemoveFromPhysicalScene();
1386 ParentID = 0; // Child agents can't be sitting 1399 ParentID = 0; // Child agents can't be sitting
1387 1400
1401// we dont have land information for child
1402 m_previusParcelHide = false;
1403 m_previusParcelUUID = UUID.Zero;
1404 m_currentParcelHide = false;
1405 m_currentParcelUUID = UUID.Zero;
1388 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1406 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1389 1407
1408 CollisionPlane = Vector4.UnitW;
1409
1390 m_scene.EventManager.TriggerOnMakeChildAgent(this); 1410 m_scene.EventManager.TriggerOnMakeChildAgent(this);
1391 } 1411 }
1392 1412
@@ -1398,9 +1418,10 @@ namespace OpenSim.Region.Framework.Scenes
1398 if (PhysicsActor != null) 1418 if (PhysicsActor != null)
1399 { 1419 {
1400// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1420// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1401 PhysicsActor.UnSubscribeEvents(); 1421
1402 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1422 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
1403 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1423 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1424 PhysicsActor.UnSubscribeEvents();
1404 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1425 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1405 PhysicsActor = null; 1426 PhysicsActor = null;
1406 } 1427 }
@@ -1438,6 +1459,8 @@ namespace OpenSim.Region.Framework.Scenes
1438 else 1459 else
1439 PhysicsActor.SetMomentum(vel); 1460 PhysicsActor.SetMomentum(vel);
1440 } 1461 }
1462
1463 SendTerseUpdateToAllClients();
1441 } 1464 }
1442 1465
1443 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) 1466 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
@@ -1469,10 +1492,14 @@ namespace OpenSim.Region.Framework.Scenes
1469 } 1492 }
1470 } 1493 }
1471 } 1494 }
1495 SendTerseUpdateToAllClients();
1472 } 1496 }
1473 1497
1474 public void StopFlying() 1498 public void StopFlying()
1475 { 1499 {
1500 if (IsInTransit)
1501 return;
1502
1476 Vector3 pos = AbsolutePosition; 1503 Vector3 pos = AbsolutePosition;
1477 if (Appearance.AvatarHeight != 127.0f) 1504 if (Appearance.AvatarHeight != 127.0f)
1478 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); 1505 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
@@ -1492,7 +1519,7 @@ namespace OpenSim.Region.Framework.Scenes
1492 else 1519 else
1493 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); 1520 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1494 1521
1495 ControllingClient.SendAgentTerseUpdate(this); 1522 SendAgentTerseUpdate(this);
1496 } 1523 }
1497 1524
1498 /// <summary> 1525 /// <summary>
@@ -1578,15 +1605,46 @@ namespace OpenSim.Region.Framework.Scenes
1578 // holds the seed cap for the child agent in that region 1605 // holds the seed cap for the child agent in that region
1579 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); 1606 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
1580 1607
1581 public void AddNeighbourRegion(ulong regionHandle, string cap) 1608 struct spRegionSizeInfo
1609 {
1610 public int sizeX;
1611 public int sizeY;
1612 }
1613
1614 private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>();
1615
1616
1617 public void AddNeighbourRegionSizeInfo(GridRegion region)
1582 { 1618 {
1583 lock (m_knownChildRegions) 1619 lock (m_knownChildRegions)
1584 { 1620 {
1585 if (!m_knownChildRegions.ContainsKey(regionHandle)) 1621 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1622 sizeInfo.sizeX = region.RegionSizeX;
1623 sizeInfo.sizeY = region.RegionSizeY;
1624 ulong regionHandle = region.RegionHandle;
1625
1626 if (!m_knownChildRegionsSizeInfo.ContainsKey(regionHandle))
1586 { 1627 {
1587 uint x, y; 1628 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1588 Utils.LongToUInts(regionHandle, out x, out y); 1629
1589 m_knownChildRegions.Add(regionHandle, cap); 1630 }
1631 else
1632 m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo;
1633 }
1634 }
1635
1636 public void SetNeighbourRegionSizeInfo(List<GridRegion> regionsList)
1637 {
1638 lock (m_knownChildRegions)
1639 {
1640 m_knownChildRegionsSizeInfo.Clear();
1641 foreach (GridRegion region in regionsList)
1642 {
1643 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1644 sizeInfo.sizeX = region.RegionSizeX;
1645 sizeInfo.sizeY = region.RegionSizeY;
1646 ulong regionHandle = region.RegionHandle;
1647 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1590 } 1648 }
1591 } 1649 }
1592 } 1650 }
@@ -1600,6 +1658,7 @@ namespace OpenSim.Region.Framework.Scenes
1600 //if (m_knownChildRegions.ContainsKey(regionHandle)) 1658 //if (m_knownChildRegions.ContainsKey(regionHandle))
1601 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); 1659 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
1602 m_knownChildRegions.Remove(regionHandle); 1660 m_knownChildRegions.Remove(regionHandle);
1661 m_knownChildRegionsSizeInfo.Remove(regionHandle);
1603 } 1662 }
1604 } 1663 }
1605 1664
@@ -1612,6 +1671,13 @@ namespace OpenSim.Region.Framework.Scenes
1612 } 1671 }
1613 } 1672 }
1614 1673
1674 public void DropThisRootRegionFromNeighbours()
1675 {
1676 ulong handle = m_scene.RegionInfo.RegionHandle;
1677 RemoveNeighbourRegion(handle);
1678 Scene.CapsModule.DropChildSeed(UUID, handle);
1679 }
1680
1615 public Dictionary<ulong, string> KnownRegions 1681 public Dictionary<ulong, string> KnownRegions
1616 { 1682 {
1617 get 1683 get
@@ -1662,12 +1728,7 @@ namespace OpenSim.Region.Framework.Scenes
1662 public void SetSize(Vector3 size, float feetoffset) 1728 public void SetSize(Vector3 size, float feetoffset)
1663 { 1729 {
1664 if (PhysicsActor != null && !IsChildAgent) 1730 if (PhysicsActor != null && !IsChildAgent)
1665 { 1731 PhysicsActor.setAvatarSize(size, feetoffset);
1666 // Eventually there will be a physics call that sets avatar size that includes offset info.
1667 // For the moment, just set the size as passed.
1668 PhysicsActor.Size = size;
1669 // PhysicsActor.setAvatarSize(size, feetoffset);
1670 }
1671 } 1732 }
1672 1733
1673 private bool WaitForUpdateAgent(IClientAPI client) 1734 private bool WaitForUpdateAgent(IClientAPI client)
@@ -1676,13 +1737,23 @@ namespace OpenSim.Region.Framework.Scenes
1676 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, 1737 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1677 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the 1738 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1678 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero 1739 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1679 m_updateAgentReceivedAfterTransferEvent.WaitOne(10000); 1740// m_updateAgentReceivedAfterTransferEvent.WaitOne(10000);
1680 1741 int count = 50;
1681 UUID originID = UUID.Zero; 1742 UUID originID = UUID.Zero;
1682 1743
1683 lock (m_originRegionIDAccessLock) 1744 lock (m_originRegionIDAccessLock)
1684 originID = m_originRegionID; 1745 originID = m_originRegionID;
1685 1746
1747
1748 while (originID.Equals(UUID.Zero) && count-- > 0)
1749 {
1750 lock (m_originRegionIDAccessLock)
1751 originID = m_originRegionID;
1752
1753 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1754 Thread.Sleep(200);
1755 }
1756
1686 if (originID.Equals(UUID.Zero)) 1757 if (originID.Equals(UUID.Zero))
1687 { 1758 {
1688 // Movement into region will fail 1759 // Movement into region will fail
@@ -1704,62 +1775,70 @@ namespace OpenSim.Region.Framework.Scenes
1704 /// </param> 1775 /// </param>
1705 public void CompleteMovement(IClientAPI client, bool openChildAgents) 1776 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1706 { 1777 {
1707// DateTime startTime = DateTime.Now; 1778 int ts = Util.EnvironmentTickCount();
1708 1779
1709 m_log.InfoFormat( 1780 m_log.InfoFormat(
1710 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1781 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1711 client.Name, Scene.Name, AbsolutePosition); 1782 client.Name, Scene.Name, AbsolutePosition);
1783
1784 m_inTransit = true;
1712 1785
1713 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags'
1714
1715 IsInTransit = true;
1716 try 1786 try
1717 { 1787 {
1718 // Make sure it's not a login agent. We don't want to wait for updates during login 1788 // Make sure it's not a login agent. We don't want to wait for updates during login
1719 if (!(PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))) 1789 if (!isNPC && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1720 { 1790 {
1791
1721 // Let's wait until UpdateAgent (called by departing region) is done 1792 // Let's wait until UpdateAgent (called by departing region) is done
1722 if (!WaitForUpdateAgent(client)) 1793 if (!WaitForUpdateAgent(client))
1723 // The sending region never sent the UpdateAgent data, we have to refuse 1794 // The sending region never sent the UpdateAgent data, we have to refuse
1724 return; 1795 return;
1725 } 1796 }
1726 1797
1727 Vector3 look = Velocity; 1798 m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1799
1800 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1728 1801
1729 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1802 if (!MakeRootAgent(AbsolutePosition, flying))
1730 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1731 { 1803 {
1732 look = new Vector3(0.99f, 0.042f, 0); 1804 m_log.DebugFormat(
1805 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1806 Name, Scene.Name);
1807
1808 return;
1733 } 1809 }
1734 1810
1735 // Prevent teleporting to an underground location 1811 m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1736 // (may crash client otherwise) 1812
1737 // 1813 Vector3 look = Lookat;
1738 Vector3 pos = AbsolutePosition; 1814 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1739 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1740 if (pos.Z < ground + 1.5f)
1741 { 1815 {
1742 pos.Z = ground + 1.5f; 1816 look = Velocity;
1743 AbsolutePosition = pos; 1817 look.Z = 0;
1818 look.Normalize();
1819 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1820 look = new Vector3(0.99f, 0.042f, 0);
1744 } 1821 }
1745 1822
1746 if (!MakeRootAgent(AbsolutePosition, flying)) 1823// start sending terrain patchs
1824 if (!isNPC)
1825 Scene.SendLayerData(ControllingClient);
1826
1827 if (!IsChildAgent && !isNPC)
1747 { 1828 {
1748 m_log.DebugFormat( 1829 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46);
1749 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", 1830 if (cof == null)
1750 Name, Scene.Name); 1831 COF = UUID.Zero;
1832 else
1833 COF = cof.ID;
1751 1834
1752 return; 1835 m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1753 } 1836 }
1754 1837
1755 // Tell the client that we're totally ready 1838 // Tell the client that we're totally ready
1756 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1839 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1757 1840
1758 // Child agents send initial data up in LLUDPServer.HandleUseCircuitCode() 1841 m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1759 if (!SentInitialDataToClient)
1760 SendInitialDataToClient();
1761
1762 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1763 1842
1764 if (!string.IsNullOrEmpty(m_callbackURI)) 1843 if (!string.IsNullOrEmpty(m_callbackURI))
1765 { 1844 {
@@ -1768,69 +1847,205 @@ namespace OpenSim.Region.Framework.Scenes
1768 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 1847 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1769 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this 1848 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1770 // region as the current region, meaning that a close sent before then will fail the teleport. 1849 // region as the current region, meaning that a close sent before then will fail the teleport.
1771 // System.Threading.Thread.Sleep(2000); 1850 // System.Threading.Thread.Sleep(2000);
1772 1851
1773 m_log.DebugFormat( 1852 m_log.DebugFormat(
1774 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1853 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1775 client.Name, client.AgentId, m_callbackURI); 1854 client.Name, client.AgentId, m_callbackURI);
1776 1855
1777 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1856 UUID originID;
1857
1858 lock (m_originRegionIDAccessLock)
1859 originID = m_originRegionID;
1860
1861 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1778 m_callbackURI = null; 1862 m_callbackURI = null;
1779 } 1863 }
1780 // else 1864// else
1781 // { 1865// {
1782 // m_log.DebugFormat( 1866// m_log.DebugFormat(
1783 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", 1867// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1784 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 1868// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1785 // } 1869// }
1870
1871 m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1786 1872
1787 ValidateAndSendAppearanceAndAgentData(); 1873 m_previusParcelHide = false;
1874 m_previusParcelUUID = UUID.Zero;
1875 m_currentParcelHide = false;
1876 m_currentParcelUUID = UUID.Zero;
1788 1877
1789 // Create child agents in neighbouring regions 1878 // send initial land overlay and parcel
1790 if (openChildAgents && !IsChildAgent) 1879 ILandChannel landch = m_scene.LandChannel;
1880 if (landch != null)
1881 landch.sendClientInitialLandInfo(client);
1882
1883 if (!IsChildAgent)
1791 { 1884 {
1792 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1885
1793 if (m_agentTransfer != null) 1886 // ValidateAndSendAppearanceAndAgentData();
1887
1888 // do it here in line
1889 // so sequence is clear
1890
1891 // verify baked textures and cache
1892 bool cachedbaked = false;
1893
1894 if (isNPC)
1895 cachedbaked = true;
1896 else
1794 { 1897 {
1795 // Note: this call can take a while, because it notifies each of the simulator's neighbours. 1898 if (m_scene.AvatarFactory != null)
1796 // It's important that we don't allow the avatar to cross regions meanwhile, as that will 1899 cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
1797 // cause serious errors. We've prevented that from happening by setting IsInTransit=true. 1900
1798 m_agentTransfer.EnableChildAgents(this); 1901 // not sure we need this
1902 if (!cachedbaked)
1903 {
1904 if (m_scene.AvatarFactory != null)
1905 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
1906 }
1799 } 1907 }
1800 1908
1801 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1909 List<ScenePresence> allpresences = m_scene.GetScenePresences();
1802 if (friendsModule != null) 1910
1803 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 1911 // send avatar object to all presences including us, so they cross it into region
1912 // then hide if necessary
1913 SendInitialAvatarDataToAllAgents(allpresences);
1914
1915 // send this look
1916 SendAppearanceToAgent(this);
1917
1918 // send this animations
1919
1920 UUID[] animIDs = null;
1921 int[] animseqs = null;
1922 UUID[] animsobjs = null;
1923
1924 if (Animator != null)
1925 Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
1926
1927 bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
1928
1929 if (haveAnims)
1930 SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
1931
1932 // we should be able to receive updates, etc
1933 // so release them
1934 m_inTransit = false;
1935
1936 // send look and animations to others
1937 // if not cached we send greys
1938 // uncomented if will wait till avatar does baking
1939 //if (cachedbaked)
1940 {
1941 foreach (ScenePresence p in allpresences)
1942 {
1943 if (p == this)
1944 continue;
1945
1946 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1947 continue;
1948
1949 SendAppearanceToAgentNF(p);
1950 if (haveAnims)
1951 SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
1952 }
1953 } // greys if
1954
1955 m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1956
1957 // attachments
1958
1959 if (isNPC || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1960 {
1961 if (Scene.AttachmentsModule != null)
1962 // Util.FireAndForget(
1963 // o =>
1964 // {
1965 if (!isNPC)
1966 Scene.AttachmentsModule.RezAttachments(this);
1967 else
1968 Util.FireAndForget(x =>
1969 {
1970 Scene.AttachmentsModule.RezAttachments(this);
1971 });
1972 // });
1973 }
1974 else
1975 {
1976 if (m_attachments.Count > 0)
1977 {
1978 m_log.DebugFormat(
1979 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1804 1980
1981 foreach (SceneObjectGroup sog in m_attachments)
1982 {
1983 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1984 sog.ResumeScripts();
1985 }
1986
1987 foreach (ScenePresence p in allpresences)
1988 {
1989 if (p == this)
1990 {
1991 SendTerseUpdateToAgentNF(this);
1992 SendAttachmentsToAgentNF(this);
1993 continue;
1994 }
1995
1996 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1997 continue;
1998
1999 SendTerseUpdateToAgentNF(p);
2000 SendAttachmentsToAgentNF(p);
2001 }
2002 }
2003 }
2004
2005 m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2006 if (openChildAgents)
2007 {
2008 // Create child agents in neighbouring regions
2009 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
2010 if (m_agentTransfer != null)
2011 {
2012 m_agentTransfer.EnableChildAgents(this);
2013 }
2014 }
1805 } 2015 }
1806 2016
1807 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region 2017 m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1808 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. 2018
1809 // This may be due to viewer code or it may be something we're not doing properly simulator side. 2019 // send the rest of the world
1810 WorkManager.RunJob( 2020 if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
1811 "ScheduleAttachmentsForFullUpdate", 2021 SendInitialDataToMe();
1812 o => ScheduleAttachmentsForFullUpdate(), 2022
1813 null, 2023 m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1814 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name),
1815 true);
1816 2024
1817 // m_log.DebugFormat( 2025 if (!IsChildAgent && openChildAgents)
1818 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 2026 {
1819 // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 2027 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
2028// if (friendsModule != null)
2029// friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
2030
2031 m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2032
2033 }
1820 } 2034 }
1821 finally 2035 finally
1822 { 2036 {
1823 IsInTransit = false; 2037 m_inTransit = false;
1824 } 2038 }
1825 } 2039 // if hide force a check
2040 // if (!IsChildAgent && newhide)
2041 // {
2042 // ParcelLoginCheck(m_currentParcelUUID);
2043 // m_currentParcelHide = newhide;
2044 // }
1826 2045
1827 private void ScheduleAttachmentsForFullUpdate() 2046 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1828 { 2047
1829 lock (m_attachments) 2048 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1830 {
1831 foreach (SceneObjectGroup sog in m_attachments)
1832 sog.ScheduleGroupForFullUpdate();
1833 }
1834 } 2049 }
1835 2050
1836 /// <summary> 2051 /// <summary>
@@ -1921,6 +2136,9 @@ namespace OpenSim.Region.Framework.Scenes
1921 return; 2136 return;
1922 } 2137 }
1923 2138
2139 if (IsInTransit)
2140 return;
2141
1924 #region Sanity Checking 2142 #region Sanity Checking
1925 2143
1926 // This is irritating. Really. 2144 // This is irritating. Really.
@@ -1955,8 +2173,8 @@ namespace OpenSim.Region.Framework.Scenes
1955 // When we get to the point of re-computing neighbors everytime this 2173 // When we get to the point of re-computing neighbors everytime this
1956 // changes, then start using the agent's drawdistance rather than the 2174 // changes, then start using the agent's drawdistance rather than the
1957 // region's draw distance. 2175 // region's draw distance.
1958 DrawDistance = agentData.Far; 2176
1959 // DrawDistance = Scene.DefaultDrawDistance; 2177 DrawDistance = Util.Clamp(agentData.Far, 32, m_scene.MaxDrawDistance);
1960 2178
1961 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 2179 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1962 2180
@@ -1964,7 +2182,7 @@ namespace OpenSim.Region.Framework.Scenes
1964 // is first pressed, not whilst it is held down. If this is required in the future then need to look 2182 // is first pressed, not whilst it is held down. If this is required in the future then need to look
1965 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not 2183 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not
1966 // received (e.g. on holding LMB down on the avatar in a viewer). 2184 // received (e.g. on holding LMB down on the avatar in a viewer).
1967// m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 2185 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
1968 2186
1969 #endregion Inputs 2187 #endregion Inputs
1970 2188
@@ -1977,6 +2195,7 @@ namespace OpenSim.Region.Framework.Scenes
1977// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2195// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1978// m_updateCount = UPDATE_COUNT; 2196// m_updateCount = UPDATE_COUNT;
1979 2197
2198
1980 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2199 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1981 { 2200 {
1982 StandUp(); 2201 StandUp();
@@ -2032,7 +2251,7 @@ namespace OpenSim.Region.Framework.Scenes
2032 2251
2033 // We need to send this back to the client in order to stop the edit beams 2252 // We need to send this back to the client in order to stop the edit beams
2034 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) 2253 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2035 ControllingClient.SendAgentTerseUpdate(this); 2254 SendAgentTerseUpdate(this);
2036 2255
2037 PhysicsActor actor = PhysicsActor; 2256 PhysicsActor actor = PhysicsActor;
2038 2257
@@ -2045,10 +2264,8 @@ namespace OpenSim.Region.Framework.Scenes
2045 2264
2046 if (AllowMovement && !SitGround) 2265 if (AllowMovement && !SitGround)
2047 { 2266 {
2048// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); 2267// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
2049
2050 bool update_rotation = false; 2268 bool update_rotation = false;
2051
2052 if (agentData.BodyRotation != Rotation) 2269 if (agentData.BodyRotation != Rotation)
2053 { 2270 {
2054 Rotation = agentData.BodyRotation; 2271 Rotation = agentData.BodyRotation;
@@ -2057,14 +2274,6 @@ namespace OpenSim.Region.Framework.Scenes
2057 2274
2058 bool update_movementflag = false; 2275 bool update_movementflag = false;
2059 2276
2060 // If we were just made root agent then we must perform movement updates for the first AgentUpdate that
2061 // we get
2062 if (MovementFlag == ForceUpdateMovementFlagValue)
2063 {
2064 MovementFlag = 0;
2065 update_movementflag = true;
2066 }
2067
2068 if (agentData.UseClientAgentPosition) 2277 if (agentData.UseClientAgentPosition)
2069 { 2278 {
2070 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; 2279 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
@@ -2075,7 +2284,7 @@ namespace OpenSim.Region.Framework.Scenes
2075 bool DCFlagKeyPressed = false; 2284 bool DCFlagKeyPressed = false;
2076 Vector3 agent_control_v3 = Vector3.Zero; 2285 Vector3 agent_control_v3 = Vector3.Zero;
2077 2286
2078 bool newFlying = actor.Flying; 2287 bool newFlying = false;
2079 2288
2080 if (ForceFly) 2289 if (ForceFly)
2081 newFlying = true; 2290 newFlying = true;
@@ -2096,6 +2305,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2305 {
2097 bool bAllowUpdateMoveToPosition = false; 2306 bool bAllowUpdateMoveToPosition = false;
2098 2307
2308 Vector3[] dirVectors;
2309
2310 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
2311 // this prevents 'jumping' in inappropriate situations.
2312// if (!Flying && (m_mouseLook || m_leftButtonDown))
2313// dirVectors = GetWalkDirectionVectors();
2314// else
2315 dirVectors = Dir_Vectors;
2316
2099 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2317 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
2100 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2318 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
2101 { 2319 {
@@ -2105,9 +2323,7 @@ namespace OpenSim.Region.Framework.Scenes
2105 2323
2106 try 2324 try
2107 { 2325 {
2108 // Don't slide against ground when crouching if camera is panned around avatar 2326 agent_control_v3 += Dir_Vectors[i];
2109 if (Flying || DCF != Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)
2110 agent_control_v3 += Dir_Vectors[i];
2111 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 2327 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
2112 } 2328 }
2113 catch (IndexOutOfRangeException) 2329 catch (IndexOutOfRangeException)
@@ -2115,10 +2331,10 @@ namespace OpenSim.Region.Framework.Scenes
2115 // Why did I get this? 2331 // Why did I get this?
2116 } 2332 }
2117 2333
2118 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) 2334 if (((MovementFlag & (uint)DCF) == 0))
2119 { 2335 {
2120 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2336 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
2121 MovementFlag += (uint)DCF; 2337 MovementFlag |= (uint)DCF;
2122 update_movementflag = true; 2338 update_movementflag = true;
2123 } 2339 }
2124 } 2340 }
@@ -2127,7 +2343,7 @@ namespace OpenSim.Region.Framework.Scenes
2127 if ((MovementFlag & (uint)DCF) != 0) 2343 if ((MovementFlag & (uint)DCF) != 0)
2128 { 2344 {
2129 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2345 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
2130 MovementFlag -= (uint)DCF; 2346 MovementFlag &= (uint)~DCF;
2131 update_movementflag = true; 2347 update_movementflag = true;
2132 2348
2133 /* 2349 /*
@@ -2180,11 +2396,11 @@ namespace OpenSim.Region.Framework.Scenes
2180 if (Flying && !ForceFly) 2396 if (Flying && !ForceFly)
2181 { 2397 {
2182 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP 2398 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
2183 if (AgentControlStopActive) 2399 // if (AgentControlStopActive)
2184 { 2400 // {
2185 agent_control_v3 = Vector3.Zero; 2401 // agent_control_v3 = Vector3.Zero;
2186 } 2402 // }
2187 else 2403 // else
2188 { 2404 {
2189 // Landing detection code 2405 // Landing detection code
2190 2406
@@ -2192,38 +2408,44 @@ namespace OpenSim.Region.Framework.Scenes
2192 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2408 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
2193 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2409 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2194 2410
2195 //m_log.Debug("[CONTROL]: " +flags); 2411 //m_log.Debug("[CONTROL]: " +flags);
2196 // Applies a satisfying roll effect to the avatar when flying. 2412 // Applies a satisfying roll effect to the avatar when flying.
2197 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) 2413 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2198 { 2414 {
2199 ApplyFlyingRoll( 2415 ApplyFlyingRoll(
2200 FLY_ROLL_RADIANS_PER_UPDATE, 2416 FLY_ROLL_RADIANS_PER_UPDATE,
2201 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2417 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2202 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2418 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2203 } 2419 }
2204 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && 2420 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2205 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2421 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2206 { 2422 {
2207 ApplyFlyingRoll( 2423 ApplyFlyingRoll(
2208 -FLY_ROLL_RADIANS_PER_UPDATE, 2424 -FLY_ROLL_RADIANS_PER_UPDATE,
2209 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2425 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2210 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2426 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2211 } 2427 }
2212 else 2428 else
2213 { 2429 {
2214 if (m_AngularVelocity.Z != 0) 2430 if (m_AngularVelocity.Z != 0)
2215 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); 2431 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2216 }
2217
2218 if (Flying && IsColliding && controlland)
2219 {
2220 // nesting this check because LengthSquared() is expensive and we don't
2221 // want to do it every step when flying.
2222 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2223 StopFlying();
2224 } 2432 }
2433
2434 /*
2435 if (Flying && IsColliding && controlland)
2436 {
2437 // nesting this check because LengthSquared() is expensive and we don't
2438 // want to do it every step when flying.
2439 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2440 StopFlying();
2441 }
2442 */
2225 } 2443 }
2226 } 2444 }
2445 else if (IsColliding && agent_control_v3.Z < 0f)
2446 agent_control_v3.Z = 0;
2447// else if(AgentControlStopActive %% Velocity.Z <0.01f)
2448
2227 2449
2228// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); 2450// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2229 2451
@@ -2236,32 +2458,23 @@ namespace OpenSim.Region.Framework.Scenes
2236 if (update_movementflag 2458 if (update_movementflag
2237 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) 2459 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
2238 { 2460 {
2239// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
2240// {
2241// m_log.DebugFormat(
2242// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2243// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2244// update_movementflag, MovementFlag, update_rotation);
2245
2246 float speedModifier;
2247 2461
2248 if (AgentControlStopActive) 2462 if (AgentControlStopActive)
2249 speedModifier = AgentControlStopSlowWhilstMoving; 2463 {
2464 // if (MovementFlag == 0 && Animator.Falling)
2465 if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2466 {
2467 AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2468 }
2250 else 2469 else
2251 speedModifier = 1; 2470 AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2471 }
2472 else
2473 {
2474 AddNewMovement(agent_control_v3);
2475 }
2252 2476
2253 AddNewMovement(agent_control_v3, speedModifier);
2254// }
2255 } 2477 }
2256// else
2257// {
2258// if (!update_movementflag)
2259// {
2260// m_log.DebugFormat(
2261// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
2262// m_scene.RegionInfo.RegionName, agent_control_v3, Name);
2263// }
2264// }
2265 2478
2266 if (update_movementflag && ParentID == 0) 2479 if (update_movementflag && ParentID == 0)
2267 { 2480 {
@@ -2274,7 +2487,7 @@ namespace OpenSim.Region.Framework.Scenes
2274 2487
2275 // We need to send this back to the client in order to see the edit beams 2488 // We need to send this back to the client in order to see the edit beams
2276 if ((State & (uint)AgentState.Editing) != 0) 2489 if ((State & (uint)AgentState.Editing) != 0)
2277 ControllingClient.SendAgentTerseUpdate(this); 2490 SendAgentTerseUpdate(this);
2278 2491
2279 m_scene.EventManager.TriggerOnClientMovement(this); 2492 m_scene.EventManager.TriggerOnClientMovement(this);
2280 } 2493 }
@@ -2320,8 +2533,8 @@ namespace OpenSim.Region.Framework.Scenes
2320 // When we get to the point of re-computing neighbors everytime this 2533 // When we get to the point of re-computing neighbors everytime this
2321 // changes, then start using the agent's drawdistance rather than the 2534 // changes, then start using the agent's drawdistance rather than the
2322 // region's draw distance. 2535 // region's draw distance.
2323 DrawDistance = agentData.Far; 2536
2324 // DrawDistance = Scene.DefaultDrawDistance; 2537 DrawDistance = Util.Clamp(agentData.Far, 32, m_scene.MaxDrawDistance);
2325 2538
2326 // Check if Client has camera in 'follow cam' or 'build' mode. 2539 // Check if Client has camera in 'follow cam' or 'build' mode.
2327 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); 2540 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
@@ -2358,11 +2571,13 @@ namespace OpenSim.Region.Framework.Scenes
2358 2571
2359 bool updated = false; 2572 bool updated = false;
2360 2573
2574 Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition;
2575
2361// m_log.DebugFormat( 2576// m_log.DebugFormat(
2362// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 2577// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2363// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 2578// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2364 2579
2365 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 2580 double distanceToTarget = LocalVectorToTarget3D.Length();
2366 2581
2367// m_log.DebugFormat( 2582// m_log.DebugFormat(
2368// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 2583// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
@@ -2385,11 +2600,11 @@ namespace OpenSim.Region.Framework.Scenes
2385 // Theoretically we might need a more complex PID approach here if other 2600 // Theoretically we might need a more complex PID approach here if other
2386 // unknown forces are acting on the avatar and we need to adaptively respond 2601 // unknown forces are acting on the avatar and we need to adaptively respond
2387 // to such forces, but the following simple approach seems to works fine. 2602 // to such forces, but the following simple approach seems to works fine.
2388 Vector3 LocalVectorToTarget3D = 2603
2389 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 2604 LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords
2390 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
2391 // Ignore z component of vector 2605 // Ignore z component of vector
2392// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 2606// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
2607
2393 LocalVectorToTarget3D.Normalize(); 2608 LocalVectorToTarget3D.Normalize();
2394 2609
2395 // update avatar movement flags. the avatar coordinate system is as follows: 2610 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -2413,28 +2628,37 @@ namespace OpenSim.Region.Framework.Scenes
2413 2628
2414 // based on the above avatar coordinate system, classify the movement into 2629 // based on the above avatar coordinate system, classify the movement into
2415 // one of left/right/back/forward. 2630 // one of left/right/back/forward.
2631
2632 const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2633 Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2634 Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2635 Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2636
2637 MovementFlag &= noMovFlagsMask;
2638 AgentControlFlags &= noMovFlagsMask;
2639
2416 if (LocalVectorToTarget3D.X < 0) //MoveBack 2640 if (LocalVectorToTarget3D.X < 0) //MoveBack
2417 { 2641 {
2418 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2642 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2419 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2643 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2420 updated = true; 2644 updated = true;
2421 } 2645 }
2422 else if (LocalVectorToTarget3D.X > 0) //Move Forward 2646 else if (LocalVectorToTarget3D.X > 0) //Move Forward
2423 { 2647 {
2424 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2648 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2425 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2649 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2426 updated = true; 2650 updated = true;
2427 } 2651 }
2428 2652
2429 if (LocalVectorToTarget3D.Y > 0) //MoveLeft 2653 if (LocalVectorToTarget3D.Y > 0) //MoveLeft
2430 { 2654 {
2431 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2655 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2432 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2656 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2433 updated = true; 2657 updated = true;
2434 } 2658 }
2435 else if (LocalVectorToTarget3D.Y < 0) //MoveRight 2659 else if (LocalVectorToTarget3D.Y < 0) //MoveRight
2436 { 2660 {
2437 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2661 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2438 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2662 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2439 updated = true; 2663 updated = true;
2440 } 2664 }
@@ -2504,37 +2728,25 @@ namespace OpenSim.Region.Framework.Scenes
2504 || pos.Y < 0 || pos.Y >= regionSize.Y 2728 || pos.Y < 0 || pos.Y >= regionSize.Y
2505 || pos.Z < 0) 2729 || pos.Z < 0)
2506 return; 2730 return;
2507 2731
2508 Scene targetScene = m_scene; 2732 Scene targetScene = m_scene;
2509
2510// Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2);
2511// pos += heightAdjust;
2512//
2513// // Anti duck-walking measure
2514// if (Math.Abs(pos.Z - AbsolutePosition.Z) < 0.2f)
2515// {
2516//// m_log.DebugFormat("[SCENE PRESENCE]: Adjusting MoveToPosition from {0} to {1}", pos, AbsolutePosition);
2517// pos.Z = AbsolutePosition.Z;
2518// }
2519
2520 // Get terrain height for sub-region in a megaregion if necessary 2733 // Get terrain height for sub-region in a megaregion if necessary
2521
2522 //COMMENT: If its only nessesary in a megaregion, why do it on normal region's too?
2523
2524 if (regionCombinerModule != null) 2734 if (regionCombinerModule != null)
2525 { 2735 {
2526 int x = (int)((m_scene.RegionInfo.WorldLocX) + pos.X); 2736 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2527 int y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y); 2737 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2528 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); 2738 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2529
2530 // If X and Y is NaN, target_region will be null 2739 // If X and Y is NaN, target_region will be null
2531 if (target_region == null) 2740 if (target_region == null)
2532 return; 2741 return;
2533 2742 UUID target_regionID = target_region.RegionID;
2534 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene); 2743 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene);
2535 } 2744 }
2536 2745
2537 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)]; 2746 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2747 // dont try to land underground
2748 terrainHeight += Appearance.AvatarHeight / 2;
2749
2538 pos.Z = Math.Max(terrainHeight, pos.Z); 2750 pos.Z = Math.Max(terrainHeight, pos.Z);
2539 2751
2540 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2752 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2543,17 +2755,14 @@ namespace OpenSim.Region.Framework.Scenes
2543 if (pos.Z - terrainHeight < 0.2) 2755 if (pos.Z - terrainHeight < 0.2)
2544 pos.Z = terrainHeight; 2756 pos.Z = terrainHeight;
2545 2757
2546 if (noFly)
2547 Flying = false;
2548 else if (pos.Z > terrainHeight)
2549 Flying = true;
2550
2551// m_log.DebugFormat( 2758// m_log.DebugFormat(
2552// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2759// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2553// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2760// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2554 2761
2555 if (noFly) 2762 if (noFly)
2556 Flying = false; 2763 Flying = false;
2764 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2765 Flying = true;
2557 2766
2558 LandAtTarget = landAtTarget; 2767 LandAtTarget = landAtTarget;
2559 MovingToTarget = true; 2768 MovingToTarget = true;
@@ -2629,48 +2838,41 @@ namespace OpenSim.Region.Framework.Scenes
2629 } 2838 }
2630 } 2839 }
2631 2840
2841 part.ParentGroup.DeleteAvatar(UUID);
2842
2843 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2844 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2632 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2845 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2633 2846
2634 ParentID = 0; 2847 ParentID = 0;
2635 ParentPart = null; 2848 ParentPart = null;
2636 2849
2637 Quaternion standRotation;
2638
2639 if (part.SitTargetAvatar == UUID) 2850 if (part.SitTargetAvatar == UUID)
2640 { 2851 standRotation = standRotation * part.SitTargetOrientation;
2641 standRotation = part.GetWorldRotation(); 2852 else
2853 standRotation = standRotation * m_bodyRot;
2642 2854
2643 if (!part.IsRoot) 2855 m_bodyRot = standRotation;
2644 standRotation = standRotation * part.SitTargetOrientation; 2856
2645// standRotation = part.RotationOffset * part.SitTargetOrientation; 2857 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2646// else
2647// standRotation = part.SitTargetOrientation;
2648 2858
2859 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2860 if (t > 0)
2861 {
2862 t = 1.0f / (float)Math.Sqrt(t);
2863 standRotationZ.W *= t;
2864 standRotationZ.Z *= t;
2649 } 2865 }
2650 else 2866 else
2651 { 2867 {
2652 standRotation = Rotation; 2868 standRotationZ.W = 1.0f;
2869 standRotationZ.Z = 0f;
2653 } 2870 }
2654 2871
2655 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2872 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2656 //Vector3 standPos = ParentPosition;
2657
2658// Vector3 standPositionAdjustment
2659// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2660 Vector3 adjustmentForSitPosition = OffsetPosition * part.ParentGroup.GroupRotation - SIT_TARGET_ADJUSTMENT * part.GetWorldRotation();
2661
2662 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2663 // hardcoding here.
2664 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2665
2666 Vector3 standPos = part.ParentGroup.AbsolutePosition + adjustmentForSitPosition + adjustmentForSitPose;
2667 2873
2668// m_log.DebugFormat( 2874 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2669// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}", 2875 m_pos = standPos;
2670// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2671
2672 Rotation = standRotation;
2673 AbsolutePosition = standPos;
2674 } 2876 }
2675 2877
2676 // We need to wait until we have calculated proper stand positions before sitting up the physical 2878 // We need to wait until we have calculated proper stand positions before sitting up the physical
@@ -2680,18 +2882,20 @@ namespace OpenSim.Region.Framework.Scenes
2680 2882
2681 if (satOnObject) 2883 if (satOnObject)
2682 { 2884 {
2683 SendAvatarDataToAllClients();
2684 m_requestedSitTargetID = 0;
2685
2686 part.RemoveSittingAvatar(this);
2687 2885
2886 m_requestedSitTargetID = 0;
2887 part.RemoveSittingAvatar(UUID);
2688 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2888 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2889
2890 SendAvatarDataToAllAgents();
2689 } 2891 }
2690 2892
2691 else if (PhysicsActor == null) 2893 // reset to default sitAnimation
2692 AddToPhysicalScene(false); 2894 sitAnimation = "SIT";
2895
2896// Animator.TrySetMovementAnimation("STAND");
2897 Animator.SetMovementAnimations("STAND");
2693 2898
2694 Animator.TrySetMovementAnimation("STAND");
2695 TriggerScenePresenceUpdated(); 2899 TriggerScenePresenceUpdated();
2696 } 2900 }
2697 2901
@@ -2739,6 +2943,7 @@ namespace OpenSim.Region.Framework.Scenes
2739 if (part == null) 2943 if (part == null)
2740 return; 2944 return;
2741 2945
2946
2742 if (PhysicsActor != null) 2947 if (PhysicsActor != null)
2743 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2948 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2744 2949
@@ -2746,23 +2951,9 @@ namespace OpenSim.Region.Framework.Scenes
2746 2951
2747 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2952 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2748 { 2953 {
2749// m_log.DebugFormat(
2750// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2751// Name, part.Name, part.LocalId);
2752
2753 offset = part.SitTargetPosition; 2954 offset = part.SitTargetPosition;
2754 sitOrientation = part.SitTargetOrientation; 2955 sitOrientation = part.SitTargetOrientation;
2755 2956
2756 if (!part.IsRoot)
2757 {
2758 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2759 sitOrientation = part.RotationOffset * sitOrientation;
2760 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2761// m_log.DebugFormat("Old sit offset {0}", offset);
2762 offset = offset * part.RotationOffset;
2763// m_log.DebugFormat("New sit offset {0}", offset);
2764 }
2765
2766 canSit = true; 2957 canSit = true;
2767 } 2958 }
2768 else 2959 else
@@ -2793,42 +2984,33 @@ namespace OpenSim.Region.Framework.Scenes
2793 2984
2794 Velocity = Vector3.Zero; 2985 Velocity = Vector3.Zero;
2795 2986
2796 part.AddSittingAvatar(this); 2987 part.AddSittingAvatar(UUID);
2797 2988
2798 cameraAtOffset = part.GetCameraAtOffset(); 2989 cameraAtOffset = part.GetCameraAtOffset();
2799
2800 if (!part.IsRoot && cameraAtOffset == Vector3.Zero)
2801 cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset();
2802
2803 bool cameraEyeOffsetFromRootForChild = false;
2804 cameraEyeOffset = part.GetCameraEyeOffset(); 2990 cameraEyeOffset = part.GetCameraEyeOffset();
2991
2992 forceMouselook = part.GetForceMouselook();
2805 2993
2806 if (!part.IsRoot && cameraEyeOffset == Vector3.Zero) 2994 if (!part.IsRoot)
2807 {
2808 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2809 cameraEyeOffsetFromRootForChild = true;
2810 }
2811
2812 if ((cameraEyeOffset != Vector3.Zero && !cameraEyeOffsetFromRootForChild) || cameraAtOffset != Vector3.Zero)
2813 { 2995 {
2814 if (!part.IsRoot) 2996 sitOrientation = part.RotationOffset * sitOrientation;
2997 offset = offset * part.RotationOffset;
2998 offset += part.OffsetPosition;
2999
3000 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2815 { 3001 {
2816 cameraEyeOffset = cameraEyeOffset * part.RotationOffset; 3002 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3003 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3004 }
3005 else
3006 {
3007 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2817 cameraAtOffset += part.OffsetPosition; 3008 cameraAtOffset += part.OffsetPosition;
3009 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3010 cameraEyeOffset += part.OffsetPosition;
2818 } 3011 }
2819
2820 cameraEyeOffset += part.OffsetPosition;
2821 } 3012 }
2822 3013
2823// m_log.DebugFormat(
2824// "[SCENE PRESENCE]: Using cameraAtOffset {0}, cameraEyeOffset {1} for sit on {2} by {3} in {4}",
2825// cameraAtOffset, cameraEyeOffset, part.Name, Name, Scene.Name);
2826
2827 forceMouselook = part.GetForceMouselook();
2828
2829 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2830 // being sat upon.
2831 offset += part.OffsetPosition;
2832 3014
2833 ControllingClient.SendSitResponse( 3015 ControllingClient.SendSitResponse(
2834 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3016 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
@@ -2875,9 +3057,6 @@ namespace OpenSim.Region.Framework.Scenes
2875 // returns false if does not suport so older sit can be tried 3057 // returns false if does not suport so older sit can be tried
2876 public bool PhysicsSit(SceneObjectPart part, Vector3 offset) 3058 public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
2877 { 3059 {
2878// TODO: Pull in these bits
2879 return false;
2880/*
2881 if (part == null || part.ParentGroup.IsAttachment) 3060 if (part == null || part.ParentGroup.IsAttachment)
2882 { 3061 {
2883 return true; 3062 return true;
@@ -2907,7 +3086,6 @@ namespace OpenSim.Region.Framework.Scenes
2907 return true; 3086 return true;
2908 3087
2909 return false; 3088 return false;
2910*/
2911 } 3089 }
2912 3090
2913 3091
@@ -2952,31 +3130,63 @@ namespace OpenSim.Region.Framework.Scenes
2952 ResetMoveToTarget(); 3130 ResetMoveToTarget();
2953 3131
2954 Velocity = Vector3.Zero; 3132 Velocity = Vector3.Zero;
3133 m_AngularVelocity = Vector3.Zero;
2955 3134
2956 part.AddSittingAvatar(this); 3135 part.AddSittingAvatar(UUID);
2957 3136
2958 Vector3 cameraAtOffset = part.GetCameraAtOffset(); 3137 Vector3 cameraAtOffset = part.GetCameraAtOffset();
2959 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3138 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2960 bool forceMouselook = part.GetForceMouselook(); 3139 bool forceMouselook = part.GetForceMouselook();
2961 3140
2962 ControllingClient.SendSitResponse( 3141 m_bodyRot = Orientation;
2963 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3142
3143 if (!part.IsRoot)
3144 {
3145 Orientation = part.RotationOffset * Orientation;
3146 offset = offset * part.RotationOffset;
3147 offset += part.OffsetPosition;
2964 3148
2965 // not using autopilot 3149 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3150 {
3151 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3152 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3153 }
3154 else
3155 {
3156 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3157 cameraAtOffset += part.OffsetPosition;
3158 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3159 cameraEyeOffset += part.OffsetPosition;
3160 }
3161
3162 }
2966 3163
2967 Rotation = Orientation;
2968 m_pos = offset; 3164 m_pos = offset;
2969 3165
3166 ControllingClient.SendSitResponse(
3167 part.ParentGroup.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
3168
3169
2970 m_requestedSitTargetID = 0; 3170 m_requestedSitTargetID = 0;
3171 part.ParentGroup.AddAvatar(UUID);
2971 3172
2972 ParentPart = part; 3173 ParentPart = part;
2973 ParentID = part.LocalId; 3174 ParentID = part.LocalId;
3175
3176 SendAvatarDataToAllAgents();
3177
3178/*
2974 if(status == 3) 3179 if(status == 3)
2975 Animator.TrySetMovementAnimation("SIT_GROUND"); 3180 Animator.TrySetMovementAnimation("SIT_GROUND");
2976 else 3181 else
2977 Animator.TrySetMovementAnimation("SIT"); 3182 Animator.TrySetMovementAnimation("SIT");
2978 SendAvatarDataToAllClients(); 3183*/
3184 if (status == 3)
3185 sitAnimation = "SIT_GROUND";
3186 else
3187 sitAnimation = "SIT";
2979 3188
3189 Animator.SetMovementAnimations("SIT");
2980 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3190 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2981 } 3191 }
2982 3192
@@ -3012,40 +3222,27 @@ namespace OpenSim.Region.Framework.Scenes
3012 3222
3013 //Quaternion result = (sitTargetOrient * vq) * nq; 3223 //Quaternion result = (sitTargetOrient * vq) * nq;
3014 3224
3015 double x, y, z, m1, m2; 3225 double x, y, z, m;
3016 3226
3017 Quaternion r = sitTargetOrient; 3227 Quaternion r = sitTargetOrient;
3018 m1 = r.X * r.X + r.Y * r.Y; 3228 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3019 m2 = r.Z * r.Z + r.W * r.W;
3020 3229
3021 // Rotate the vector <0, 0, 1> 3230 if (Math.Abs(1.0 - m) > 0.000001)
3022 x = 2 * (r.X * r.Z + r.Y * r.W);
3023 y = 2 * (-r.X * r.W + r.Y * r.Z);
3024 z = m2 - m1;
3025
3026 // Set m to be the square of the norm of r.
3027 double m = m1 + m2;
3028
3029 // This constant is emperically determined to be what is used in SL.
3030 // See also http://opensimulator.org/mantis/view.php?id=7096
3031 double offset = 0.05;
3032
3033 // Normally m will be ~ 1, but if someone passed a handcrafted quaternion
3034 // to llSitTarget with values so small that squaring them is rounded off
3035 // to zero, then m could be zero. The result of this floating point
3036 // round off error (causing us to skip this impossible normalization)
3037 // is only 5 cm.
3038 if (m > 0.000001)
3039 { 3231 {
3040 offset /= m; 3232 m = 1.0 / Math.Sqrt(m);
3233 r.X *= (float)m;
3234 r.Y *= (float)m;
3235 r.Z *= (float)m;
3236 r.W *= (float)m;
3041 } 3237 }
3042 3238
3239 x = 2 * (r.X * r.Z + r.Y * r.W);
3240 y = 2 * (-r.X * r.W + r.Y * r.Z);
3241 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3043 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3242 Vector3 up = new Vector3((float)x, (float)y, (float)z);
3044 Vector3 sitOffset = up * (float)offset; 3243 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
3045 3244
3046 // sitOffset is in Avatar Center coordinates: from origin to 'sitTargetPos + SIT_TARGET_ADJUSTMENT'. 3245 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3047 // So, we need to _substract_ it to get to the origin of the Avatar Center.
3048 Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
3049 Quaternion newRot; 3246 Quaternion newRot;
3050 3247
3051 if (part.IsRoot) 3248 if (part.IsRoot)
@@ -3078,19 +3275,22 @@ namespace OpenSim.Region.Framework.Scenes
3078// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3275// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
3079 } 3276 }
3080 3277
3081 ParentPart = part; 3278 part.ParentGroup.AddAvatar(UUID);
3279 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
3082 ParentID = m_requestedSitTargetID; 3280 ParentID = m_requestedSitTargetID;
3083 m_AngularVelocity = Vector3.Zero; 3281 m_AngularVelocity = Vector3.Zero;
3084 Velocity = Vector3.Zero; 3282 Velocity = Vector3.Zero;
3085 RemoveFromPhysicalScene(); 3283 RemoveFromPhysicalScene();
3086 3284
3087 String sitAnimation = "SIT"; 3285 SendAvatarDataToAllAgents();
3286
3287 sitAnimation = "SIT";
3088 if (!String.IsNullOrEmpty(part.SitAnimation)) 3288 if (!String.IsNullOrEmpty(part.SitAnimation))
3089 { 3289 {
3090 sitAnimation = part.SitAnimation; 3290 sitAnimation = part.SitAnimation;
3091 } 3291 }
3092 Animator.TrySetMovementAnimation(sitAnimation); 3292// Animator.TrySetMovementAnimation(sitAnimation);
3093 SendAvatarDataToAllClients(); 3293 Animator.SetMovementAnimations("SIT");
3094 TriggerScenePresenceUpdated(); 3294 TriggerScenePresenceUpdated();
3095 } 3295 }
3096 } 3296 }
@@ -3102,10 +3302,14 @@ namespace OpenSim.Region.Framework.Scenes
3102 3302
3103// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3303// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
3104 m_AngularVelocity = Vector3.Zero; 3304 m_AngularVelocity = Vector3.Zero;
3105 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3305 sitAnimation = "SIT_GROUND_CONSTRAINED";
3106 TriggerScenePresenceUpdated(); 3306// Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3307// TriggerScenePresenceUpdated();
3107 SitGround = true; 3308 SitGround = true;
3108 RemoveFromPhysicalScene(); 3309 RemoveFromPhysicalScene();
3310
3311 Animator.SetMovementAnimations("SITGROUND");
3312 TriggerScenePresenceUpdated();
3109 } 3313 }
3110 3314
3111 /// <summary> 3315 /// <summary>
@@ -3129,85 +3333,68 @@ namespace OpenSim.Region.Framework.Scenes
3129 TriggerScenePresenceUpdated(); 3333 TriggerScenePresenceUpdated();
3130 } 3334 }
3131 3335
3336 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
3337 {
3338 Animator.avnChangeAnim(animID, addRemove, sendPack);
3339 }
3340
3341
3342
3132 /// <summary> 3343 /// <summary>
3133 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3344 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
3134 /// </summary> 3345 /// </summary>
3135 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3346 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
3136 /// <param name="thisAddSpeedModifier"> 3347 /// <param name="thisAddSpeedModifier">
3137 /// Optional additional speed modifier for this particular add. Default is 1</param> 3348 /// Optional additional speed modifier for this particular add. Default is 1</param>
3138 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) 3349 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
3139 { 3350 {
3140// m_log.DebugFormat( 3351 // m_log.DebugFormat(
3141// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", 3352 // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3142// vec, Rotation, thisAddSpeedModifier, Name); 3353 // vec, Rotation, thisAddSpeedModifier, Name);
3143
3144 Quaternion rot = Rotation;
3145 if (!Flying && PresenceType != PresenceType.Npc)
3146 {
3147 // The only situation in which we care about X and Y is avatar flying. The rest of the time
3148 // these parameters are not relevant for determining avatar movement direction and cause issues such
3149 // as wrong walk speed if the camera is rotated.
3150 rot.X = 0;
3151 rot.Y = 0;
3152 rot.Normalize();
3153 }
3154 3354
3155 Vector3 direc = vec * rot; 3355 // rotate from avatar coord space to world
3356 // for now all controls assume this is only a rotation around Z
3357 // if not all checks below need to be done before this rotation
3358 Vector3 direc = vec * Rotation;
3156 direc.Normalize(); 3359 direc.Normalize();
3157 3360
3158 if (Flying != FlyingOld) // add for fly velocity control 3361 // mouse look situation ?
3159 {
3160 FlyingOld = Flying; // add for fly velocity control
3161 if (!Flying)
3162 WasFlying = true; // add for fly velocity control
3163 }
3164
3165 if (IsColliding)
3166 WasFlying = false; // add for fly velocity control
3167
3168 if ((vec.Z == 0f) && !Flying) 3362 if ((vec.Z == 0f) && !Flying)
3169 direc.Z = 0f; // Prevent camera WASD up. 3363 direc.Z = 0f; // Prevent camera WASD up.
3170 3364
3365 // odd rescalings
3171 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; 3366 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
3172 3367
3173// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3368 // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
3174 3369
3175 if (PhysicsActor != null) 3370 if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
3176 { 3371 {
3177 if (Flying) 3372 if (breaking)
3178 { 3373 direc.Z = -9999f; //hack to tell physics to stop on Z
3374 else
3375 direc = Vector3.Zero;
3376 }
3377 else if (Flying)
3378 {
3379 if (IsColliding && direc.Z < 0)
3380 // landing situation, prevent avatar moving or it may fail to land
3381 // animator will handle this condition and do the land
3382 direc = Vector3.Zero;
3383 else
3179 direc *= 4.0f; 3384 direc *= 4.0f;
3180 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 3385 }
3181 //if (controlland) 3386 else if (IsColliding)
3182 // m_log.Info("[AGENT]: landCommand"); 3387 {
3183 //if (IsColliding) 3388 if (direc.Z > 2.0f) // reinforce jumps
3184 // m_log.Info("[AGENT]: colliding");
3185 //if (Flying && IsColliding && controlland)
3186 //{
3187 // StopFlying();
3188 // m_log.Info("[AGENT]: Stop Flying");
3189 //}
3190 }
3191 if (Animator.Falling && WasFlying) // if falling from flying, disable motion add
3192 { 3389 {
3193 direc *= 0.0f; 3390 direc.Z *= 2.6f;
3194 }
3195 else if (!Flying && IsColliding)
3196 {
3197 if (direc.Z > 2.0f)
3198 {
3199 direc.Z *= 2.6f;
3200
3201 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
3202// Animator.TrySetMovementAnimation("PREJUMP");
3203// Animator.TrySetMovementAnimation("JUMP");
3204 }
3205 } 3391 }
3392 else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3393 direc.Z = 0;
3206 } 3394 }
3207 3395
3208// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); 3396 // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
3209 3397
3210 // TODO: Add the force instead of only setting it to support multiple forces per frame?
3211 m_forceToApply = direc; 3398 m_forceToApply = direc;
3212 Animator.UpdateMovementAnimations(); 3399 Animator.UpdateMovementAnimations();
3213 } 3400 }
@@ -3218,27 +3405,26 @@ namespace OpenSim.Region.Framework.Scenes
3218 3405
3219 public override void Update() 3406 public override void Update()
3220 { 3407 {
3408 const float ROTATION_TOLERANCE = 0.01f;
3409 const float VELOCITY_TOLERANCE = 0.001f;
3410 const float POSITION_TOLERANCE = 0.05f;
3411
3221 if (IsChildAgent == false) 3412 if (IsChildAgent == false)
3222 { 3413 {
3414 CheckForBorderCrossing();
3415
3416 if (IsInTransit)
3417 return;
3418
3223 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3419 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
3224 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3420 // grab the latest PhysicsActor velocity, whereas m_velocity is often
3225 // storing a requested force instead of an actual traveling velocity 3421 // storing a requested force instead of an actual traveling velocity
3226 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn) 3422 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn)
3227 SendAvatarDataToAllClients(); 3423 SendAvatarDataToAllAgents();
3228 3424
3229 // Allow any updates for sitting avatars to that llSetPrimitiveLinkParams() can work for very 3425 if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
3230 // small increments (e.g. sit position adjusters). An alternative may be to eliminate the tolerance 3426 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
3231 // checks on all updates but the ramifications of this would need careful consideration. 3427 !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
3232 bool updateClients
3233 = IsSatOnObject && (Rotation != m_lastRotation || Velocity != m_lastVelocity || m_pos != m_lastPosition);
3234
3235 if (!updateClients)
3236 updateClients
3237 = !Rotation.ApproxEquals(m_lastRotation, Scene.RootRotationUpdateTolerance)
3238 || !Velocity.ApproxEquals(m_lastVelocity, Scene.RootVelocityUpdateTolerance)
3239 || !m_pos.ApproxEquals(m_lastPosition, Scene.RootPositionUpdateTolerance);
3240
3241 if (updateClients)
3242 { 3428 {
3243 SendTerseUpdateToAllClients(); 3429 SendTerseUpdateToAllClients();
3244 3430
@@ -3248,9 +3434,6 @@ namespace OpenSim.Region.Framework.Scenes
3248 m_lastVelocity = Velocity; 3434 m_lastVelocity = Velocity;
3249 } 3435 }
3250 3436
3251 if (Scene.AllowAvatarCrossing)
3252 CheckForBorderCrossing();
3253
3254 CheckForSignificantMovement(); // sends update to the modules. 3437 CheckForSignificantMovement(); // sends update to the modules.
3255 } 3438 }
3256 } 3439 }
@@ -3259,8 +3442,38 @@ namespace OpenSim.Region.Framework.Scenes
3259 3442
3260 #region Update Client(s) 3443 #region Update Client(s)
3261 3444
3445 public void SendUpdateToAgent(ScenePresence p)
3446 {
3447 IClientAPI remoteClient = p.ControllingClient;
3448
3449 if (remoteClient.IsActive)
3450 {
3451 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3452 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3453 m_scene.StatsReporter.AddAgentUpdates(1);
3454 }
3455 }
3456
3457 public void SendFullUpdateToClient(IClientAPI remoteClient)
3458 {
3459 if (remoteClient.IsActive)
3460 {
3461 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3462 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3463 m_scene.StatsReporter.AddAgentUpdates(1);
3464 }
3465 }
3466
3467 // this is diferente from SendTerseUpdateToClient
3468 // this sends bypassing entities updates
3469 public void SendAgentTerseUpdate(ISceneEntity p)
3470 {
3471 ControllingClient.SendAgentTerseUpdate(p);
3472 }
3473
3262 /// <summary> 3474 /// <summary>
3263 /// Sends a location update to the client connected to this scenePresence 3475 /// Sends a location update to the client connected to this scenePresence
3476 /// via entity updates
3264 /// </summary> 3477 /// </summary>
3265 /// <param name="remoteClient"></param> 3478 /// <param name="remoteClient"></param>
3266 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3479 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -3269,31 +3482,7 @@ namespace OpenSim.Region.Framework.Scenes
3269 // server. 3482 // server.
3270 if (remoteClient.IsActive) 3483 if (remoteClient.IsActive)
3271 { 3484 {
3272 if (Scene.RootTerseUpdatePeriod > 1)
3273 {
3274// Console.WriteLine(
3275// "{0} {1} {2} {3} {4} {5} for {6} to {7}",
3276// remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f), Name, remoteClient.Name);
3277 if (remoteClient.AgentId != UUID
3278 && !remoteClient.SceneAgent.IsChildAgent
3279 && m_terseUpdateCount % Scene.RootTerseUpdatePeriod != 0
3280 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3281 {
3282// m_log.DebugFormat("[SCENE PRESENCE]: Discarded update from {0} to {1}, args {2} {3} {4} {5} {6} {7}",
3283// Name, remoteClient.Name, remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f));
3284
3285 return;
3286 }
3287 }
3288
3289 if (Scene.ChildTerseUpdatePeriod > 1
3290 && remoteClient.SceneAgent.IsChildAgent
3291 && m_terseUpdateCount % Scene.ChildTerseUpdatePeriod != 0
3292 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3293 return;
3294
3295 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3485 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3296
3297 remoteClient.SendEntityUpdate( 3486 remoteClient.SendEntityUpdate(
3298 this, 3487 this,
3299 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3488 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -3303,6 +3492,38 @@ namespace OpenSim.Region.Framework.Scenes
3303 } 3492 }
3304 } 3493 }
3305 3494
3495 public void SendTerseUpdateToAgent(ScenePresence p)
3496 {
3497 IClientAPI remoteClient = p.ControllingClient;
3498
3499 if (!remoteClient.IsActive)
3500 return;
3501
3502 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3503 return;
3504
3505 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3506 remoteClient.SendEntityUpdate(
3507 this,
3508 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3509 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3510
3511 m_scene.StatsReporter.AddAgentUpdates(1);
3512 }
3513
3514 public void SendTerseUpdateToAgentNF(ScenePresence p)
3515 {
3516 IClientAPI remoteClient = p.ControllingClient;
3517 if (remoteClient.IsActive)
3518 {
3519 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3520 remoteClient.SendEntityUpdate(this,
3521 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3522 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3523 m_scene.StatsReporter.AddAgentUpdates(1);
3524 }
3525 }
3526
3306 3527
3307 // vars to support reduced update frequency when velocity is unchanged 3528 // vars to support reduced update frequency when velocity is unchanged
3308 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3529 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -3331,10 +3552,6 @@ namespace OpenSim.Region.Framework.Scenes
3331 float speed = Velocity.Length(); 3552 float speed = Velocity.Length();
3332 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity); 3553 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity);
3333 3554
3334// m_log.DebugFormat(
3335// "[SCENE PRESENCE]: Delta-v {0}, lastVelocity {1}, Velocity {2} for {3} in {4}",
3336// velocidyDiff, lastVelocitySentToAllClients, Velocity, Name, Scene.Name);
3337
3338 // assuming 5 ms. worst case precision for timer, use 2x that 3555 // assuming 5 ms. worst case precision for timer, use 2x that
3339 // for distance error threshold 3556 // for distance error threshold
3340 float distanceErrorThreshold = speed * 0.01f; 3557 float distanceErrorThreshold = speed * 0.01f;
@@ -3343,18 +3560,13 @@ namespace OpenSim.Region.Framework.Scenes
3343 || Math.Abs(distanceError) > distanceErrorThreshold 3560 || Math.Abs(distanceError) > distanceErrorThreshold
3344 || velocityDiff > 0.01f) // did velocity change from last update? 3561 || velocityDiff > 0.01f) // did velocity change from last update?
3345 { 3562 {
3346// m_log.DebugFormat(
3347// "[SCENE PRESENCE]: Update triggered with speed {0}, distanceError {1}, distanceThreshold {2}, delta-v {3} for {4} in {5}",
3348// speed, distanceError, distanceErrorThreshold, velocidyDiff, Name, Scene.Name);
3349
3350 lastVelocitySentToAllClients = Velocity; 3563 lastVelocitySentToAllClients = Velocity;
3351 lastTerseUpdateToAllClientsTick = currentTick; 3564 lastTerseUpdateToAllClientsTick = currentTick;
3352 lastPositionSentToAllClients = OffsetPosition; 3565 lastPositionSentToAllClients = OffsetPosition;
3353 3566
3354 m_terseUpdateCount++; 3567 // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3355 3568// m_scene.ForEachClient(SendTerseUpdateToClient);
3356// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); 3569 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
3357 m_scene.ForEachClient(SendTerseUpdateToClient);
3358 } 3570 }
3359 TriggerScenePresenceUpdated(); 3571 TriggerScenePresenceUpdated();
3360 } 3572 }
@@ -3379,36 +3591,39 @@ namespace OpenSim.Region.Framework.Scenes
3379 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); 3591 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
3380 } 3592 }
3381 3593
3382 public void SendInitialDataToClient() 3594 public void SendInitialDataToMe()
3383 { 3595 {
3384 SentInitialDataToClient = true;
3385
3386 // Send all scene object to the new client 3596 // Send all scene object to the new client
3387 WorkManager.RunJob("SendInitialDataToClient", delegate 3597 Util.FireAndForget(delegate
3388 { 3598 {
3389// m_log.DebugFormat(
3390// "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}",
3391// IsChildAgent ? "child" : "root", Name, Scene.Name, m_teleportFlags);
3392
3393 // we created a new ScenePresence (a new child agent) in a fresh region. 3599 // we created a new ScenePresence (a new child agent) in a fresh region.
3394 // Request info about all the (root) agents in this region 3600 // Request info about all the (root) agents in this region
3395 // Note: This won't send data *to* other clients in that region (children don't send) 3601 // Note: This won't send data *to* other clients in that region (children don't send)
3396 SendOtherAgentsAvatarDataToClient(); 3602 if (m_teleportFlags <= 0)
3397 SendOtherAgentsAppearanceToClient(); 3603 {
3604 ILandChannel landch = m_scene.LandChannel;
3605 if (landch != null)
3606 {
3607 landch.sendClientInitialLandInfo(ControllingClient);
3608 }
3609 }
3398 3610
3611 SendOtherAgentsAvatarFullToMe();
3399 EntityBase[] entities = Scene.Entities.GetEntities(); 3612 EntityBase[] entities = Scene.Entities.GetEntities();
3400 foreach (EntityBase e in entities) 3613 foreach (EntityBase e in entities)
3401 { 3614 {
3402 if (e != null && e is SceneObjectGroup) 3615 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
3403 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3616 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
3404 } 3617 }
3405 }, null, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), false, true); 3618 });
3406 } 3619 }
3407 3620
3408 /// <summary> 3621 /// <summary>
3409 /// Do everything required once a client completes its movement into a region and becomes 3622 /// Do everything required once a client completes its movement into a region and becomes
3410 /// a root agent. 3623 /// a root agent.
3411 /// </summary> 3624 /// </summary>
3625 ///
3626/* only called from on place, do done inline there
3412 private void ValidateAndSendAppearanceAndAgentData() 3627 private void ValidateAndSendAppearanceAndAgentData()
3413 { 3628 {
3414 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); 3629 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
@@ -3422,46 +3637,70 @@ namespace OpenSim.Region.Framework.Scenes
3422 // to see if all the baked textures are already here. 3637 // to see if all the baked textures are already here.
3423 if (m_scene.AvatarFactory != null) 3638 if (m_scene.AvatarFactory != null)
3424 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); 3639 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
3425 3640
3426 // If we aren't using a cached appearance, then clear out the baked textures 3641 // If we aren't using a cached appearance, then clear out the baked textures
3427 if (!cachedappearance) 3642 if (!cachedappearance)
3428 { 3643 {
3429 Appearance.ResetAppearance();
3430 if (m_scene.AvatarFactory != null) 3644 if (m_scene.AvatarFactory != null)
3431 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3645 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
3432 } 3646 }
3433
3434 // This agent just became root. We are going to tell everyone about it. The process of
3435 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it
3436 // again here... this comes after the cached appearance check because the avatars
3437 // appearance goes into the avatar update packet
3438 SendAvatarDataToAllClients();
3439 3647
3440 // This invocation always shows up in the viewer logs as an error. Is it needed? 3648 // send avatar object to all viewers so they cross it into region
3441 SendAppearanceToClient(this); 3649 bool newhide = m_currentParcelHide;
3650 m_currentParcelHide = false;
3442 3651
3443 // If we are using the the cached appearance then send it out to everyone 3652 SendAvatarDataToAllAgents();
3444 if (cachedappearance)
3445 {
3446 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
3447 3653
3448 // If the avatars baked textures are all in the cache, then we have a 3654 // now hide
3449 // complete appearance... send it out, if not, then we'll send it when 3655 if (newhide)
3450 // the avatar finishes updating its appearance 3656 {
3451 SendAppearanceToAllOtherClients(); 3657 ParcelLoginCheck(m_currentParcelUUID);
3658 m_currentParcelHide = true;
3452 } 3659 }
3453 }
3454 3660
3455 public void SendAvatarDataToAllClients() 3661 SendAppearanceToAgent(this);
3662
3663 m_inTransit = false;
3664
3665 SendAppearanceToAllOtherAgents();
3666
3667 if(Animator!= null)
3668 Animator.SendAnimPack();
3669 }
3670*/
3671 /// <summary>
3672 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3673 /// can be either a child or root
3674 /// </summary>
3675 public void SendOtherAgentsAvatarFullToMe()
3456 { 3676 {
3457 SendAvatarDataToAllClients(true); 3677 int count = 0;
3678 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
3679 {
3680 // only send information about other root agents
3681 if (p.UUID == UUID)
3682 return;
3683
3684 // get the avatar, then a kill if can't see it
3685 p.SendInitialAvatarDataToAgent(this);
3686
3687 if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200)
3688 return;
3689
3690 p.SendAppearanceToAgentNF(this);
3691 p.SendAnimPackToAgentNF(this);
3692 p.SendAttachmentsToAgentNF(this);
3693 count++;
3694 });
3695
3696 m_scene.StatsReporter.AddAgentUpdates(count);
3458 } 3697 }
3459 3698
3460 /// <summary> 3699 /// <summary>
3461 /// Send this agent's avatar data to all other root and child agents in the scene 3700 /// Send this agent's avatar data to all other root and child agents in the scene
3462 /// This agent must be root. This avatar will receive its own update. 3701 /// This agent must be root. This avatar will receive its own update.
3463 /// </summary> 3702 /// </summary>
3464 public void SendAvatarDataToAllClients(bool full) 3703 public void SendAvatarDataToAllAgents()
3465 { 3704 {
3466 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); 3705 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
3467 // only send update from root agents to other clients; children are only "listening posts" 3706 // only send update from root agents to other clients; children are only "listening posts"
@@ -3470,64 +3709,73 @@ namespace OpenSim.Region.Framework.Scenes
3470 m_log.WarnFormat( 3709 m_log.WarnFormat(
3471 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", 3710 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
3472 Name, Scene.RegionInfo.RegionName); 3711 Name, Scene.RegionInfo.RegionName);
3473
3474 return; 3712 return;
3475 } 3713 }
3476 3714
3477 m_lastSize = Appearance.AvatarSize; 3715 m_lastSize = Appearance.AvatarSize;
3478
3479 int count = 0; 3716 int count = 0;
3717
3480 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3718 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3481 { 3719 {
3482 if (full) 3720 SendAvatarDataToAgent(scenePresence);
3483 SendAvatarDataToClient(scenePresence);
3484 else
3485 scenePresence.ControllingClient.SendAvatarDataImmediate(this);
3486 count++; 3721 count++;
3487 }); 3722 });
3488 3723
3489 m_scene.StatsReporter.AddAgentUpdates(count); 3724 m_scene.StatsReporter.AddAgentUpdates(count);
3490 } 3725 }
3491 3726 // sends avatar object to all clients so they cross it into region
3492 /// <summary> 3727 // then sends kills to hide
3493 /// Send avatar data for all other root agents to this agent, this agent 3728 public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
3494 /// can be either a child or root
3495 /// </summary>
3496 public void SendOtherAgentsAvatarDataToClient()
3497 { 3729 {
3730 m_lastSize = Appearance.AvatarSize;
3498 int count = 0; 3731 int count = 0;
3499 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3732 foreach (ScenePresence p in presences)
3500 { 3733 {
3501 // only send information about other root agents 3734 p.ControllingClient.SendAvatarDataImmediate(this);
3502 if (scenePresence.UUID == UUID) 3735 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3503 return; 3736 // either just kill the object
3504 3737 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3505 scenePresence.SendAvatarDataToClient(this); 3738 // or also attachments viewer may still know about
3506 count++; 3739 SendKillTo(p);
3507 }); 3740 count++;
3508 3741 }
3509 m_scene.StatsReporter.AddAgentUpdates(count); 3742 m_scene.StatsReporter.AddAgentUpdates(count);
3510 } 3743 }
3511 3744
3745 public void SendInitialAvatarDataToAgent(ScenePresence p)
3746 {
3747 p.ControllingClient.SendAvatarDataImmediate(this);
3748 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3749 // either just kill the object
3750 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3751 // or also attachments viewer may still know about
3752 SendKillTo(p);
3753 }
3754
3512 /// <summary> 3755 /// <summary>
3513 /// Send avatar data to an agent. 3756 /// Send avatar data to an agent.
3514 /// </summary> 3757 /// </summary>
3515 /// <param name="avatar"></param> 3758 /// <param name="avatar"></param>
3516 public void SendAvatarDataToClient(ScenePresence avatar) 3759 public void SendAvatarDataToAgent(ScenePresence avatar)
3517 { 3760 {
3518 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToClient from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3761 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
3519 3762 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3763 return;
3520 avatar.ControllingClient.SendAvatarDataImmediate(this); 3764 avatar.ControllingClient.SendAvatarDataImmediate(this);
3521 Animator.SendAnimPackToClient(avatar.ControllingClient); 3765 }
3766
3767 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3768 {
3769 avatar.ControllingClient.SendAvatarDataImmediate(this);
3522 } 3770 }
3523 3771
3524 /// <summary> 3772 /// <summary>
3525 /// Send this agent's appearance to all other root and child agents in the scene 3773 /// Send this agent's appearance to all other root and child agents in the scene
3526 /// This agent must be root. 3774 /// This agent must be root.
3527 /// </summary> 3775 /// </summary>
3528 public void SendAppearanceToAllOtherClients() 3776 public void SendAppearanceToAllOtherAgents()
3529 { 3777 {
3530// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherClients: {0} {1}", Name, UUID); 3778 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3531 3779
3532 // only send update from root agents to other clients; children are only "listening posts" 3780 // only send update from root agents to other clients; children are only "listening posts"
3533 if (IsChildAgent) 3781 if (IsChildAgent)
@@ -3538,56 +3786,80 @@ namespace OpenSim.Region.Framework.Scenes
3538 3786
3539 return; 3787 return;
3540 } 3788 }
3541 3789
3542 int count = 0; 3790 int count = 0;
3543 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3791 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3544 { 3792 {
3545 // only send information to other root agents 3793 // only send information to other root agents
3546 if (scenePresence.UUID == UUID) 3794 if (scenePresence.UUID == UUID)
3547 return; 3795 return;
3548
3549 SendAppearanceToClient(scenePresence);
3550 count++;
3551 });
3552 3796
3797 SendAppearanceToAgent(scenePresence);
3798 count++;
3799 });
3553 m_scene.StatsReporter.AddAgentUpdates(count); 3800 m_scene.StatsReporter.AddAgentUpdates(count);
3554 } 3801 }
3555 3802
3556 /// <summary> 3803 public void SendAppearanceToAgent(ScenePresence avatar)
3557 /// Send appearance from all other root agents to this agent. this agent
3558 /// can be either root or child
3559 /// </summary>
3560 public void SendOtherAgentsAppearanceToClient()
3561 { 3804 {
3562// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToClient {0} {1}", Name, UUID); 3805 // m_log.DebugFormat(
3806 // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3807 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3808 return;
3809 SendAppearanceToAgentNF(avatar);
3810 }
3563 3811
3564 int count = 0; 3812 public void SendAppearanceToAgentNF(ScenePresence avatar)
3565 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3813 {
3566 { 3814 avatar.ControllingClient.SendAppearance(
3567 // only send information about other root agents 3815 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3568 if (scenePresence.UUID == UUID) 3816 }
3569 return;
3570
3571 scenePresence.SendAppearanceToClient(this);
3572 count++;
3573 });
3574 3817
3575 m_scene.StatsReporter.AddAgentUpdates(count); 3818 public void SendAnimPackToAgent(ScenePresence p)
3819 {
3820 if (IsChildAgent || Animator == null)
3821 return;
3822
3823 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3824 return;
3825
3826 Animator.SendAnimPackToClient(p.ControllingClient);
3576 } 3827 }
3577 3828
3578 /// <summary> 3829 public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3579 /// Send appearance data to an agent.
3580 /// </summary>
3581 /// <param name="avatar"></param>
3582 public void SendAppearanceToClient(ScenePresence avatar)
3583 { 3830 {
3584// m_log.DebugFormat( 3831 if (IsChildAgent)
3585// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3832 return;
3586 3833
3587 avatar.ControllingClient.SendAppearance( 3834 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3588 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3835 return;
3589 3836
3590 3837 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3838 }
3839
3840 public void SendAnimPackToAgentNF(ScenePresence p)
3841 {
3842 if (IsChildAgent || Animator == null)
3843 return;
3844 Animator.SendAnimPackToClient(p.ControllingClient);
3845 }
3846
3847 public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3848 {
3849 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3850 }
3851
3852 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3853 {
3854 if (IsChildAgent)
3855 return;
3856
3857 m_scene.ForEachScenePresence(delegate(ScenePresence p)
3858 {
3859 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3860 return;
3861 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3862 });
3591 } 3863 }
3592 3864
3593 #endregion 3865 #endregion
@@ -3611,6 +3883,7 @@ namespace OpenSim.Region.Framework.Scenes
3611 m_lastChildAgentUpdatePosition = AbsolutePosition; 3883 m_lastChildAgentUpdatePosition = AbsolutePosition;
3612// m_lastChildAgentUpdateCamPosition = CameraPosition; 3884// m_lastChildAgentUpdateCamPosition = CameraPosition;
3613 3885
3886/* cadu is not used
3614 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3887 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3615 cadu.ActiveGroupID = UUID.Zero.Guid; 3888 cadu.ActiveGroupID = UUID.Zero.Guid;
3616 cadu.AgentID = UUID.Guid; 3889 cadu.AgentID = UUID.Guid;
@@ -3624,6 +3897,7 @@ namespace OpenSim.Region.Framework.Scenes
3624 3897
3625 // Throttles 3898 // Throttles
3626 float multiplier = 1; 3899 float multiplier = 1;
3900
3627 int childRegions = KnownRegionCount; 3901 int childRegions = KnownRegionCount;
3628 if (childRegions != 0) 3902 if (childRegions != 0)
3629 multiplier = 1f / childRegions; 3903 multiplier = 1f / childRegions;
@@ -3634,9 +3908,22 @@ namespace OpenSim.Region.Framework.Scenes
3634 3908
3635 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); 3909 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
3636 cadu.Velocity = Velocity; 3910 cadu.Velocity = Velocity;
3637 3911*/
3638 AgentPosition agentpos = new AgentPosition(); 3912 AgentPosition agentpos = new AgentPosition();
3639 agentpos.CopyFrom(cadu, ControllingClient.SessionId); 3913// agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3914
3915 agentpos.AgentID = new UUID(UUID.Guid);
3916 agentpos.SessionID = ControllingClient.SessionId;
3917
3918 agentpos.Size = Appearance.AvatarSize;
3919
3920 agentpos.Center = CameraPosition;
3921 agentpos.Far = DrawDistance;
3922 agentpos.Position = AbsolutePosition;
3923 agentpos.Velocity = Velocity;
3924 agentpos.RegionHandle = RegionHandle;
3925 agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
3926
3640 3927
3641 // Let's get this out of the update loop 3928 // Let's get this out of the update loop
3642 Util.FireAndForget( 3929 Util.FireAndForget(
@@ -3657,7 +3944,7 @@ namespace OpenSim.Region.Framework.Scenes
3657 protected void CheckForBorderCrossing() 3944 protected void CheckForBorderCrossing()
3658 { 3945 {
3659 // Check that we we are not a child 3946 // Check that we we are not a child
3660 if (IsChildAgent) 3947 if (IsChildAgent || IsInTransit)
3661 return; 3948 return;
3662 3949
3663 // If we don't have a PhysActor, we can't cross anyway 3950 // If we don't have a PhysActor, we can't cross anyway
@@ -3667,79 +3954,67 @@ namespace OpenSim.Region.Framework.Scenes
3667 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3954 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3668 return; 3955 return;
3669 3956
3670 if (IsInTransit)
3671 return;
3672
3673 Vector3 pos2 = AbsolutePosition; 3957 Vector3 pos2 = AbsolutePosition;
3674 Vector3 origPosition = pos2;
3675 Vector3 vel = Velocity; 3958 Vector3 vel = Velocity;
3676 3959
3677 // Compute the future avatar position. 3960 float timeStep = 0.1f;
3678 // If the avatar will be crossing, we force the crossing to happen now 3961 pos2.X += vel.X * timeStep;
3679 // in the hope that this will make the avatar movement smoother when crossing. 3962 pos2.Y += vel.Y * timeStep;
3680 pos2 += vel * 0.05f; 3963 pos2.Z += vel.Z * timeStep;
3681
3682 if (m_scene.PositionIsInCurrentRegion(pos2))
3683 return;
3684 3964
3685 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}", 3965// m_log.DebugFormat(
3686 LogHeader, Name, Scene.Name, pos2); 3966// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3687 3967// pos2, Name, Scene.Name);
3688 // Disconnect from the current region
3689 bool isFlying = Flying;
3690 RemoveFromPhysicalScene();
3691 3968
3692 // pos2 is the forcasted position so make that the 'current' position so the crossing 3969 if (Scene.PositionIsInCurrentRegion(pos2))
3693 // code will move us into the newly addressed region. 3970 return;
3694 m_pos = pos2;
3695 3971
3696 if (CrossToNewRegion()) 3972 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3697 { 3973 {
3698 AddToPhysicalScene(isFlying); 3974 // we don't have entity transfer module
3699 } 3975 Vector3 pos = AbsolutePosition;
3700 else 3976 float px = pos.X;
3701 { 3977 if (px < 0)
3702 // Tried to make crossing happen but it failed. 3978 pos.X += Velocity.X * 2;
3703 if (m_requestedSitTargetUUID == UUID.Zero) 3979 else if (px > m_scene.RegionInfo.RegionSizeX)
3704 { 3980 pos.X -= Velocity.X * 2;
3705 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); 3981
3706 3982 float py = pos.Y;
3707 Velocity = Vector3.Zero; 3983 if (py < 0)
3708 AbsolutePosition = EnforceSanityOnPosition(origPosition); 3984 pos.Y += Velocity.Y * 2;
3985 else if (py > m_scene.RegionInfo.RegionSizeY)
3986 pos.Y -= Velocity.Y * 2;
3709 3987
3710 AddToPhysicalScene(isFlying); 3988 Velocity = Vector3.Zero;
3711 } 3989 AbsolutePosition = pos;
3712 } 3990 }
3713 } 3991 }
3714 3992
3715 // Given a position, make sure it is within the current region. 3993 public void CrossToNewRegionFail()
3716 // If just outside some border, the returned position will be just inside the border on that side.
3717 private Vector3 EnforceSanityOnPosition(Vector3 origPosition)
3718 { 3994 {
3719 const float borderFudge = 0.1f; 3995 if (m_requestedSitTargetUUID == UUID.Zero)
3720 Vector3 ret = origPosition;
3721
3722 // Sanity checking on the position to make sure it is in the region we couldn't cross from
3723 float extentX = (float)m_scene.RegionInfo.RegionSizeX;
3724 float extentY = (float)m_scene.RegionInfo.RegionSizeY;
3725 IRegionCombinerModule combiner = m_scene.RequestModuleInterface<IRegionCombinerModule>();
3726 if (combiner != null)
3727 { 3996 {
3728 // If a mega-region, the size could be much bigger 3997 bool isFlying = Flying;
3729 Vector2 megaExtent = combiner.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 3998 RemoveFromPhysicalScene();
3730 extentX = megaExtent.X; 3999
3731 extentY = megaExtent.Y; 4000 Vector3 pos = AbsolutePosition;
3732 } 4001 float px = pos.X;
3733 if (ret.X < 0) 4002 if (px < 0)
3734 ret.X = borderFudge; 4003 pos.X += Velocity.X * 2;
3735 else if (ret.X >= extentX) 4004 else if (px > m_scene.RegionInfo.RegionSizeX)
3736 ret.X = extentX - borderFudge; 4005 pos.X -= Velocity.X * 2;
3737 if (ret.Y < 0) 4006
3738 ret.Y = borderFudge; 4007 float py = pos.Y;
3739 else if (ret.Y >= extentY) 4008 if (py < 0)
3740 ret.Y = extentY - borderFudge; 4009 pos.Y += Velocity.Y * 2;
4010 else if (py > m_scene.RegionInfo.RegionSizeY)
4011 pos.Y -= Velocity.Y * 2;
3741 4012
3742 return ret; 4013 Velocity = Vector3.Zero;
4014 AbsolutePosition = pos;
4015
4016 AddToPhysicalScene(isFlying);
4017 }
3743 } 4018 }
3744 4019
3745 /// <summary> 4020 /// <summary>
@@ -3750,16 +4025,25 @@ namespace OpenSim.Region.Framework.Scenes
3750 /// </summary> 4025 /// </summary>
3751 protected bool CrossToNewRegion() 4026 protected bool CrossToNewRegion()
3752 { 4027 {
4028 bool result = false;
4029// parcelRegionCross(false);
3753 try 4030 try
3754 { 4031 {
3755 return m_scene.CrossAgentToNewRegion(this, Flying); 4032 result = m_scene.CrossAgentToNewRegion(this, Flying);
3756 } 4033 }
3757 catch 4034 catch
3758 { 4035 {
3759 return m_scene.CrossAgentToNewRegion(this, false); 4036// result = m_scene.CrossAgentToNewRegion(this, false);
4037 return false;
3760 } 4038 }
4039 // if(!result)
4040 // parcelRegionCross(true);
4041
4042 return result;
4043
3761 } 4044 }
3762 4045
4046/* useless. Either use MakeChild or delete the presence
3763 public void Reset() 4047 public void Reset()
3764 { 4048 {
3765// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 4049// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3770,7 +4054,7 @@ namespace OpenSim.Region.Framework.Scenes
3770 4054
3771 Animator.ResetAnimations(); 4055 Animator.ResetAnimations();
3772 } 4056 }
3773 4057*/
3774 /// <summary> 4058 /// <summary>
3775 /// Computes which child agents to close when the scene presence moves to another region. 4059 /// Computes which child agents to close when the scene presence moves to another region.
3776 /// Removes those regions from m_knownRegions. 4060 /// Removes those regions from m_knownRegions.
@@ -3778,8 +4062,9 @@ namespace OpenSim.Region.Framework.Scenes
3778 /// <param name="newRegionX">The new region's x on the map</param> 4062 /// <param name="newRegionX">The new region's x on the map</param>
3779 /// <param name="newRegionY">The new region's y on the map</param> 4063 /// <param name="newRegionY">The new region's y on the map</param>
3780 /// <returns></returns> 4064 /// <returns></returns>
3781 public void CloseChildAgents(uint newRegionX, uint newRegionY) 4065 public void CloseChildAgents(ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY)
3782 { 4066 {
4067 uint newRegionX, newRegionY;
3783 List<ulong> byebyeRegions = new List<ulong>(); 4068 List<ulong> byebyeRegions = new List<ulong>();
3784 List<ulong> knownRegions = KnownRegionHandles; 4069 List<ulong> knownRegions = KnownRegionHandles;
3785 m_log.DebugFormat( 4070 m_log.DebugFormat(
@@ -3787,21 +4072,35 @@ namespace OpenSim.Region.Framework.Scenes
3787 knownRegions.Count, Scene.RegionInfo.RegionName); 4072 knownRegions.Count, Scene.RegionInfo.RegionName);
3788 //DumpKnownRegions(); 4073 //DumpKnownRegions();
3789 4074
4075 Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
4076
4077 uint x, y;
4078 spRegionSizeInfo regInfo;
4079
3790 foreach (ulong handle in knownRegions) 4080 foreach (ulong handle in knownRegions)
3791 { 4081 {
3792 // Don't close the agent on this region yet 4082 // Don't close the agent on this region yet
3793 if (handle != Scene.RegionInfo.RegionHandle) 4083 if (handle != Scene.RegionInfo.RegionHandle)
3794 { 4084 {
3795 uint x, y;
3796 Util.RegionHandleToRegionLoc(handle, out x, out y); 4085 Util.RegionHandleToRegionLoc(handle, out x, out y);
4086 if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo))
4087 {
3797 4088
3798// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 4089 // m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3799// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 4090 // m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
3800 float dist = (float)Math.Max(Scene.DefaultDrawDistance, 4091 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY,
3801 (float)Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY)); 4092 regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
3802 if (Util.IsOutsideView(dist, x, newRegionX, y, newRegionY)) 4093 {
4094 byebyeRegions.Add(handle);
4095 }
4096 }
4097 else
3803 { 4098 {
3804 byebyeRegions.Add(handle); 4099 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY,
4100 (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY))
4101 {
4102 byebyeRegions.Add(handle);
4103 }
3805 } 4104 }
3806 } 4105 }
3807 } 4106 }
@@ -3820,6 +4119,7 @@ namespace OpenSim.Region.Framework.Scenes
3820 foreach (ulong handle in byebyeRegions) 4119 foreach (ulong handle in byebyeRegions)
3821 { 4120 {
3822 RemoveNeighbourRegion(handle); 4121 RemoveNeighbourRegion(handle);
4122 Scene.CapsModule.DropChildSeed(UUID, handle);
3823 } 4123 }
3824 } 4124 }
3825 4125
@@ -3831,6 +4131,8 @@ namespace OpenSim.Region.Framework.Scenes
3831 /// </summary> 4131 /// </summary>
3832 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 4132 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3833 { 4133 {
4134 int oldgodlevel = GodLevel;
4135
3834 if (godStatus) 4136 if (godStatus)
3835 { 4137 {
3836 // For now, assign god level 200 to anyone 4138 // For now, assign god level 200 to anyone
@@ -3851,6 +4153,9 @@ namespace OpenSim.Region.Framework.Scenes
3851 } 4153 }
3852 4154
3853 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4155 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4156
4157 if(oldgodlevel != GodLevel)
4158 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3854 } 4159 }
3855 4160
3856 #region Child Agent Updates 4161 #region Child Agent Updates
@@ -3862,12 +4167,16 @@ namespace OpenSim.Region.Framework.Scenes
3862 return; 4167 return;
3863 4168
3864 CopyFrom(cAgentData); 4169 CopyFrom(cAgentData);
3865 4170
3866 m_updateAgentReceivedAfterTransferEvent.Set();
3867 } 4171 }
3868 4172
3869 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4173 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3870 4174
4175 private void RaiseUpdateThrottles()
4176 {
4177 m_scene.EventManager.TriggerThrottleUpdate(this);
4178 }
4179
3871 /// <summary> 4180 /// <summary>
3872 /// This updates important decision making data about a child agent 4181 /// This updates important decision making data about a child agent
3873 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 4182 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
@@ -3877,15 +4186,11 @@ namespace OpenSim.Region.Framework.Scenes
3877 if (!IsChildAgent) 4186 if (!IsChildAgent)
3878 return; 4187 return;
3879 4188
3880// m_log.DebugFormat( 4189 RegionHandle = cAgentData.RegionHandle;
3881// "[SCENE PRESENCE]: ChildAgentPositionUpdate for {0} in {1}, tRegion {2},{3}, rRegion {4},{5}, pos {6}",
3882// Name, Scene.Name, tRegionX, tRegionY, rRegionX, rRegionY, cAgentData.Position);
3883 4190
3884 // Find the distance (in meters) between the two regions 4191 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3885 // XXX: We cannot use Util.RegionLocToHandle() here because a negative value will silently overflow the 4192 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
3886 // uint 4193 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
3887 int shiftx = (int)(((int)rRegionX - (int)tRegionX) * Constants.RegionSize);
3888 int shifty = (int)(((int)rRegionY - (int)tRegionY) * Constants.RegionSize);
3889 4194
3890 Vector3 offset = new Vector3(shiftx, shifty, 0f); 4195 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3891 4196
@@ -3893,7 +4198,7 @@ namespace OpenSim.Region.Framework.Scenes
3893 // changes, then start using the agent's drawdistance rather than the 4198 // changes, then start using the agent's drawdistance rather than the
3894 // region's draw distance. 4199 // region's draw distance.
3895 DrawDistance = cAgentData.Far; 4200 DrawDistance = cAgentData.Far;
3896 // DrawDistance = Scene.DefaultDrawDistance; 4201// DrawDistance = Scene.DefaultDrawDistance;
3897 4202
3898 if (cAgentData.Position != marker) // UGH!! 4203 if (cAgentData.Position != marker) // UGH!!
3899 m_pos = cAgentData.Position + offset; 4204 m_pos = cAgentData.Position + offset;
@@ -3907,10 +4212,36 @@ namespace OpenSim.Region.Framework.Scenes
3907 CameraPosition = cAgentData.Center + offset; 4212 CameraPosition = cAgentData.Center + offset;
3908 4213
3909 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) 4214 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
3910 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); 4215 {
4216 // some scaling factor
4217 float x = m_pos.X;
4218 if (x > m_scene.RegionInfo.RegionSizeX)
4219 x -= m_scene.RegionInfo.RegionSizeX;
4220 float y = m_pos.Y;
4221 if (y > m_scene.RegionInfo.RegionSizeY)
4222 y -= m_scene.RegionInfo.RegionSizeY;
4223
4224 x = x * x + y * y;
4225
4226 const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize;
4227 float factor = 1.0f - distScale * x;
4228 if (factor < 0.2f)
4229 factor = 0.2f;
4230
4231 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor);
4232 }
4233
4234 if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4235 {
4236 if (Scene.CapsModule != null)
4237 {
4238 Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4239 }
4240
4241 KnownRegions = cAgentData.ChildrenCapSeeds;
4242 }
3911 4243
3912 //cAgentData.AVHeight; 4244 //cAgentData.AVHeight;
3913 RegionHandle = cAgentData.RegionHandle;
3914 //m_velocity = cAgentData.Velocity; 4245 //m_velocity = cAgentData.Velocity;
3915 } 4246 }
3916 4247
@@ -3932,16 +4263,7 @@ namespace OpenSim.Region.Framework.Scenes
3932 cAgent.Far = DrawDistance; 4263 cAgent.Far = DrawDistance;
3933 4264
3934 // Throttles 4265 // Throttles
3935 float multiplier = 1; 4266 cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
3936 int childRegions = KnownRegionCount;
3937 if (childRegions != 0)
3938 multiplier = 1f / childRegions;
3939
3940 // Minimum throttle for a child region is 1/4 of the root region throttle
3941 if (multiplier <= 0.25f)
3942 multiplier = 0.25f;
3943
3944 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
3945 4267
3946 cAgent.HeadRotation = m_headrotation; 4268 cAgent.HeadRotation = m_headrotation;
3947 cAgent.BodyRotation = Rotation; 4269 cAgent.BodyRotation = Rotation;
@@ -3954,7 +4276,8 @@ namespace OpenSim.Region.Framework.Scenes
3954 4276
3955 cAgent.AlwaysRun = SetAlwaysRun; 4277 cAgent.AlwaysRun = SetAlwaysRun;
3956 4278
3957 cAgent.Appearance = new AvatarAppearance(Appearance); 4279 // make clear we want the all thing
4280 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3958 4281
3959 cAgent.ParentPart = ParentUUID; 4282 cAgent.ParentPart = ParentUUID;
3960 cAgent.SitOffset = PrevSitOffset; 4283 cAgent.SitOffset = PrevSitOffset;
@@ -3980,6 +4303,10 @@ namespace OpenSim.Region.Framework.Scenes
3980 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 4303 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3981 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; 4304 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3982 4305
4306 cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4307
4308 cAgent.MotionState = (byte)Animator.currentControlState;
4309
3983 if (Scene.AttachmentsModule != null) 4310 if (Scene.AttachmentsModule != null)
3984 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 4311 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
3985 } 4312 }
@@ -4004,7 +4331,16 @@ namespace OpenSim.Region.Framework.Scenes
4004 // changes, then start using the agent's drawdistance rather than the 4331 // changes, then start using the agent's drawdistance rather than the
4005 // region's draw distance. 4332 // region's draw distance.
4006 DrawDistance = cAgent.Far; 4333 DrawDistance = cAgent.Far;
4007 // DrawDistance = Scene.DefaultDrawDistance; 4334 //DrawDistance = Scene.DefaultDrawDistance;
4335
4336 if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4337 {
4338 if (Scene.CapsModule != null)
4339 {
4340 Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4341 }
4342 KnownRegions = cAgent.ChildrenCapSeeds;
4343 }
4008 4344
4009 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4345 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
4010 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4346 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
@@ -4017,14 +4353,17 @@ namespace OpenSim.Region.Framework.Scenes
4017 GodLevel = cAgent.GodLevel; 4353 GodLevel = cAgent.GodLevel;
4018 SetAlwaysRun = cAgent.AlwaysRun; 4354 SetAlwaysRun = cAgent.AlwaysRun;
4019 4355
4356
4020 Appearance = new AvatarAppearance(cAgent.Appearance); 4357 Appearance = new AvatarAppearance(cAgent.Appearance);
4358/*
4359 bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4360
4021 if (PhysicsActor != null) 4361 if (PhysicsActor != null)
4022 { 4362 {
4023 bool isFlying = Flying;
4024 RemoveFromPhysicalScene(); 4363 RemoveFromPhysicalScene();
4025 AddToPhysicalScene(isFlying); 4364 AddToPhysicalScene(isFlying);
4026 } 4365 }
4027 4366*/
4028 try 4367 try
4029 { 4368 {
4030 lock (scriptedcontrols) 4369 lock (scriptedcontrols)
@@ -4048,34 +4387,23 @@ namespace OpenSim.Region.Framework.Scenes
4048 } 4387 }
4049 catch { } 4388 catch { }
4050 4389
4390 Animator.ResetAnimations();
4391
4392 Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4393
4051 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4394 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
4052 if (cAgent.Anims != null)
4053 Animator.Animations.FromArray(cAgent.Anims);
4054 if (cAgent.DefaultAnim != null) 4395 if (cAgent.DefaultAnim != null)
4055 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4396 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
4056 if (cAgent.AnimState != null) 4397 if (cAgent.AnimState != null)
4057 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4398 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4399 if (cAgent.Anims != null)
4400 Animator.Animations.FromArray(cAgent.Anims);
4401 if (cAgent.MotionState != 0)
4402 Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
4058 4403
4059 if (Scene.AttachmentsModule != null) 4404 if (Scene.AttachmentsModule != null)
4060 { 4405 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4061 // If the JobEngine is running we can schedule this job now and continue rather than waiting for all 4406
4062 // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory
4063 // graph is inspected for each attachments and assets possibly fetched.
4064 //
4065 // We don't need to worry about a race condition as the job to later start the scripts is also
4066 // JobEngine scheduled and so will always occur after this task.
4067 // XXX: This will not be true if JobEngine ever gets more than one thread.
4068 WorkManager.RunJob(
4069 "CopyAttachments",
4070 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this),
4071 null,
4072 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name),
4073 true);
4074 }
4075
4076 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread
4077 // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart
4078 // script attachments can outrace this thread.
4079 lock (m_originRegionIDAccessLock) 4407 lock (m_originRegionIDAccessLock)
4080 m_originRegionID = cAgent.RegionID; 4408 m_originRegionID = cAgent.RegionID;
4081 } 4409 }
@@ -4094,6 +4422,8 @@ namespace OpenSim.Region.Framework.Scenes
4094 /// </summary> 4422 /// </summary>
4095 public void UpdateMovement() 4423 public void UpdateMovement()
4096 { 4424 {
4425 if (IsInTransit)
4426 return;
4097 if (m_forceToApply.HasValue) 4427 if (m_forceToApply.HasValue)
4098 { 4428 {
4099 Vector3 force = m_forceToApply.Value; 4429 Vector3 force = m_forceToApply.Value;
@@ -4124,16 +4454,13 @@ namespace OpenSim.Region.Framework.Scenes
4124 if (Appearance.AvatarHeight == 0) 4454 if (Appearance.AvatarHeight == 0)
4125// Appearance.SetHeight(); 4455// Appearance.SetHeight();
4126 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); 4456 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
4127 4457
4128/* 4458 PhysicsScene scene = m_scene.PhysicsScene;
4459 Vector3 pVec = AbsolutePosition;
4460
4129 PhysicsActor = scene.AddAvatar( 4461 PhysicsActor = scene.AddAvatar(
4130 LocalId, Firstname + "." + Lastname, pVec, 4462 LocalId, Firstname + "." + Lastname, pVec,
4131 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying); 4463 Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
4132*/
4133
4134 PhysicsActor = m_scene.PhysicsScene.AddAvatar(
4135 LocalId, Firstname + "." + Lastname, AbsolutePosition, Velocity,
4136 Appearance.AvatarBoxSize, isFlying);
4137 4464
4138 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 4465 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
4139 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 4466 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -4168,7 +4495,9 @@ namespace OpenSim.Region.Framework.Scenes
4168 { 4495 {
4169 if (IsChildAgent || Animator == null) 4496 if (IsChildAgent || Animator == null)
4170 return; 4497 return;
4171 4498
4499 if(IsInTransit)
4500 return;
4172 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4501 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
4173 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( 4502 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
4174 // as of this comment the interval is set in AddToPhysicalScene 4503 // as of this comment the interval is set in AddToPhysicalScene
@@ -4192,7 +4521,49 @@ namespace OpenSim.Region.Framework.Scenes
4192// m_lastColCount = coldata.Count; 4521// m_lastColCount = coldata.Count;
4193// } 4522// }
4194 4523
4195 CollisionPlane = Vector4.UnitW; 4524 if (coldata.Count != 0)
4525 {
4526/*
4527 switch (Animator.CurrentMovementAnimation)
4528 {
4529 case "STAND":
4530 case "WALK":
4531 case "RUN":
4532 case "CROUCH":
4533 case "CROUCHWALK":
4534 {
4535 */
4536 ContactPoint lowest;
4537 lowest.SurfaceNormal = Vector3.Zero;
4538 lowest.Position = Vector3.Zero;
4539 lowest.Position.Z = float.MaxValue;
4540
4541 foreach (ContactPoint contact in coldata.Values)
4542 {
4543
4544 if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z)
4545 {
4546 lowest = contact;
4547 }
4548 }
4549
4550 if (lowest.Position.Z != float.MaxValue)
4551 {
4552 lowest.SurfaceNormal = -lowest.SurfaceNormal;
4553 CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
4554 }
4555 else
4556 CollisionPlane = Vector4.UnitW;
4557/*
4558 }
4559 break;
4560 }
4561*/
4562 }
4563 else
4564 CollisionPlane = Vector4.UnitW;
4565
4566 RaiseCollisionScriptEvents(coldata);
4196 4567
4197 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 4568 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
4198 if (Invulnerable || GodLevel > 0) 4569 if (Invulnerable || GodLevel > 0)
@@ -4311,6 +4682,10 @@ namespace OpenSim.Region.Framework.Scenes
4311 4682
4312 m_attachments.Add(gobj); 4683 m_attachments.Add(gobj);
4313 } 4684 }
4685
4686 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
4687 if (bakedModule != null)
4688 bakedModule.UpdateMeshAvatar(m_uuid);
4314 } 4689 }
4315 4690
4316 /// <summary> 4691 /// <summary>
@@ -4474,6 +4849,287 @@ namespace OpenSim.Region.Framework.Scenes
4474 return validated; 4849 return validated;
4475 } 4850 }
4476 4851
4852 public void SendAttachmentsToAllAgents()
4853 {
4854 lock (m_attachments)
4855 {
4856 foreach (SceneObjectGroup sog in m_attachments)
4857 {
4858 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4859 {
4860 if (p != this && sog.HasPrivateAttachmentPoint)
4861 return;
4862
4863 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4864 return;
4865
4866 SendTerseUpdateToAgentNF(p);
4867 SendAttachmentFullUpdateToAgentNF(sog, p);
4868 });
4869 }
4870 }
4871 }
4872
4873 // send attachments to a client without filters except for huds
4874 // for now they are checked in several places down the line...
4875 public void SendAttachmentsToAgentNF(ScenePresence p)
4876 {
4877 SendTerseUpdateToAgentNF(p);
4878 lock (m_attachments)
4879 {
4880 foreach (SceneObjectGroup sog in m_attachments)
4881 {
4882 SendAttachmentFullUpdateToAgentNF(sog, p);
4883 }
4884 }
4885 }
4886
4887 public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
4888 {
4889 if (p != this && sog.HasPrivateAttachmentPoint)
4890 return;
4891
4892 SceneObjectPart[] parts = sog.Parts;
4893 SceneObjectPart rootpart = sog.RootPart;
4894
4895 p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
4896
4897 for (int i = 0; i < parts.Length; i++)
4898 {
4899 SceneObjectPart part = parts[i];
4900 if (part == rootpart)
4901 continue;
4902 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4903 }
4904 }
4905
4906 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
4907 {
4908 if (IsChildAgent || IsInTransit)
4909 return;
4910
4911 SceneObjectPart[] origparts = sog.Parts;
4912 SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
4913 PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
4914
4915 SceneObjectPart rootpart = sog.RootPart;
4916 UpdateRequired rootreq = sog.RootPart.UpdateFlag;
4917
4918 int j = 0;
4919 bool allterse = true;
4920 for (int i = 0; i < origparts.Length; i++)
4921 {
4922 if (origparts[i] != rootpart)
4923 {
4924 switch (origparts[i].UpdateFlag)
4925 {
4926 case UpdateRequired.NONE:
4927 break;
4928
4929 case UpdateRequired.TERSE:
4930 flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4931 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4932 parts[j] = origparts[i];
4933 j++;
4934 break;
4935
4936 case UpdateRequired.FULL:
4937 flags[j] = PrimUpdateFlags.FullUpdate;
4938 allterse = false;
4939 parts[j] = origparts[i];
4940 j++;
4941 break;
4942 }
4943 }
4944 origparts[i].UpdateFlag = 0;
4945 }
4946
4947 if (j == 0 && rootreq == UpdateRequired.NONE)
4948 return;
4949
4950 PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
4951
4952 if (rootreq != UpdateRequired.FULL && allterse)
4953 {
4954 rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4955 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4956 }
4957
4958 int nparts = j;
4959
4960 ControllingClient.SendEntityUpdate(rootpart, rootflag);
4961
4962 for (int i = 0; i < nparts; i++)
4963 {
4964 ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4965 }
4966
4967 if (sog.HasPrivateAttachmentPoint)
4968 return;
4969
4970 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4971 foreach (ScenePresence p in allPresences)
4972 {
4973 if (p == this)
4974 continue;
4975
4976 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4977 continue;
4978
4979 p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
4980
4981 for (int i = 0; i < nparts; i++)
4982 {
4983 p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4984 }
4985 }
4986 }
4987
4988 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
4989 {
4990 if (IsChildAgent || IsInTransit)
4991 return;
4992
4993 PrimUpdateFlags flag;
4994 switch (UpdateFlag)
4995 {
4996 case UpdateRequired.TERSE:
4997 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4998 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4999 break;
5000
5001 case UpdateRequired.FULL:
5002 flag = PrimUpdateFlags.FullUpdate;
5003 break;
5004
5005 default:
5006 return;
5007 }
5008
5009 SceneObjectPart[] parts = sog.Parts;
5010 SceneObjectPart rootpart = sog.RootPart;
5011
5012// rootpart.UpdateFlag = 0;
5013
5014 ControllingClient.SendEntityUpdate(rootpart, flag);
5015
5016 for (int i = 0; i < parts.Length; i++)
5017 {
5018 SceneObjectPart part = parts[i];
5019 if (part == rootpart)
5020 continue;
5021 ControllingClient.SendEntityUpdate(part, flag);
5022// part.UpdateFlag = 0;
5023 }
5024
5025 if (sog.HasPrivateAttachmentPoint)
5026 return;
5027
5028
5029 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5030 foreach (ScenePresence p in allPresences)
5031 {
5032 if (p == this)
5033 continue;
5034
5035 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5036 continue;
5037
5038 p.ControllingClient.SendEntityUpdate(rootpart, flag);
5039
5040 for (int i = 0; i < parts.Length; i++)
5041 {
5042 SceneObjectPart part = parts[i];
5043 if (part == rootpart)
5044 continue;
5045 p.ControllingClient.SendEntityUpdate(part, flag);
5046 }
5047 }
5048 }
5049
5050 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
5051 {
5052 if (IsChildAgent || IsInTransit)
5053 return;
5054
5055
5056 PrimUpdateFlags flag;
5057 switch (part.UpdateFlag)
5058 {
5059 case UpdateRequired.TERSE:
5060 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5061 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5062 break;
5063
5064 case UpdateRequired.FULL:
5065 flag = PrimUpdateFlags.FullUpdate;
5066 break;
5067
5068 default:
5069 return;
5070 }
5071
5072 part.UpdateFlag = 0;
5073
5074 ControllingClient.SendEntityUpdate(part, flag);
5075
5076 if (part.ParentGroup.HasPrivateAttachmentPoint)
5077 return;
5078
5079 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5080 foreach (ScenePresence p in allPresences)
5081 {
5082 if (p == this)
5083 continue;
5084
5085 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5086 continue;
5087
5088 p.ControllingClient.SendEntityUpdate(part, flag);
5089 }
5090 }
5091
5092
5093 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
5094 {
5095 if (IsChildAgent || IsInTransit)
5096 return;
5097
5098 PrimUpdateFlags flag;
5099 switch (UpdateFlag)
5100 {
5101 case UpdateRequired.TERSE:
5102 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5103 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5104 break;
5105
5106 case UpdateRequired.FULL:
5107 flag = PrimUpdateFlags.FullUpdate;
5108 break;
5109
5110 default:
5111 return;
5112 }
5113
5114// part.UpdateFlag = 0;
5115
5116 ControllingClient.SendEntityUpdate(part, flag);
5117
5118 if (part.ParentGroup.HasPrivateAttachmentPoint)
5119 return;
5120
5121 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5122 foreach (ScenePresence p in allPresences)
5123 {
5124 if (p == this)
5125 continue;
5126 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5127 continue;
5128
5129 p.ControllingClient.SendEntityUpdate(part, flag);
5130 }
5131 }
5132
4477 /// <summary> 5133 /// <summary>
4478 /// Send a script event to this scene presence's attachments 5134 /// Send a script event to this scene presence's attachments
4479 /// </summary> 5135 /// </summary>
@@ -4592,6 +5248,15 @@ namespace OpenSim.Region.Framework.Scenes
4592 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5248 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4593 } 5249 }
4594 5250
5251 public void ClearControls()
5252 {
5253 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5254 lock (scriptedcontrols)
5255 {
5256 scriptedcontrols.Clear();
5257 }
5258 }
5259
4595 private void UnRegisterSeatControls(UUID obj) 5260 private void UnRegisterSeatControls(UUID obj)
4596 { 5261 {
4597 List<UUID> takers = new List<UUID>(); 5262 List<UUID> takers = new List<UUID>();
@@ -4833,11 +5498,8 @@ namespace OpenSim.Region.Framework.Scenes
4833 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); 5498 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
4834 if (spawnPoints.Length == 0) 5499 if (spawnPoints.Length == 0)
4835 { 5500 {
4836 if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) 5501 pos.X = 128.0f;
4837 { 5502 pos.Y = 128.0f;
4838 pos.X = 128.0f;
4839 pos.Y = 128.0f;
4840 }
4841 return; 5503 return;
4842 } 5504 }
4843 5505
@@ -4982,8 +5644,8 @@ namespace OpenSim.Region.Framework.Scenes
4982 pos = land.LandData.UserLocation; 5644 pos = land.LandData.UserLocation;
4983 } 5645 }
4984 } 5646 }
4985 5647// this is now done in completeMovement for all cases and not just this
4986 land.SendLandUpdateToClient(ControllingClient); 5648// land.SendLandUpdateToClient(ControllingClient);
4987 } 5649 }
4988 } 5650 }
4989 5651
@@ -4998,6 +5660,7 @@ namespace OpenSim.Region.Framework.Scenes
4998 detobj.velVector = obj.Velocity; 5660 detobj.velVector = obj.Velocity;
4999 detobj.colliderType = 0; 5661 detobj.colliderType = 0;
5000 detobj.groupUUID = obj.GroupID; 5662 detobj.groupUUID = obj.GroupID;
5663 detobj.linkNumber = 0;
5001 5664
5002 return detobj; 5665 return detobj;
5003 } 5666 }
@@ -5013,6 +5676,7 @@ namespace OpenSim.Region.Framework.Scenes
5013 detobj.velVector = av.Velocity; 5676 detobj.velVector = av.Velocity;
5014 detobj.colliderType = 0; 5677 detobj.colliderType = 0;
5015 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 5678 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5679 detobj.linkNumber = 0;
5016 5680
5017 return detobj; 5681 return detobj;
5018 } 5682 }
@@ -5028,7 +5692,7 @@ namespace OpenSim.Region.Framework.Scenes
5028 detobj.velVector = Vector3.Zero; 5692 detobj.velVector = Vector3.Zero;
5029 detobj.colliderType = 0; 5693 detobj.colliderType = 0;
5030 detobj.groupUUID = UUID.Zero; 5694 detobj.groupUUID = UUID.Zero;
5031 5695 detobj.linkNumber = 0;
5032 return detobj; 5696 return detobj;
5033 } 5697 }
5034 5698
@@ -5095,6 +5759,95 @@ namespace OpenSim.Region.Framework.Scenes
5095 } 5759 }
5096 } 5760 }
5097 5761
5762 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
5763 {
5764 try
5765 {
5766 List<uint> thisHitColliders = new List<uint>();
5767 List<uint> endedColliders = new List<uint>();
5768 List<uint> startedColliders = new List<uint>();
5769 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
5770 CollisionForSoundInfo soundinfo;
5771 ContactPoint curcontact;
5772
5773 if (coldata.Count == 0)
5774 {
5775 if (m_lastColliders.Count == 0)
5776 return; // nothing to do
5777
5778 foreach (uint localID in m_lastColliders)
5779 {
5780 endedColliders.Add(localID);
5781 }
5782 m_lastColliders.Clear();
5783 }
5784
5785 else
5786 {
5787 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5788
5789 foreach (uint id in coldata.Keys)
5790 {
5791 thisHitColliders.Add(id);
5792 if (!m_lastColliders.Contains(id))
5793 {
5794 startedColliders.Add(id);
5795 curcontact = coldata[id];
5796 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
5797 {
5798 soundinfo = new CollisionForSoundInfo();
5799 soundinfo.colliderID = id;
5800 soundinfo.position = curcontact.Position;
5801 soundinfo.relativeVel = curcontact.RelativeSpeed;
5802 soundinfolist.Add(soundinfo);
5803 }
5804 }
5805 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
5806 }
5807
5808 // calculate things that ended colliding
5809 foreach (uint localID in m_lastColliders)
5810 {
5811 if (!thisHitColliders.Contains(localID))
5812 {
5813 endedColliders.Add(localID);
5814 }
5815 }
5816 //add the items that started colliding this time to the last colliders list.
5817 foreach (uint localID in startedColliders)
5818 {
5819 m_lastColliders.Add(localID);
5820 }
5821 // remove things that ended colliding from the last colliders list
5822 foreach (uint localID in endedColliders)
5823 {
5824 m_lastColliders.Remove(localID);
5825 }
5826
5827 if (soundinfolist.Count > 0)
5828 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
5829 }
5830
5831 foreach (SceneObjectGroup att in GetAttachments())
5832 {
5833 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
5834 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
5835 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
5836
5837 if (startedColliders.Contains(0))
5838 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
5839 if (m_lastColliders.Contains(0))
5840 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
5841 if (endedColliders.Contains(0))
5842 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
5843 }
5844 }
5845 finally
5846 {
5847 m_collisionEventFlag = false;
5848 }
5849 }
5850
5098 private void TeleportFlagsDebug() { 5851 private void TeleportFlagsDebug() {
5099 5852
5100 // Some temporary debugging help to show all the TeleportFlags we have... 5853 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -5119,5 +5872,282 @@ namespace OpenSim.Region.Framework.Scenes
5119 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5872 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
5120 5873
5121 } 5874 }
5875
5876 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5877 {
5878 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5879
5880 foreach (ScenePresence p in allpresences)
5881 {
5882 if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5883 continue;
5884
5885 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5886 {
5887 if (isGod)
5888 p.SendViewTo(this);
5889 else
5890 p.SendKillTo(this);
5891 }
5892 }
5893 }
5894
5895 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5896 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5897 {
5898 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5899 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5900 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5901 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5902 List<ScenePresence> allpresences = null;
5903
5904 if (IsInTransit || IsChildAgent)
5905 return;
5906
5907 if (check)
5908 {
5909 // check is relative to current parcel only
5910 if (currentParcelUUID == null || oldhide == currentParcelHide)
5911 return;
5912
5913 allpresences = m_scene.GetScenePresences();
5914
5915 if (oldhide)
5916 { // where private
5917 foreach (ScenePresence p in allpresences)
5918 {
5919 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5920 continue;
5921
5922 // those on not on parcel see me
5923 if (currentParcelID != p.currentParcelUUID)
5924 {
5925 viewsToSendto.Add(p); // they see me
5926 }
5927 }
5928 } // where private end
5929
5930 else
5931 { // where public
5932 foreach (ScenePresence p in allpresences)
5933 {
5934 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5935 continue;
5936
5937 // those not on parcel dont see me
5938 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5939 {
5940 killsToSendto.Add(p); // they dont see me
5941 }
5942 }
5943 } // where public end
5944
5945 allpresences.Clear();
5946 }
5947 else
5948 {
5949 if (currentParcelHide)
5950 {
5951 // now on a private parcel
5952 allpresences = m_scene.GetScenePresences();
5953
5954 if (previusParcelHide && previusParcelID != UUID.Zero)
5955 {
5956 foreach (ScenePresence p in allpresences)
5957 {
5958 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5959 continue;
5960
5961 // only those on previus parcel need receive kills
5962 if (previusParcelID == p.currentParcelUUID)
5963 {
5964 if(p.GodLevel < 200)
5965 killsToSendto.Add(p); // they dont see me
5966 if(GodLevel < 200)
5967 killsToSendme.Add(p); // i dont see them
5968 }
5969 // only those on new parcel need see
5970 if (currentParcelID == p.currentParcelUUID)
5971 {
5972 viewsToSendto.Add(p); // they see me
5973 viewsToSendme.Add(p); // i see them
5974 }
5975 }
5976 }
5977 else
5978 {
5979 //was on a public area
5980 allpresences = m_scene.GetScenePresences();
5981
5982 foreach (ScenePresence p in allpresences)
5983 {
5984 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5985 continue;
5986
5987 // those not on new parcel dont see me
5988 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5989 {
5990 killsToSendto.Add(p); // they dont see me
5991 }
5992 else
5993 {
5994 viewsToSendme.Add(p); // i see those on it
5995 }
5996 }
5997 }
5998 allpresences.Clear();
5999 } // now on a private parcel end
6000
6001 else
6002 {
6003 // now on public parcel
6004 if (previusParcelHide && previusParcelID != UUID.Zero)
6005 {
6006 // was on private area
6007 allpresences = m_scene.GetScenePresences();
6008
6009 foreach (ScenePresence p in allpresences)
6010 {
6011 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6012 continue;
6013 // only those old parcel need kills
6014 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
6015 {
6016 killsToSendme.Add(p); // i dont see them
6017 }
6018 else
6019 {
6020 viewsToSendto.Add(p); // they see me
6021 }
6022 }
6023 }
6024 else
6025 return; // was on a public area also
6026 } // now on public parcel end
6027 }
6028
6029 // send the things
6030
6031 if (killsToSendto.Count > 0)
6032 {
6033 foreach (ScenePresence p in killsToSendto)
6034 {
6035 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
6036 SendKillTo(p);
6037 }
6038 }
6039
6040 if (killsToSendme.Count > 0)
6041 {
6042 foreach (ScenePresence p in killsToSendme)
6043 {
6044 m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
6045 p.SendKillTo(this);
6046 }
6047 }
6048
6049 if (viewsToSendto.Count > 0)
6050 {
6051 foreach (ScenePresence p in viewsToSendto)
6052 {
6053 SendViewTo(p);
6054 }
6055 }
6056
6057 if (viewsToSendme.Count > 0 )
6058 {
6059 foreach (ScenePresence p in viewsToSendme)
6060 {
6061 if (p.IsChildAgent)
6062 continue;
6063// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
6064 p.SendViewTo(this);
6065 }
6066 }
6067 }
6068
6069 public void HasMovedAway(bool nearRegion)
6070 {
6071
6072 if (nearRegion)
6073 {
6074 if (Scene.AttachmentsModule != null)
6075 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6076
6077 if (!ParcelHideThisAvatar || GodLevel >= 200)
6078 return;
6079
6080 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6081 foreach (ScenePresence p in allpresences)
6082 {
6083 if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
6084 continue;
6085
6086 if (p.currentParcelUUID == m_currentParcelUUID)
6087 {
6088 p.SendKillTo(this);
6089 }
6090 }
6091 }
6092 else
6093 {
6094 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6095 foreach (ScenePresence p in allpresences)
6096 {
6097 if (p == this)
6098 continue;
6099 SendKillTo(p);
6100 if (!p.IsChildAgent)
6101 p.SendKillTo(this);
6102 }
6103
6104 if (Scene.AttachmentsModule != null)
6105 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6106 }
6107 }
6108
6109
6110// kill with attachs root kills
6111 public void SendKillTo(ScenePresence p)
6112 {
6113 List<uint> ids = new List<uint>(m_attachments.Count + 1);
6114 foreach (SceneObjectGroup sog in m_attachments)
6115 {
6116 ids.Add(sog.RootPart.LocalId);
6117 }
6118
6119 ids.Add(LocalId);
6120 p.ControllingClient.SendKillObject(ids);
6121 }
6122
6123/*
6124// kill with hack
6125 public void SendKillTo(ScenePresence p)
6126 {
6127 foreach (SceneObjectGroup sog in m_attachments)
6128 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6129 p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6130 }
6131*/
6132 public void SendViewTo(ScenePresence p)
6133 {
6134 SendAvatarDataToAgentNF(p);
6135 SendAppearanceToAgent(p);
6136 if (Animator != null)
6137 Animator.SendAnimPackToClient(p.ControllingClient);
6138 SendAttachmentsToAgentNF(p);
6139 }
6140
6141 public void SetAnimationOverride(string animState, UUID animID)
6142 {
6143 Overrides.SetOverride(animState, animID);
6144// Animator.SendAnimPack();
6145 Animator.ForceUpdateMovementAnimations();
6146 }
6147
6148 public UUID GetAnimationOverride(string animState)
6149 {
6150 return Overrides.GetOverriddenAnimation(animState);
6151 }
5122 } 6152 }
5123} 6153}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 4caa9cb..c8a01a0 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -278,7 +278,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
278 // Script state may, or may not, exist. Not having any, is NOT 278 // Script state may, or may not, exist. Not having any, is NOT
279 // ever a problem. 279 // ever a problem.
280 sceneObject.LoadScriptState(doc); 280 sceneObject.LoadScriptState(doc);
281 281
282 return sceneObject; 282 return sceneObject;
283 } 283 }
284 catch (Exception e) 284 catch (Exception e)
@@ -307,14 +307,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
307 } 307 }
308 } 308 }
309 309
310
311 /// <summary> 310 /// <summary>
312 /// Modifies a SceneObjectGroup. 311 /// Modifies a SceneObjectGroup.
313 /// </summary> 312 /// </summary>
314 /// <param name="sog">The object</param> 313 /// <param name="sog">The object</param>
315 /// <returns>Whether the object was actually modified</returns> 314 /// <returns>Whether the object was actually modified</returns>
316 public delegate bool SceneObjectModifier(SceneObjectGroup sog); 315 public delegate bool SceneObjectModifier(SceneObjectGroup sog);
317 316
318 /// <summary> 317 /// <summary>
319 /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing. 318 /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing.
320 /// </summary> 319 /// </summary>
@@ -328,7 +327,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
328 CoalescedSceneObjects coa = null; 327 CoalescedSceneObjects coa = null;
329 328
330 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data)); 329 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data));
331
332 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) 330 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa))
333 { 331 {
334 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); 332 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
@@ -374,7 +372,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
374 return data; 372 return data;
375 } 373 }
376 374
377
378 #region manual serialization 375 #region manual serialization
379 376
380 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors 377 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors
@@ -450,11 +447,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
450 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 447 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
451 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 448 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
452 449
450 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
451 m_SOPXmlProcessors.Add("Force", ProcessForce);
452 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
453 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
454
455
456 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
457
453 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType); 458 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
454 m_SOPXmlProcessors.Add("Density", ProcessDensity); 459 m_SOPXmlProcessors.Add("Density", ProcessDensity);
455 m_SOPXmlProcessors.Add("Friction", ProcessFriction); 460 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
456 m_SOPXmlProcessors.Add("Bounce", ProcessBounce); 461 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
457 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier); 462 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
463 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset);
464 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset);
465
466 m_SOPXmlProcessors.Add("SoundID", ProcessSoundID);
467 m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain);
468 m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags);
469 m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius);
470 m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing);
458 471
459 #endregion 472 #endregion
460 473
@@ -483,7 +496,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
483 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 496 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
484 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 497 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
485 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 498 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
486 499
487 #endregion 500 #endregion
488 501
489 #region ShapeXmlProcessors initialization 502 #region ShapeXmlProcessors initialization
@@ -709,6 +722,58 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
709 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty); 722 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
710 } 723 }
711 724
725 private static void ProcessCameraEyeOffset(SceneObjectPart obj, XmlReader reader)
726 {
727 obj.SetCameraEyeOffset(Util.ReadVector(reader, "CameraEyeOffset"));
728 }
729
730 private static void ProcessCameraAtOffset(SceneObjectPart obj, XmlReader reader)
731 {
732 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset"));
733 }
734
735 private static void ProcessSoundID(SceneObjectPart obj, XmlReader reader)
736 {
737 obj.Sound = Util.ReadUUID(reader, "SoundID");
738 }
739
740 private static void ProcessSoundGain(SceneObjectPart obj, XmlReader reader)
741 {
742 obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty);
743 }
744
745 private static void ProcessSoundFlags(SceneObjectPart obj, XmlReader reader)
746 {
747 obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty);
748 }
749
750 private static void ProcessSoundRadius(SceneObjectPart obj, XmlReader reader)
751 {
752 obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty);
753 }
754
755 private static void ProcessSoundQueueing(SceneObjectPart obj, XmlReader reader)
756 {
757 obj.SoundQueueing = Util.ReadBoolean(reader);
758 }
759
760 private static void ProcessVehicle(SceneObjectPart obj, XmlReader reader)
761 {
762 SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
763
764 if (vehicle == null)
765 {
766 obj.VehicleParams = null;
767 m_log.DebugFormat(
768 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
769 obj.Name, obj.UUID);
770 }
771 else
772 {
773 obj.VehicleParams = vehicle;
774 }
775 }
776
712 private static void ProcessShape(SceneObjectPart obj, XmlReader reader) 777 private static void ProcessShape(SceneObjectPart obj, XmlReader reader)
713 { 778 {
714 List<string> errorNodeNames; 779 List<string> errorNodeNames;
@@ -883,6 +948,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
883 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 948 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
884 } 949 }
885 950
951 private static void ProcessBuoyancy(SceneObjectPart obj, XmlReader reader)
952 {
953 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
954 }
955
956 private static void ProcessForce(SceneObjectPart obj, XmlReader reader)
957 {
958 obj.Force = Util.ReadVector(reader, "Force");
959 }
960 private static void ProcessTorque(SceneObjectPart obj, XmlReader reader)
961 {
962 obj.Torque = Util.ReadVector(reader, "Torque");
963 }
964
965 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlReader reader)
966 {
967 obj.VolumeDetectActive = Util.ReadBoolean(reader);
968 }
969
886 #endregion 970 #endregion
887 971
888 #region TaskInventoryXmlProcessors 972 #region TaskInventoryXmlProcessors
@@ -1271,12 +1355,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1271 1355
1272 if (sog.RootPart.KeyframeMotion != null) 1356 if (sog.RootPart.KeyframeMotion != null)
1273 { 1357 {
1274 Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); 1358 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1275 1359
1276 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); 1360 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1277 writer.WriteBase64(data, 0, data.Length); 1361 writer.WriteBase64(data, 0, data.Length);
1278 writer.WriteEndElement(); 1362 writer.WriteEndElement();
1279 } 1363 }
1364
1280 1365
1281 writer.WriteEndElement(); 1366 writer.WriteEndElement();
1282 } 1367 }
@@ -1388,8 +1473,17 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1388 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1473 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1389 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1474 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1390 1475
1391 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) 1476 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1392 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); 1477
1478 WriteVector(writer, "Force", sop.Force);
1479 WriteVector(writer, "Torque", sop.Torque);
1480
1481 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1482
1483 if (sop.VehicleParams != null)
1484 sop.VehicleParams.ToXml2(writer);
1485
1486 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1393 if (sop.Density != 1000.0f) 1487 if (sop.Density != 1000.0f)
1394 writer.WriteElementString("Density", sop.Density.ToString().ToLower()); 1488 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1395 if (sop.Friction != 0.6f) 1489 if (sop.Friction != 0.6f)
@@ -1398,7 +1492,18 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1398 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); 1492 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower());
1399 if (sop.GravityModifier != 1.0f) 1493 if (sop.GravityModifier != 1.0f)
1400 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); 1494 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1495 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1496 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1401 1497
1498 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1499 {
1500 WriteUUID(writer, "SoundID", sop.Sound, options);
1501 writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower());
1502 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1503 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower());
1504 }
1505 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1506
1402 writer.WriteEndElement(); 1507 writer.WriteEndElement();
1403 } 1508 }
1404 1509
@@ -1625,12 +1730,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1625 { 1730 {
1626 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1731 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1627 1732
1628 if (reader.IsEmptyElement)
1629 {
1630 reader.Read();
1631 return tinv;
1632 }
1633
1634 reader.ReadStartElement(name, String.Empty); 1733 reader.ReadStartElement(name, String.Empty);
1635 1734
1636 while (reader.Name == "TaskInventoryItem") 1735 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 2174e51..66cf14f 100755
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -62,8 +62,10 @@ namespace OpenSim.Region.Framework.Scenes
62 private YourStatsAreWrong handlerStatsIncorrect; 62 private YourStatsAreWrong handlerStatsIncorrect;
63 63
64 // Determines the size of the array that is used to collect StatBlocks 64 // Determines the size of the array that is used to collect StatBlocks
65 // for sending to the SimStats and SimExtraStatsCollector 65 // for sending viewer compatible stats must be conform with sb array filling below
66 private const int m_statisticArraySize = 28; 66 private const int m_statisticViewerArraySize = 38;
67 // size of LastReportedSimFPS with extra stats.
68 private const int m_statisticExtraArraySize = (int)(Stats.SimExtraCountEnd - Stats.SimExtraCountStart);
67 69
68 /// <summary> 70 /// <summary>
69 /// These are the IDs of stats sent in the StatsPacket to the viewer. 71 /// These are the IDs of stats sent in the StatsPacket to the viewer.
@@ -74,6 +76,7 @@ namespace OpenSim.Region.Framework.Scenes
74 /// </remarks> 76 /// </remarks>
75 public enum Stats : uint 77 public enum Stats : uint
76 { 78 {
79// viewers defined IDs
77 TimeDilation = 0, 80 TimeDilation = 0,
78 SimFPS = 1, 81 SimFPS = 1,
79 PhysicsFPS = 2, 82 PhysicsFPS = 2,
@@ -90,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
90 Agents = 13, 93 Agents = 13,
91 ChildAgents = 14, 94 ChildAgents = 14,
92 ActiveScripts = 15, 95 ActiveScripts = 15,
93 ScriptLinesPerSecond = 16, 96 LSLScriptLinesPerSecond = 16, // viewers don't like this anymore
94 InPacketsPerSecond = 17, 97 InPacketsPerSecond = 17,
95 OutPacketsPerSecond = 18, 98 OutPacketsPerSecond = 18,
96 PendingDownloads = 19, 99 PendingDownloads = 19,
@@ -109,11 +112,24 @@ namespace OpenSim.Region.Framework.Scenes
109 SimSpareMs = 32, 112 SimSpareMs = 32,
110 SimSleepMs = 33, 113 SimSleepMs = 33,
111 SimIoPumpTime = 34, 114 SimIoPumpTime = 34,
112 FrameDilation = 35, 115 SimPCTSscriptsRun = 35,
113 UsersLoggingIn = 36, 116 SimRegionIdle = 36, // dataserver only
114 TotalGeoPrim = 37, 117 SimRegionIdlePossible = 37, // dataserver only
115 TotalMesh = 38, 118 SimAIStepTimeMS = 38,
116 ThreadCount = 39 119 SimSkippedSillouet_PS = 39,
120 SimSkippedCharsPerC = 40,
121
122// extra stats IDs irrelevant, just far from viewer defined ones
123 SimExtraCountStart = 1000,
124
125 internalLSLScriptLinesPerSecond = 1000,
126 FrameDilation2 = 1001,
127 UsersLoggingIn = 1002,
128 TotalGeoPrim = 1003,
129 TotalMesh = 1004,
130 ThreadCount = 1005,
131
132 SimExtraCountEnd = 1006
117 } 133 }
118 134
119 /// <summary> 135 /// <summary>
@@ -168,11 +184,6 @@ namespace OpenSim.Region.Framework.Scenes
168 private uint m_lastUpdateFrame; 184 private uint m_lastUpdateFrame;
169 185
170 /// <summary> 186 /// <summary>
171 /// Our nominal fps target, as expected in fps stats when a sim is running normally.
172 /// </summary>
173 private float m_nominalReportedFps = 55;
174
175 /// <summary>
176 /// Parameter to adjust reported scene fps 187 /// Parameter to adjust reported scene fps
177 /// </summary> 188 /// </summary>
178 /// <remarks> 189 /// <remarks>
@@ -180,11 +191,11 @@ namespace OpenSim.Region.Framework.Scenes
180 /// However, we will still report an FPS that's closer to what people are used to seeing. A lower FPS might 191 /// However, we will still report an FPS that's closer to what people are used to seeing. A lower FPS might
181 /// affect clients and monitoring scripts/software. 192 /// affect clients and monitoring scripts/software.
182 /// </remarks> 193 /// </remarks>
183 private float m_reportedFpsCorrectionFactor = 5; 194 private float m_reportedFpsCorrectionFactor = 1.0f;
184 195
185 // saved last reported value so there is something available for llGetRegionFPS 196 // saved last reported value so there is something available for llGetRegionFPS
186 private float lastReportedSimFPS; 197 private float lastReportedSimFPS;
187 private float[] lastReportedSimStats = new float[m_statisticArraySize]; 198 private float[] lastReportedSimStats = new float[m_statisticExtraArraySize + m_statisticViewerArraySize];
188 private float m_pfps; 199 private float m_pfps;
189 200
190 /// <summary> 201 /// <summary>
@@ -197,14 +208,14 @@ namespace OpenSim.Region.Framework.Scenes
197 /// </summary> 208 /// </summary>
198 private int m_objectUpdates; 209 private int m_objectUpdates;
199 210
200 private int m_frameMS; 211 private float m_frameMS;
201 private int m_spareMS; 212
202 private int m_netMS; 213 private float m_netMS;
203 private int m_agentMS; 214 private float m_agentMS;
204 private int m_physicsMS; 215 private float m_physicsMS;
205 private int m_imageMS; 216 private float m_imageMS;
206 private int m_otherMS; 217 private float m_otherMS;
207 private int m_scriptMS; 218 private float m_sleeptimeMS;
208 219
209 private int m_rootAgents; 220 private int m_rootAgents;
210 private int m_childAgents; 221 private int m_childAgents;
@@ -222,28 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
222 233
223 private int m_objectCapacity = 45000; 234 private int m_objectCapacity = 45000;
224 235
225 // This is the number of frames that will be stored and then averaged for 236 // The current number of users attempting to login to the region
226 // the Total, Simulation, Physics, and Network Frame Time; It is set to
227 // 10 by default but can be changed by the OpenSim.ini configuration file
228 // NumberOfFrames parameter
229 private int m_numberFramesStored;
230
231 // The arrays that will hold the time it took to run the past N frames,
232 // where N is the num_frames_to_average given by the configuration file
233 private double[] m_totalFrameTimeMilliseconds;
234 private double[] m_simulationFrameTimeMilliseconds;
235 private double[] m_physicsFrameTimeMilliseconds;
236 private double[] m_networkFrameTimeMilliseconds;
237
238 // The location of the next time in milliseconds that will be
239 // (over)written when the next frame completes
240 private int m_nextLocation = 0;
241
242 // The correct number of frames that have completed since the last stats
243 // update for physics
244 private int m_numberPhysicsFrames;
245
246 // The current number of users attempting to login to the region
247 private int m_usersLoggingIn; 237 private int m_usersLoggingIn;
248 238
249 // The last reported value of threads from the SmartThreadPool inside of 239 // The last reported value of threads from the SmartThreadPool inside of
@@ -258,28 +248,11 @@ namespace OpenSim.Region.Framework.Scenes
258 248
259 private IEstateModule estateModule; 249 private IEstateModule estateModule;
260 250
261 public SimStatsReporter(Scene scene) 251 public SimStatsReporter(Scene scene)
262 : this(scene, Scene.m_defaultNumberFramesStored)
263 { 252 {
264 }
265
266 public SimStatsReporter(Scene scene, int numberOfFrames)
267 {
268 // Store the number of frames from the OpenSim.ini configuration file
269 m_numberFramesStored = numberOfFrames;
270
271 // Initialize the different frame time arrays to the correct sizes
272 m_totalFrameTimeMilliseconds = new double[m_numberFramesStored];
273 m_simulationFrameTimeMilliseconds = new double[m_numberFramesStored];
274 m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored];
275 m_networkFrameTimeMilliseconds = new double[m_numberFramesStored];
276
277 // Initialize the current number of users logging into the region
278 m_usersLoggingIn = 0;
279
280 m_scene = scene; 253 m_scene = scene;
281 m_reportedFpsCorrectionFactor = scene.MinFrameSeconds * m_nominalReportedFps; 254
282 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); 255 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000.0f);
283 ReportingRegion = scene.RegionInfo; 256 ReportingRegion = scene.RegionInfo;
284 257
285 m_objectCapacity = scene.RegionInfo.ObjectCapacity; 258 m_objectCapacity = scene.RegionInfo.ObjectCapacity;
@@ -293,7 +266,7 @@ namespace OpenSim.Region.Framework.Scenes
293 266
294 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit 267 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
295 /// longer than ideal (which in itself is a concern). 268 /// longer than ideal (which in itself is a concern).
296 SlowFramesStatReportThreshold = (int)Math.Ceiling(scene.MinFrameTicks * 1.2); 269 SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2);
297 270
298 SlowFramesStat 271 SlowFramesStat
299 = new Stat( 272 = new Stat(
@@ -308,7 +281,6 @@ namespace OpenSim.Region.Framework.Scenes
308 StatVerbosity.Info); 281 StatVerbosity.Info);
309 282
310 StatsManager.RegisterStat(SlowFramesStat); 283 StatsManager.RegisterStat(SlowFramesStat);
311
312 } 284 }
313 285
314 286
@@ -325,7 +297,7 @@ namespace OpenSim.Region.Framework.Scenes
325 public void SetUpdateMS(int ms) 297 public void SetUpdateMS(int ms)
326 { 298 {
327 m_statsUpdatesEveryMS = ms; 299 m_statsUpdatesEveryMS = ms;
328 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); 300 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000.0f);
329 m_report.Interval = m_statsUpdatesEveryMS; 301 m_report.Interval = m_statsUpdatesEveryMS;
330 } 302 }
331 303
@@ -345,21 +317,11 @@ namespace OpenSim.Region.Framework.Scenes
345 317
346 private void statsHeartBeat(object sender, EventArgs e) 318 private void statsHeartBeat(object sender, EventArgs e)
347 { 319 {
348 double totalSumFrameTime; 320 if (!m_scene.Active)
349 double simulationSumFrameTime;
350 double physicsSumFrameTime;
351 double networkSumFrameTime;
352 float frameDilation;
353 int currentFrame;
354
355 if (!m_scene.Active)
356 return; 321 return;
357 322
358 // Create arrays to hold the statistics for this current scene, 323 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[m_statisticViewerArraySize];
359 // these will be passed to the SimExtraStatsCollector, they are also 324 SimStatsPacket.StatBlock[] sbex = new SimStatsPacket.StatBlock[m_statisticExtraArraySize];
360 // sent to the SimStats class
361 SimStatsPacket.StatBlock[] sb = new
362 SimStatsPacket.StatBlock[m_statisticArraySize];
363 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 325 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
364 326
365 // Know what's not thread safe in Mono... modifying timers. 327 // Know what's not thread safe in Mono... modifying timers.
@@ -380,31 +342,27 @@ namespace OpenSim.Region.Framework.Scenes
380 } 342 }
381 343
382#region various statistic googly moogly 344#region various statistic googly moogly
345 // factor to consider updates integration time
346 float updateFactor = 1.0f / m_statsUpdateFactor;
383 347
384 // ORIGINAL code commented out until we have time to add our own 348 // the nominal frame time, corrected by reporting multiplier
385 // statistics to the statistics window, this will be done as a 349 float TargetFrameTime = 1000.0f * m_scene.MinFrameTime / m_reportedFpsCorrectionFactor;
386 // new section given the title of our current project
387 // We're going to lie about the FPS because we've been lying since 2008. The actual FPS is currently
388 // locked at a maximum of 11. Maybe at some point this can change so that we're not lying.
389 //int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor);
390 int reportedFPS = m_fps;
391 350
392 // save the reported value so there is something available for llGetRegionFPS 351 // acumulated fps scaled by reporting multiplier
393 lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; 352 float reportedFPS = (m_fps * m_reportedFpsCorrectionFactor);
353 if (reportedFPS <= 0)
354 reportedFPS = 1;
394 355
395 // ORIGINAL code commented out until we have time to add our own 356 // factor to calculate per frame values
396 // statistics to the statistics window 357 float perframefactor = 1.0f / (float)reportedFPS;
397 //float physfps = ((m_pfps / 1000));
398 float physfps = m_numberPhysicsFrames;
399 358
400 //if (physfps > 600) 359 // fps considering the integration time
401 //physfps = physfps - (physfps - 600); 360 reportedFPS = reportedFPS * updateFactor;
361 // save the reported value so there is something available for llGetRegionFPS
362 lastReportedSimFPS = reportedFPS;
402 363
403 if (physfps < 0)
404 physfps = 0;
405 364
406#endregion 365#endregion
407
408 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); 366 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount();
409 m_childAgents = m_scene.SceneGraph.GetChildAgentCount(); 367 m_childAgents = m_scene.SceneGraph.GetChildAgentCount();
410 m_numPrim = m_scene.SceneGraph.GetTotalObjectsCount(); 368 m_numPrim = m_scene.SceneGraph.GetTotalObjectsCount();
@@ -413,78 +371,54 @@ namespace OpenSim.Region.Framework.Scenes
413 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount(); 371 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount();
414 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount(); 372 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount();
415 373
374 float physfps = m_pfps;
375 if (physfps < 0)
376 physfps = 0;
377
378 float sparetime;
379 float sleeptime;
380
381 float TotalFrameTime = m_frameMS * perframefactor;
382 sleeptime = m_sleeptimeMS * perframefactor;
383
384 sparetime = m_frameMS - m_sleeptimeMS; // total time minus sleep
385 sparetime *= perframefactor; // average per frame
386 sparetime = TargetFrameTime - sparetime; // real spare
387 if (sparetime < 0)
388 sparetime = 0;
389 else if (sparetime > TotalFrameTime)
390 sparetime = TotalFrameTime;
391
392
393
416 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code 394 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code
417 // so that stat numbers are always consistent. 395 // so that stat numbers are always consistent.
418 CheckStatSanity(); 396 CheckStatSanity();
419 397
420 //Our time dilation is 0.91 when we're running a full speed, 398 // other MS is actually simulation time
421 // therefore to make sure we get an appropriate range, 399 // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS;
422 // we have to factor in our error. (0.10f * statsUpdateFactor) 400 // m_imageMS m_netMS are not included in m_frameMS
423 // multiplies the fix for the error times the amount of times it'll occur a second
424 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
425 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
426
427 // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change
428 // values to X-per-second values.
429
430 uint thisFrame = m_scene.Frame;
431 uint numFrames = thisFrame - m_lastUpdateFrame;
432 float framesUpdated = (float)numFrames * m_reportedFpsCorrectionFactor;
433 m_lastUpdateFrame = thisFrame;
434
435 // Avoid div-by-zero if somehow we've not updated any frames.
436 if (framesUpdated == 0)
437 framesUpdated = 1;
438
439 for (int i = 0; i < m_statisticArraySize; i++)
440 {
441 sb[i] = new SimStatsPacket.StatBlock();
442 }
443 401
444 // Resetting the sums of the frame times to prevent any errors 402 m_otherMS = m_frameMS - m_physicsMS - m_agentMS - m_sleeptimeMS;
445 // in calculating the moving average for frame time 403 if (m_otherMS < 0)
446 totalSumFrameTime = 0; 404 m_otherMS = 0;
447 simulationSumFrameTime = 0;
448 physicsSumFrameTime = 0;
449 networkSumFrameTime = 0;
450 405
451 // Loop through all the frames that were stored for the current 406 for (int i = 0; i < m_statisticViewerArraySize; i++)
452 // heartbeat to process the moving average of frame times
453 for (int i = 0; i < m_numberFramesStored; i++)
454 { 407 {
455 // Sum up each frame time in order to calculate the moving 408 sb[i] = new SimStatsPacket.StatBlock();
456 // average of frame time
457 totalSumFrameTime += m_totalFrameTimeMilliseconds[i];
458 simulationSumFrameTime +=
459 m_simulationFrameTimeMilliseconds[i];
460 physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i];
461 networkSumFrameTime += m_networkFrameTimeMilliseconds[i];
462 } 409 }
463 410
464 // Get the index that represents the current frame based on the next one known; go back
465 // to the last index if next one is stated to restart at 0
466 if (m_nextLocation == 0)
467 currentFrame = m_numberFramesStored - 1;
468 else
469 currentFrame = m_nextLocation - 1;
470
471 // Calculate the frame dilation; which is currently based on the ratio between the sum of the
472 // physics and simulation rate, and the set minimum time to run a scene's frame
473 frameDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] +
474 m_physicsFrameTimeMilliseconds[currentFrame]) / m_scene.MinFrameTicks;
475
476 // ORIGINAL code commented out until we have time to add our own
477 sb[0].StatID = (uint) Stats.TimeDilation; 411 sb[0].StatID = (uint) Stats.TimeDilation;
478 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); 412 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ;
479 413
480 sb[1].StatID = (uint) Stats.SimFPS; 414 sb[1].StatID = (uint) Stats.SimFPS;
481 sb[1].StatValue = reportedFPS / m_statsUpdateFactor; 415 sb[1].StatValue = reportedFPS;
482 416
483 sb[2].StatID = (uint) Stats.PhysicsFPS; 417 sb[2].StatID = (uint) Stats.PhysicsFPS;
484 sb[2].StatValue = physfps / m_statsUpdateFactor; 418 sb[2].StatValue = physfps * updateFactor;
485 419
486 sb[3].StatID = (uint) Stats.AgentUpdates; 420 sb[3].StatID = (uint) Stats.AgentUpdates;
487 sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor); 421 sb[3].StatValue = m_agentUpdates * updateFactor;
488 422
489 sb[4].StatID = (uint) Stats.Agents; 423 sb[4].StatID = (uint) Stats.Agents;
490 sb[4].StatValue = m_rootAgents; 424 sb[4].StatValue = m_rootAgents;
@@ -498,38 +432,32 @@ namespace OpenSim.Region.Framework.Scenes
498 sb[7].StatID = (uint) Stats.ActivePrim; 432 sb[7].StatID = (uint) Stats.ActivePrim;
499 sb[7].StatValue = m_activePrim; 433 sb[7].StatValue = m_activePrim;
500 434
501 // ORIGINAL code commented out until we have time to add our own
502 // statistics to the statistics window
503 sb[8].StatID = (uint)Stats.FrameMS; 435 sb[8].StatID = (uint)Stats.FrameMS;
504 //sb[8].StatValue = m_frameMS / framesUpdated; 436 sb[8].StatValue = TotalFrameTime;
505 sb[8].StatValue = (float) totalSumFrameTime / m_numberFramesStored;
506 437
507 sb[9].StatID = (uint)Stats.NetMS; 438 sb[9].StatID = (uint)Stats.NetMS;
508 //sb[9].StatValue = m_netMS / framesUpdated; 439 sb[9].StatValue = m_netMS * perframefactor;
509 sb[9].StatValue = (float) networkSumFrameTime / m_numberFramesStored;
510 440
511 sb[10].StatID = (uint)Stats.PhysicsMS; 441 sb[10].StatID = (uint)Stats.PhysicsMS;
512 //sb[10].StatValue = m_physicsMS / framesUpdated; 442 sb[10].StatValue = m_physicsMS * perframefactor;
513 sb[10].StatValue = (float) physicsSumFrameTime / m_numberFramesStored;
514 443
515 sb[11].StatID = (uint)Stats.ImageMS ; 444 sb[11].StatID = (uint)Stats.ImageMS ;
516 sb[11].StatValue = m_imageMS / framesUpdated; 445 sb[11].StatValue = m_imageMS * perframefactor;
517 446
518 sb[12].StatID = (uint)Stats.OtherMS; 447 sb[12].StatID = (uint)Stats.OtherMS;
519 //sb[12].StatValue = m_otherMS / framesUpdated; 448 sb[12].StatValue = m_otherMS * perframefactor;
520 sb[12].StatValue = (float) simulationSumFrameTime / m_numberFramesStored;
521 449
522 sb[13].StatID = (uint)Stats.InPacketsPerSecond; 450 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
523 sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); 451 sb[13].StatValue = (m_inPacketsPerSecond * updateFactor);
524 452
525 sb[14].StatID = (uint)Stats.OutPacketsPerSecond; 453 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
526 sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor); 454 sb[14].StatValue = (m_outPacketsPerSecond * updateFactor);
527 455
528 sb[15].StatID = (uint)Stats.UnAckedBytes; 456 sb[15].StatID = (uint)Stats.UnAckedBytes;
529 sb[15].StatValue = m_unAckedBytes; 457 sb[15].StatValue = m_unAckedBytes;
530 458
531 sb[16].StatID = (uint)Stats.AgentMS; 459 sb[16].StatID = (uint)Stats.AgentMS;
532 sb[16].StatValue = m_agentMS / framesUpdated; 460 sb[16].StatValue = m_agentMS * perframefactor;
533 461
534 sb[17].StatID = (uint)Stats.PendingDownloads; 462 sb[17].StatID = (uint)Stats.PendingDownloads;
535 sb[17].StatValue = m_pendingDownloads; 463 sb[17].StatValue = m_pendingDownloads;
@@ -540,75 +468,140 @@ namespace OpenSim.Region.Framework.Scenes
540 sb[19].StatID = (uint)Stats.ActiveScripts; 468 sb[19].StatID = (uint)Stats.ActiveScripts;
541 sb[19].StatValue = m_activeScripts; 469 sb[19].StatValue = m_activeScripts;
542 470
543 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; 471 sb[20].StatID = (uint)Stats.SimSleepMs;
544 sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor; 472 sb[20].StatValue = sleeptime;
545 473
546 sb[21].StatID = (uint)Stats.SimSpareMs; 474 sb[21].StatID = (uint)Stats.SimSpareMs;
547 sb[21].StatValue = m_spareMS / framesUpdated; 475 sb[21].StatValue = sparetime;
548 476
549 // Current ratio between the sum of physics and sim rate, and the 477 // this should came from phys engine
550 // minimum time to run a scene's frame 478 sb[22].StatID = (uint)Stats.SimPhysicsStepMs;
551 sb[22].StatID = (uint)Stats.FrameDilation; 479 sb[22].StatValue = 20;
552 sb[22].StatValue = frameDilation;
553 480
554 // Current number of users currently attemptint to login to region 481 // send the ones we dont have as zeros, to clean viewers state
555 sb[23].StatID = (uint)Stats.UsersLoggingIn; 482 // specially arriving from regions with wrond IDs in use
556 sb[23].StatValue = m_usersLoggingIn;
557 483
558 // Total number of geometric primitives in the scene 484 sb[23].StatID = (uint)Stats.VirtualSizeKb;
559 sb[24].StatID = (uint)Stats.TotalGeoPrim; 485 sb[23].StatValue = 0;
560 sb[24].StatValue = m_numGeoPrim;
561 486
562 // Total number of mesh objects in the scene 487 sb[24].StatID = (uint)Stats.ResidentSizeKb;
563 sb[25].StatID = (uint)Stats.TotalMesh; 488 sb[24].StatValue = 0;
564 sb[25].StatValue = m_numMesh; 489
490 sb[25].StatID = (uint)Stats.PendingLocalUploads;
491 sb[25].StatValue = 0;
492
493 sb[26].StatID = (uint)Stats.PhysicsPinnedTasks;
494 sb[26].StatValue = 0;
495
496 sb[27].StatID = (uint)Stats.PhysicsLodTasks;
497 sb[27].StatValue = 0;
498
499 sb[28].StatID = (uint)Stats.ScriptEps; // we should have this
500 sb[28].StatValue = 0;
501
502 sb[29].StatID = (uint)Stats.SimAIStepTimeMS;
503 sb[29].StatValue = 0;
504
505 sb[30].StatID = (uint)Stats.SimIoPumpTime;
506 sb[30].StatValue = 0;
507
508 sb[31].StatID = (uint)Stats.SimPCTSscriptsRun;
509 sb[31].StatValue = 0;
510
511 sb[32].StatID = (uint)Stats.SimRegionIdle;
512 sb[32].StatValue = 0;
513
514 sb[33].StatID = (uint)Stats.SimRegionIdlePossible;
515 sb[33].StatValue = 0;
516
517 sb[34].StatID = (uint)Stats.SimSkippedSillouet_PS;
518 sb[34].StatValue = 0;
565 519
566 // Current number of threads that XEngine is using 520 sb[35].StatID = (uint)Stats.SimSkippedCharsPerC;
567 sb[26].StatID = (uint)Stats.ThreadCount; 521 sb[35].StatValue = 0;
568 sb[26].StatValue = m_inUseThreads;
569 522
570 sb[27].StatID = (uint)Stats.ScriptMS; 523 sb[36].StatID = (uint)Stats.SimPhysicsMemory;
571 sb[27].StatValue = (numFrames <= 0) ? 0 : ((float)m_scriptMS / numFrames); 524 sb[36].StatValue = 0;
572 525
573 for (int i = 0; i < m_statisticArraySize; i++) 526 sb[37].StatID = (uint)Stats.ScriptMS;
527 sb[37].StatValue = 0;
528
529
530 for (int i = 0; i < m_statisticViewerArraySize; i++)
574 { 531 {
575 lastReportedSimStats[i] = sb[i].StatValue; 532 lastReportedSimStats[i] = sb[i].StatValue;
576 } 533 }
577 534
535
536 // add extra stats for internal use
537
538 for (int i = 0; i < m_statisticExtraArraySize; i++)
539 {
540 sbex[i] = new SimStatsPacket.StatBlock();
541 }
542
543 sbex[0].StatID = (uint)Stats.LSLScriptLinesPerSecond;
544 sbex[0].StatValue = m_scriptLinesPerSecond * updateFactor;
545 lastReportedSimStats[38] = m_scriptLinesPerSecond * updateFactor;
546
547 sbex[1].StatID = (uint)Stats.FrameDilation2;
548 sbex[1].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation;
549 lastReportedSimStats[39] = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation;
550
551 sbex[2].StatID = (uint)Stats.UsersLoggingIn;
552 sbex[2].StatValue = m_usersLoggingIn;
553 lastReportedSimStats[40] = m_usersLoggingIn;
554
555 sbex[3].StatID = (uint)Stats.TotalGeoPrim;
556 sbex[3].StatValue = m_numGeoPrim;
557 lastReportedSimStats[41] = m_numGeoPrim;
558
559 sbex[4].StatID = (uint)Stats.TotalMesh;
560 sbex[4].StatValue = m_numMesh;
561 lastReportedSimStats[42] = m_numMesh;
562
563 sbex[5].StatID = (uint)Stats.ThreadCount;
564 sbex[5].StatValue = m_inUseThreads;
565 lastReportedSimStats[43] = m_inUseThreads;
566
578 SimStats simStats 567 SimStats simStats
579 = new SimStats( 568 = new SimStats(
580 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, 569 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity,
581 rb, sb, m_scene.RegionInfo.originRegionID); 570 rb, sb, sbex, m_scene.RegionInfo.originRegionID);
582 571
583 handlerSendStatResult = OnSendStatsResult; 572 handlerSendStatResult = OnSendStatsResult;
584 if (handlerSendStatResult != null) 573 if (handlerSendStatResult != null)
585 { 574 {
586 handlerSendStatResult(simStats); 575 handlerSendStatResult(simStats);
587 } 576 }
588 577
589 // Extra statistics that aren't currently sent to clients 578 // Extra statistics that aren't currently sent to clients
590 lock (m_lastReportedExtraSimStats) 579 if (m_scene.PhysicsScene != null)
591 { 580 {
592 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 581 lock (m_lastReportedExtraSimStats)
593 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
594
595 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
596
597 if (physicsStats != null)
598 { 582 {
599 foreach (KeyValuePair<string, float> tuple in physicsStats) 583 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates * updateFactor;
584 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
585
586 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
587
588 if (physicsStats != null)
600 { 589 {
601 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second 590 foreach (KeyValuePair<string, float> tuple in physicsStats)
602 // Need to change things so that stats source can indicate whether they are per second or 591 {
603 // per frame. 592 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second
604 if (tuple.Key.EndsWith("MS")) 593 // Need to change things so that stats source can indicate whether they are per second or
605 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated; 594 // per frame.
606 else 595 if (tuple.Key.EndsWith("MS"))
607 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor; 596 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * perframefactor;
597 else
598 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * updateFactor;
599 }
608 } 600 }
609 } 601 }
610 } 602 }
611 603
604// LastReportedObjectUpdates = m_objectUpdates / m_statsUpdateFactor;
612 ResetValues(); 605 ResetValues();
613 } 606 }
614 } 607 }
@@ -617,7 +610,6 @@ namespace OpenSim.Region.Framework.Scenes
617 { 610 {
618 // Reset the number of frames that the physics library has 611 // Reset the number of frames that the physics library has
619 // processed since the last stats report 612 // processed since the last stats report
620 m_numberPhysicsFrames = 0;
621 613
622 m_timeDilation = 0; 614 m_timeDilation = 0;
623 m_fps = 0; 615 m_fps = 0;
@@ -635,8 +627,10 @@ namespace OpenSim.Region.Framework.Scenes
635 m_physicsMS = 0; 627 m_physicsMS = 0;
636 m_imageMS = 0; 628 m_imageMS = 0;
637 m_otherMS = 0; 629 m_otherMS = 0;
638 m_scriptMS = 0; 630 m_sleeptimeMS = 0;
639 m_spareMS = 0; 631
632//Ckrinke This variable is not used, so comment to remove compiler warning until it is used.
633//Ckrinke m_scriptMS = 0;
640 } 634 }
641 635
642 # region methods called from Scene 636 # region methods called from Scene
@@ -707,7 +701,7 @@ namespace OpenSim.Region.Framework.Scenes
707 if (m_unAckedBytes < 0) m_unAckedBytes = 0; 701 if (m_unAckedBytes < 0) m_unAckedBytes = 0;
708 } 702 }
709 703
710 public void addFrameMS(int ms) 704 public void addFrameMS(float ms)
711 { 705 {
712 m_frameMS += ms; 706 m_frameMS += ms;
713 707
@@ -717,65 +711,34 @@ namespace OpenSim.Region.Framework.Scenes
717 SlowFramesStat.Value++; 711 SlowFramesStat.Value++;
718 } 712 }
719 713
720 public void AddSpareMS(int ms) 714 public void addNetMS(float ms)
721 {
722 m_spareMS += ms;
723 }
724
725 public void addNetMS(int ms)
726 { 715 {
727 m_netMS += ms; 716 m_netMS += ms;
728 } 717 }
729 718
730 public void addAgentMS(int ms) 719 public void addAgentMS(float ms)
731 { 720 {
732 m_agentMS += ms; 721 m_agentMS += ms;
733 } 722 }
734 723
735 public void addPhysicsMS(int ms) 724 public void addPhysicsMS(float ms)
736 { 725 {
737 m_physicsMS += ms; 726 m_physicsMS += ms;
738 } 727 }
739 728
740 public void addImageMS(int ms) 729 public void addImageMS(float ms)
741 { 730 {
742 m_imageMS += ms; 731 m_imageMS += ms;
743 } 732 }
744 733
745 public void addOtherMS(int ms) 734 public void addOtherMS(float ms)
746 { 735 {
747 m_otherMS += ms; 736 m_otherMS += ms;
748 } 737 }
749 738
750 public void AddScriptMS(int ms) 739 public void addSleepMS(float ms)
751 {
752 m_scriptMS += ms;
753 }
754
755 public void addPhysicsFrame(int frames)
756 {
757 // Add the number of physics frames to the correct total physics
758 // frames
759 m_numberPhysicsFrames += frames;
760 }
761
762 public void addFrameTimeMilliseconds(double total, double simulation,
763 double physics, double network)
764 { 740 {
765 // Save the frame times from the current frame into the appropriate 741 m_sleeptimeMS += ms;
766 // arrays
767 m_totalFrameTimeMilliseconds[m_nextLocation] = total;
768 m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation;
769 m_physicsFrameTimeMilliseconds[m_nextLocation] = physics;
770 m_networkFrameTimeMilliseconds[m_nextLocation] = network;
771
772 // Update to the next location in the list
773 m_nextLocation++;
774
775 // Since the list will begin to overwrite the oldest frame values
776 // first, the next location needs to loop back to the beginning of the
777 // list whenever it reaches the end
778 m_nextLocation = m_nextLocation % m_numberFramesStored;
779 } 742 }
780 743
781 public void AddPendingDownloads(int count) 744 public void AddPendingDownloads(int count)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index 3d563a6..506ad24 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.Framework.Scenes
57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension 57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension 58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
59 59
60
60 // Default, not-often-used builder 61 // Default, not-often-used builder
61 public TerrainChannel() 62 public TerrainChannel()
62 { 63 {
@@ -157,7 +158,11 @@ namespace OpenSim.Region.Framework.Scenes
157 { 158 {
158 if (Double.IsNaN(value) || Double.IsInfinity(value)) 159 if (Double.IsNaN(value) || Double.IsInfinity(value))
159 return; 160 return;
160 161 if (value < 0)
162 value = 0;
163 else
164 if (value > 655.35)
165 value = 655.35;
161 m_terrainData[x, y] = (float)value; 166 m_terrainData[x, y] = (float)value;
162 } 167 }
163 } 168 }
@@ -363,8 +368,8 @@ namespace OpenSim.Region.Framework.Scenes
363 public int SizeY; 368 public int SizeY;
364 public int SizeZ; 369 public int SizeZ;
365 public float CompressionFactor; 370 public float CompressionFactor;
366 public int[] Map; 371 public float[] Map;
367 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap) 372 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, float[] pMap)
368 { 373 {
369 Version = 1; 374 Version = 1;
370 SizeX = pX; 375 SizeX = pX;
@@ -395,17 +400,22 @@ namespace OpenSim.Region.Framework.Scenes
395 // Fill the heightmap with the center bump terrain 400 // Fill the heightmap with the center bump terrain
396 private void PinHeadIsland() 401 private void PinHeadIsland()
397 { 402 {
403 float cx = m_terrainData.SizeX * 0.5f;
404 float cy = m_terrainData.SizeY * 0.5f;
405 float h;
398 for (int x = 0; x < Width; x++) 406 for (int x = 0; x < Width; x++)
399 { 407 {
400 for (int y = 0; y < Height; y++) 408 for (int y = 0; y < Height; y++)
401 { 409 {
402 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 410 // h = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
403 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d); 411 h = 1.0f;
404 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d); 412 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 50) * 0.01d);
405 if (m_terrainData[x, y]< spherFacA) 413 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 100) * 0.001d);
406 m_terrainData[x, y]= spherFacA; 414 if (h < spherFacA)
407 if (m_terrainData[x, y]< spherFacB) 415 h = spherFacA;
408 m_terrainData[x, y] = spherFacB; 416 if (h < spherFacB)
417 h = spherFacB;
418 m_terrainData[x, y] = h;
409 } 419 }
410 } 420 }
411 } 421 }
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
index 0b196c1..dc3b717 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
@@ -42,6 +42,7 @@ using OpenSim.Tests.Common;
42 42
43namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
44{ 44{
45 /*
45 /// <summary> 46 /// <summary>
46 /// Test copying of scene objects. 47 /// Test copying of scene objects.
47 /// </summary> 48 /// </summary>
@@ -343,4 +344,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
343 } 344 }
344 } 345 }
345 } 346 }
347 */
346} \ No newline at end of file 348} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 1c396ac..f980209 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -81,8 +81,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
81 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 81 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
82 82
83 TestScene scene = new SceneHelpers().SetupScene(); 83 TestScene scene = new SceneHelpers().SetupScene();
84 SceneHelpers.SetupSceneModules(scene, new PermissionsModule()); 84 IConfigSource configSource = new IniConfigSource();
85 TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 85 IConfig config = configSource.AddConfig("Startup");
86 config.Set("serverside_object_permissions", true);
87 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
88 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
86 89
87 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 90 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
88 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 91 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
@@ -104,9 +107,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
104 107
105 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 108 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
106 Assert.That(retrievedPart2, Is.Null); 109 Assert.That(retrievedPart2, Is.Null);
107
108 Assert.That(client.ReceivedKills.Count, Is.EqualTo(1));
109 Assert.That(client.ReceivedKills[0], Is.EqualTo(soLocalId));
110 } 110 }
111 111
112 /// <summary> 112 /// <summary>
@@ -133,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 133 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
134 134
135 // We need this for derez 135 // We need this for derez
136 SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule()); 136 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
137 137
138 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, ""); 138 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
139 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, ""); 139 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
@@ -153,12 +153,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
153 uint soLocalId = so.LocalId; 153 uint soLocalId = so.LocalId;
154 154
155 sceneA.DeleteSceneObject(so, false); 155 sceneA.DeleteSceneObject(so, false);
156
157 Assert.That(clientA.ReceivedKills.Count, Is.EqualTo(1));
158 Assert.That(clientA.ReceivedKills[0], Is.EqualTo(soLocalId));
159
160 Assert.That(childClientsB[0].ReceivedKills.Count, Is.EqualTo(1));
161 Assert.That(childClientsB[0].ReceivedKills[0], Is.EqualTo(soLocalId));
162 } 156 }
163 157
164 /// <summary> 158 /// <summary>
@@ -177,7 +171,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
177 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001"); 171 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001");
178 172
179 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
180 SceneHelpers.SetupSceneModules(scene, new PermissionsModule()); 174 IConfigSource configSource = new IniConfigSource();
175 IConfig config = configSource.AddConfig("Startup");
176 config.Set("serverside_object_permissions", true);
177 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
181 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 178 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
182 179
183 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 180 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
@@ -260,4 +257,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
260// Assert.That(retrievedPart, Is.Null); 257// Assert.That(retrievedPart, Is.Null);
261 } 258 }
262 } 259 }
263} \ No newline at end of file 260}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index 975c4d9..9a665f6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -60,6 +60,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
60 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); 60 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2));
61 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); 61 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3));
62 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); 62 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4));
63
64 Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1));
63 } 65 }
64 66
65 /// <summary> 67 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
index aadf7c6..a92e364 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common;
42namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectUserGroupTests : OpenSimTestCase 45 public class SceneObjectUserGroupTests
46 { 46 {
47 /// <summary> 47 /// <summary>
48 /// Test share with group object functionality 48 /// Test share with group object functionality
@@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 public void TestShareWithGroup() 52 public void TestShareWithGroup()
53 { 53 {
54 TestHelpers.InMethod(); 54 TestHelpers.InMethod();
55// log4net.Config.XmlConfigurator.Configure();
55 56
56 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 57 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
57 58
@@ -68,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
68 69
69 SceneHelpers.SetupSceneModules( 70 SceneHelpers.SetupSceneModules(
70 scene, configSource, new object[] 71 scene, configSource, new object[]
71 { new PermissionsModule(), 72 { new DefaultPermissionsModule(),
72 new GroupsModule(), 73 new GroupsModule(),
73 new MockGroupsServicesConnector() }); 74 new MockGroupsServicesConnector() });
74 75
@@ -79,4 +80,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
79 groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true); 80 groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true);
80 } 81 }
81 } 82 }
82} \ No newline at end of file 83}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
index 2e6dc70..aa26767 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -73,14 +73,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 SceneHelpers.SetupSceneModules(scene, capsMod); 73 SceneHelpers.SetupSceneModules(scene, capsMod);
74 74
75 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid); 75 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
76 Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null); 76 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
77 77
78 // TODO: Need to add tests for other ICapabiltiesModule methods. 78 // TODO: Need to add tests for other ICapabiltiesModule methods.
79 79
80// scene.IncomingCloseAgent(sp.UUID, false);
81// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
80 scene.CloseAgent(sp.UUID, false); 82 scene.CloseAgent(sp.UUID, false);
81 Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null); 83// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
82 84
83 // TODO: Need to add tests for other ICapabiltiesModule methods. 85 // TODO: Need to add tests for other ICapabiltiesModule methods.
84 } 86 }
85 } 87 }
86} \ No newline at end of file 88}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 7127644..37eec52 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -190,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
190 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 190 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
191 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 191 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
192 // IsAdministrator if no permissions module is present is true. 192 // IsAdministrator if no permissions module is present is true.
193 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB); 193// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
194 194
195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
196 TestClient tc = new TestClient(acd, sceneA); 196 TestClient tc = new TestClient(acd, sceneA);
@@ -244,4 +244,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); 244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
245 } 245 }
246 } 246 }
247} \ No newline at end of file 247}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index b232a44..64f11cd 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -98,9 +98,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
98 98
99 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 99 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
100 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 100 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
101 HashSet<ScenePresence> sittingAvatars = part.GetSittingAvatars(); 101 HashSet<UUID> sittingAvatars = part.GetSittingAvatars();
102 Assert.That(sittingAvatars.Count, Is.EqualTo(1)); 102 Assert.That(sittingAvatars.Count, Is.EqualTo(1));
103 Assert.That(sittingAvatars.Contains(m_sp)); 103 Assert.That(sittingAvatars.Contains(m_sp.UUID));
104 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 104 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
105 } 105 }
106 106
@@ -210,9 +210,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
210 Assert.That(m_sp.PhysicsActor, Is.Null); 210 Assert.That(m_sp.PhysicsActor, Is.Null);
211 211
212 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 212 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
213 HashSet<ScenePresence> sittingAvatars = part.GetSittingAvatars(); 213 HashSet<UUID> sittingAvatars = part.GetSittingAvatars();
214 Assert.That(sittingAvatars.Count, Is.EqualTo(1)); 214 Assert.That(sittingAvatars.Count, Is.EqualTo(1));
215 Assert.That(sittingAvatars.Contains(m_sp)); 215 Assert.That(sittingAvatars.Contains(m_sp.UUID));
216 216
217 m_sp.StandUp(); 217 m_sp.StandUp();
218 218
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index bacfc17..226ed6e 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -280,7 +280,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
280 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 280 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
281 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 281 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
282 // IsAdministrator if no permissions module is present is true. 282 // IsAdministrator if no permissions module is present is true.
283 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 283 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
284 284
285 // Shared scene modules 285 // Shared scene modules
286 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 286 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
@@ -445,7 +445,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
445 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 445 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
446 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 446 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
447 // IsAdministrator if no permissions module is present is true. 447 // IsAdministrator if no permissions module is present is true.
448 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 448 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
449 449
450 // Shared scene modules 450 // Shared scene modules
451 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 451 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
@@ -658,4 +658,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
658// TestHelpers.DisableLogging(); 658// TestHelpers.DisableLogging();
659 } 659 }
660 } 660 }
661} \ No newline at end of file 661}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index b01088d..33a630c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Tests
95 Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f); 95 Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f);
96 Vector3 rezVel = new Vector3(2, 2, 2); 96 Vector3 rezVel = new Vector3(2, 2, 2);
97 97
98 scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0); 98 scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0,false);
99 99
100 SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso"); 100 SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso");
101 101
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..7bbf1bd 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,202 +27,307 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic;
30using log4net; 31using log4net;
31using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
33 35
34namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
35{ 37{
36 public class UndoState 38 public class UndoState
37 { 39 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
39
40 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero;
42 public Quaternion Rotation = Quaternion.Identity;
43
44 /// <summary>
45 /// Is this undo state for an entire group?
46 /// </summary>
47 public bool ForGroup;
48 41
42 public ObjectChangeData data;
43 public DateTime creationtime;
49 /// <summary> 44 /// <summary>
50 /// Constructor. 45 /// Constructor.
51 /// </summary> 46 /// </summary>
52 /// <param name="part"></param> 47 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param> 48 /// <param name="change">bit field with what is changed</param>
54 public UndoState(SceneObjectPart part, bool forGroup) 49 ///
50 public UndoState(SceneObjectPart part, ObjectChangeType change)
55 { 51 {
56 if (part.ParentID == 0) 52 data = new ObjectChangeData();
57 { 53 data.change = change;
58 ForGroup = forGroup; 54 creationtime = DateTime.UtcNow;
59
60// if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition;
62// else
63// Position = part.OffsetPosition;
64
65// m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 55
68 Rotation = part.RotationOffset; 56 if (part.ParentGroup.RootPart == part)
69 57 {
70// m_log.DebugFormat( 58 if ((change & ObjectChangeType.Position) != 0)
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 59 data.position = part.ParentGroup.AbsolutePosition;
72 60 if ((change & ObjectChangeType.Rotation) != 0)
73 Scale = part.Shape.Scale; 61 data.rotation = part.RotationOffset;
74 62 if ((change & ObjectChangeType.Scale) != 0)
75// m_log.DebugFormat( 63 data.scale = part.Shape.Scale;
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 64 }
78 else 65 else
79 { 66 {
80 Position = part.OffsetPosition; 67 if ((change & ObjectChangeType.Position) != 0)
81// m_log.DebugFormat( 68 data.position = part.OffsetPosition;
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 69 if ((change & ObjectChangeType.Rotation) != 0)
70 data.rotation = part.RotationOffset;
71 if ((change & ObjectChangeType.Scale) != 0)
72 data.scale = part.Shape.Scale;
73 }
74 }
75 /// <summary>
76 /// check if undo or redo is too old
77 /// </summary>
83 78
84 Rotation = part.RotationOffset; 79 public bool checkExpire()
85// m_log.DebugFormat( 80 {
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 81 TimeSpan t = DateTime.UtcNow - creationtime;
82 if (t.Seconds > UNDOEXPIRESECONDS)
83 return true;
84 return false;
85 }
87 86
88 Scale = part.Shape.Scale; 87 /// <summary>
89// m_log.DebugFormat( 88 /// updates undo or redo creation time to now
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 89 /// </summary>
91 } 90 public void updateExpire()
91 {
92 creationtime = DateTime.UtcNow;
92 } 93 }
93 94
94 /// <summary> 95 /// <summary>
95 /// Compare the relevant state in the given part to this state. 96 /// Compare the relevant state in the given part to this state.
96 /// </summary> 97 /// </summary>
97 /// <param name="part"></param> 98 /// <param name="part"></param>
98 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns> 99 /// <returns>true what fiels and related data are equal, False otherwise.</returns>
99 public bool Compare(SceneObjectPart part) 100 ///
101 public bool Compare(SceneObjectPart part, ObjectChangeType change)
100 { 102 {
103 if (data.change != change) // if diferent targets, then they are diferent
104 return false;
105
101 if (part != null) 106 if (part != null)
102 { 107 {
103 if (part.ParentID == 0) 108 if (part.ParentID == 0)
104 return 109 {
105 Position == part.ParentGroup.AbsolutePosition 110 if ((change & ObjectChangeType.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition)
106 && Rotation == part.RotationOffset 111 return false;
107 && Scale == part.Shape.Scale; 112 }
108 else 113 else
109 return 114 {
110 Position == part.OffsetPosition 115 if ((change & ObjectChangeType.Position) != 0 && data.position != part.OffsetPosition)
111 && Rotation == part.RotationOffset 116 return false;
112 && Scale == part.Shape.Scale; 117 }
113 } 118
119 if ((change & ObjectChangeType.Rotation) != 0 && data.rotation != part.RotationOffset)
120 return false;
121 if ((change & ObjectChangeType.Rotation) != 0 && data.scale == part.Shape.Scale)
122 return false;
123 return true;
114 124
125 }
115 return false; 126 return false;
116 } 127 }
117 128
118 public void PlaybackState(SceneObjectPart part) 129 /// <summary>
130 /// executes the undo or redo to a part or its group
131 /// </summary>
132 /// <param name="part"></param>
133 ///
134
135 public void PlayState(SceneObjectPart part)
119 { 136 {
120 part.Undoing = true; 137 part.Undoing = true;
121 138
122 if (part.ParentID == 0) 139 SceneObjectGroup grp = part.ParentGroup;
123 {
124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
127 140
128 if (Position != Vector3.Zero) 141 if (grp != null)
129 { 142 {
130 if (ForGroup) 143 grp.doChangeObject(part, data);
131 part.ParentGroup.AbsolutePosition = Position; 144 }
132 else 145 part.Undoing = false;
133 part.ParentGroup.UpdateRootPosition(Position); 146 }
134 } 147 }
135 148
136// m_log.DebugFormat( 149 public class UndoRedoState
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 150 {
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 151 int size;
152 public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
153 public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
139 154
140 if (ForGroup) 155 /// <summary>
141 part.UpdateRotation(Rotation); 156 /// creates a new UndoRedoState with default states memory size
142 else 157 /// </summary>
143 part.ParentGroup.UpdateRootRotation(Rotation);
144 158
145 if (Scale != Vector3.Zero) 159 public UndoRedoState()
146 { 160 {
147// m_log.DebugFormat( 161 size = 5;
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 162 }
149// part.Shape.Scale, Scale, part.Name, part.LocalId);
150 163
151 if (ForGroup) 164 /// <summary>
152 part.ParentGroup.GroupResize(Scale); 165 /// creates a new UndoRedoState with states memory having indicated size
153 else 166 /// </summary>
154 part.Resize(Scale); 167 /// <param name="size"></param>
155 }
156 168
157 part.ParentGroup.ScheduleGroupForTerseUpdate(); 169 public UndoRedoState(int _size)
158 } 170 {
171 if (_size < 3)
172 size = 3;
159 else 173 else
160 { 174 size = _size;
161 // Note: Updating these properties on sop automatically schedules an update if needed 175 }
162 if (Position != Vector3.Zero)
163 {
164// m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId);
167 176
168 part.OffsetPosition = Position; 177 /// <summary>
169 } 178 /// returns number of undo entries in memory
179 /// </summary>
170 180
171// m_log.DebugFormat( 181 public int Count
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 182 {
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 183 get { return m_undo.Count; }
184 }
174 185
175 part.UpdateRotation(Rotation); 186 /// <summary>
187 /// clears all undo and redo entries
188 /// </summary>
176 189
177 if (Scale != Vector3.Zero) 190 public void Clear()
191 {
192 m_undo.Clear();
193 m_redo.Clear();
194 }
195
196 /// <summary>
197 /// adds a new state undo to part or its group, with changes indicated by what bits
198 /// </summary>
199 /// <param name="part"></param>
200 /// <param name="change">bit field with what is changed</param>
201
202 public void StoreUndo(SceneObjectPart part, ObjectChangeType change)
203 {
204 lock (m_undo)
205 {
206 UndoState last;
207
208 if (m_redo.Count > 0) // last code seems to clear redo on every new undo
178 { 209 {
179// m_log.DebugFormat( 210 m_redo.Clear();
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 211 }
181// part.Shape.Scale, Scale, part.Name, part.LocalId);
182 212
183 part.Resize(Scale); 213 if (m_undo.Count > 0)
214 {
215 // check expired entry
216 last = m_undo.First.Value;
217 if (last != null && last.checkExpire())
218 m_undo.Clear();
219 else
220 {
221 // see if we actually have a change
222 if (last != null)
223 {
224 if (last.Compare(part, change))
225 return;
226 }
227 }
184 } 228 }
185 }
186 229
187 part.Undoing = false; 230 // limite size
231 while (m_undo.Count >= size)
232 m_undo.RemoveLast();
233
234 UndoState nUndo = new UndoState(part, change);
235 m_undo.AddFirst(nUndo);
236 }
188 } 237 }
189 238
190 public void PlayfwdState(SceneObjectPart part) 239 /// <summary>
191 { 240 /// executes last state undo to part or its group
192 part.Undoing = true; 241 /// current state is pushed into redo
242 /// </summary>
243 /// <param name="part"></param>
193 244
194 if (part.ParentID == 0) 245 public void Undo(SceneObjectPart part)
246 {
247 lock (m_undo)
195 { 248 {
196 if (Position != Vector3.Zero) 249 UndoState nUndo;
197 part.ParentGroup.AbsolutePosition = Position;
198
199 if (Rotation != Quaternion.Identity)
200 part.UpdateRotation(Rotation);
201 250
202 if (Scale != Vector3.Zero) 251 // expire redo
252 if (m_redo.Count > 0)
203 { 253 {
204 if (ForGroup) 254 nUndo = m_redo.First.Value;
205 part.ParentGroup.GroupResize(Scale); 255 if (nUndo != null && nUndo.checkExpire())
206 else 256 m_redo.Clear();
207 part.Resize(Scale);
208 } 257 }
209 258
210 part.ParentGroup.ScheduleGroupForTerseUpdate(); 259 if (m_undo.Count > 0)
260 {
261 UndoState goback = m_undo.First.Value;
262 // check expired
263 if (goback != null && goback.checkExpire())
264 {
265 m_undo.Clear();
266 return;
267 }
268
269 if (goback != null)
270 {
271 m_undo.RemoveFirst();
272
273 // redo limite size
274 while (m_redo.Count >= size)
275 m_redo.RemoveLast();
276
277 nUndo = new UndoState(part, goback.data.change); // new value in part should it be full goback copy?
278 m_redo.AddFirst(nUndo);
279
280 goback.PlayState(part);
281 }
282 }
211 } 283 }
212 else 284 }
285
286 /// <summary>
287 /// executes last state redo to part or its group
288 /// current state is pushed into undo
289 /// </summary>
290 /// <param name="part"></param>
291
292 public void Redo(SceneObjectPart part)
293 {
294 lock (m_undo)
213 { 295 {
214 // Note: Updating these properties on sop automatically schedules an update if needed 296 UndoState nUndo;
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217 297
218 if (Rotation != Quaternion.Identity) 298 // expire undo
219 part.UpdateRotation(Rotation); 299 if (m_undo.Count > 0)
300 {
301 nUndo = m_undo.First.Value;
302 if (nUndo != null && nUndo.checkExpire())
303 m_undo.Clear();
304 }
220 305
221 if (Scale != Vector3.Zero) 306 if (m_redo.Count > 0)
222 part.Resize(Scale); 307 {
308 UndoState gofwd = m_redo.First.Value;
309 // check expired
310 if (gofwd != null && gofwd.checkExpire())
311 {
312 m_redo.Clear();
313 return;
314 }
315
316 if (gofwd != null)
317 {
318 m_redo.RemoveFirst();
319
320 // limite undo size
321 while (m_undo.Count >= size)
322 m_undo.RemoveLast();
323
324 nUndo = new UndoState(part, gofwd.data.change); // new value in part should it be full gofwd copy?
325 m_undo.AddFirst(nUndo);
326
327 gofwd.PlayState(part);
328 }
329 }
223 } 330 }
224
225 part.Undoing = false;
226 } 331 }
227 } 332 }
228 333
@@ -247,4 +352,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 352 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 353 }
249 } 354 }
250} \ No newline at end of file 355}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 9ec4e1d..d8928ee 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -126,7 +126,6 @@ namespace OpenSim.Region.Framework.Scenes
126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); 126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid);
127 127
128 m_assetUuidsToInspect.Enqueue(uuid); 128 m_assetUuidsToInspect.Enqueue(uuid);
129
130 return true; 129 return true;
131 } 130 }
132 131